From 3ade2b375d3e928a06a39bb5ce48e59ea054f9c8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 12 Sep 2024 06:45:08 +0200 Subject: Merging upstream version 3.4.0. Signed-off-by: Daniel Baumann --- Doxyfile.in | 394 ++- Makefile.in | 5 +- NEWS | 142 + README.md | 3 +- configure | 1192 +++----- configure.ac | 201 +- distro/Makefile.in | 5 +- distro/config/apkg.toml | 8 - distro/pkg/deb-nolibxdp/control | 15 +- distro/pkg/deb-nolibxdp/knot.install | 1 - distro/pkg/deb-nolibxdp/libknot14.install | 1 - distro/pkg/deb-nolibxdp/libknot14.symbols | 277 -- distro/pkg/deb-nolibxdp/libknot15.install | 1 + distro/pkg/deb-nolibxdp/libknot15.symbols | 290 ++ distro/pkg/deb-nolibxdp/rules | 6 +- distro/pkg/deb-nolibxdp/ufw/knot | 4 - distro/pkg/deb-noxdp/changelog | 6 - distro/pkg/deb-noxdp/clean | 2 - distro/pkg/deb-noxdp/compat | 1 - distro/pkg/deb-noxdp/control | 288 -- distro/pkg/deb-noxdp/copyright | 179 -- distro/pkg/deb-noxdp/cz.nic.knotd.conf | 9 - distro/pkg/deb-noxdp/docs | 1 - distro/pkg/deb-noxdp/knot-dnssecutils.install | 3 - distro/pkg/deb-noxdp/knot-dnssecutils.manpages | 3 - distro/pkg/deb-noxdp/knot-dnsutils.install | 2 - distro/pkg/deb-noxdp/knot-dnsutils.manpages | 2 - distro/pkg/deb-noxdp/knot-doc.install | 1 - distro/pkg/deb-noxdp/knot-doc.links | 5 - distro/pkg/deb-noxdp/knot-exporter.install | 3 - distro/pkg/deb-noxdp/knot-host.install | 1 - distro/pkg/deb-noxdp/knot-host.manpages | 1 - distro/pkg/deb-noxdp/knot-module-dnstap.install | 1 - distro/pkg/deb-noxdp/knot-module-geoip.install | 1 - distro/pkg/deb-noxdp/knot.dirs | 1 - distro/pkg/deb-noxdp/knot.init | 149 - distro/pkg/deb-noxdp/knot.install | 8 - distro/pkg/deb-noxdp/knot.manpages | 6 - distro/pkg/deb-noxdp/knot.postinst | 16 - distro/pkg/deb-noxdp/knot.postrm | 21 - distro/pkg/deb-noxdp/knot.service | 30 - distro/pkg/deb-noxdp/libdnssec9.install | 1 - distro/pkg/deb-noxdp/libdnssec9.symbols | 96 - distro/pkg/deb-noxdp/libknot-dev.install | 3 - distro/pkg/deb-noxdp/libknot14.install | 1 - distro/pkg/deb-noxdp/libknot14.symbols | 226 -- distro/pkg/deb-noxdp/libzscanner4.install | 1 - distro/pkg/deb-noxdp/libzscanner4.symbols | 12 - distro/pkg/deb-noxdp/not-installed | 1 - .../patches/05-revert-mod-dnstap-TCP-sink.patch | 160 -- distro/pkg/deb-noxdp/patches/series | 1 - distro/pkg/deb-noxdp/prepare-environment | 38 - distro/pkg/deb-noxdp/python3-libknot.install | 2 - distro/pkg/deb-noxdp/rules | 95 - distro/pkg/deb-noxdp/source/format | 1 - distro/pkg/deb-noxdp/tests/authoritative-server | 150 - distro/pkg/deb-noxdp/tests/control | 13 - distro/pkg/deb-noxdp/tests/kdig | 14 - distro/pkg/deb-noxdp/ufw/knot | 4 - distro/pkg/deb-noxdp/watch | 4 - distro/pkg/deb/control | 14 +- distro/pkg/deb/knot.install | 1 - distro/pkg/deb/libknot14.install | 1 - distro/pkg/deb/libknot14.symbols | 277 -- distro/pkg/deb/libknot15.install | 1 + distro/pkg/deb/libknot15.symbols | 290 ++ distro/pkg/deb/rules | 6 +- distro/pkg/deb/ufw/knot | 4 - distro/pkg/el-7/01-revert-AC_PROG_CC.patch | 18 - .../el-7/02-fix-compilation-by-using-SHA-1.patch | 67 - .../03-doc-don-t-try-to-import-sphinx_panels.patch | 25 - ...4-revert-don-t-share-PKCS-11-private-keys.patch | 160 -- .../pkg/el-7/05-revert-mod-dnstap-TCP-sink.patch | 160 -- distro/pkg/el-7/knot.service | 25 - distro/pkg/el-7/knot.spec | 334 --- distro/pkg/el-7/knot.tmpfiles | 3 - distro/pkg/rpm/knot.spec | 2 +- doc/Makefile.am | 109 +- doc/Makefile.in | 275 +- doc/appendices.rst | 21 - doc/conf.py | 5 +- doc/configuration.rst | 75 +- doc/installation.rst | 5 +- doc/introduction.rst | 4 +- doc/man/kcatalogprint.8 | 81 + doc/man/kcatalogprint.8in | 80 - doc/man/kdig.1 | 465 +++ doc/man/kdig.1in | 464 --- doc/man/keymgr.8 | 390 +++ doc/man/keymgr.8in | 389 --- doc/man/khost.1 | 157 ++ doc/man/khost.1in | 156 -- doc/man/kjournalprint.8 | 118 + doc/man/kjournalprint.8in | 120 - doc/man/knot.conf.5 | 2957 ++++++++++++++++++++ doc/man/knot.conf.5in | 2887 ------------------- doc/man/knotc.8 | 447 +++ doc/man/knotc.8in | 440 --- doc/man/knotd.8 | 94 + doc/man/knotd.8in | 93 - doc/man/knsec3hash.1 | 108 + doc/man/knsec3hash.1in | 96 - doc/man/knsupdate.1 | 252 ++ doc/man/knsupdate.1in | 218 -- doc/man/kxdpgun.8 | 299 ++ doc/man/kxdpgun.8in | 278 -- doc/man/kzonecheck.1 | 95 + doc/man/kzonecheck.1in | 94 - doc/man/kzonesign.1 | 96 + doc/man/kzonesign.1in | 95 - doc/man_kcatalogprint.rst | 3 +- doc/man_kdig.rst | 9 +- doc/man_keymgr.rst | 3 +- doc/man_khost.rst | 3 +- doc/man_kjournalprint.rst | 6 +- doc/man_knotc.rst | 15 +- doc/man_knotd.rst | 3 +- doc/man_knsec3hash.rst | 12 + doc/man_knsupdate.rst | 74 +- doc/man_kxdpgun.rst | 25 +- doc/man_kzonecheck.rst | 3 +- doc/man_kzonesign.rst | 3 +- doc/migration.rst | 90 +- doc/operation.rst | 34 +- doc/reference.rst | 114 +- doc/requirements.rst | 8 +- python/Makefile.in | 5 +- python/knot_exporter/Makefile.in | 5 +- python/libknot/Makefile.in | 5 +- python/libknot/libknot/probe.py | 10 +- samples/Makefile.in | 5 +- src/Makefile.in | 462 ++- src/config.h.in | 44 +- src/contrib/Makefile.inc | 1 + src/contrib/asan.h | 13 +- src/contrib/atomic.h | 73 + src/contrib/files.c | 23 +- src/contrib/files.h | 9 +- src/contrib/json.c | 7 + src/contrib/json.h | 7 +- src/contrib/mempattern.c | 10 +- src/contrib/spinlock.h | 80 +- src/contrib/string.c | 20 +- src/contrib/string.h | 4 +- src/contrib/time.h | 5 + src/knot/Makefile.inc | 12 +- src/knot/catalog/catalog_db.c | 4 +- src/knot/catalog/catalog_update.c | 4 +- src/knot/catalog/interpret.c | 4 +- src/knot/common/dbus.c | 243 ++ src/knot/common/dbus.h | 86 + src/knot/common/fdset.c | 9 +- src/knot/common/fdset.h | 13 +- src/knot/common/stats.c | 356 ++- src/knot/common/stats.h | 61 +- src/knot/common/systemd.c | 98 +- src/knot/common/systemd.h | 66 +- src/knot/conf/base.c | 19 +- src/knot/conf/base.h | 3 + src/knot/conf/conf.c | 15 +- src/knot/conf/conf.h | 17 +- src/knot/conf/schema.c | 35 +- src/knot/conf/schema.h | 25 +- src/knot/conf/tools.c | 93 +- src/knot/ctl/commands.c | 547 ++-- src/knot/ctl/commands.h | 4 +- src/knot/ctl/process.c | 17 +- src/knot/ctl/process.h | 12 +- src/knot/dnssec/context.c | 15 +- src/knot/dnssec/context.h | 16 +- src/knot/dnssec/ds_query.c | 4 +- src/knot/dnssec/key-events.c | 6 +- src/knot/dnssec/key_records.c | 23 +- src/knot/dnssec/key_records.h | 6 +- src/knot/dnssec/rrset-sign.c | 17 +- src/knot/dnssec/rrset-sign.h | 6 +- src/knot/dnssec/zone-events.c | 95 +- src/knot/dnssec/zone-events.h | 22 +- src/knot/dnssec/zone-sign.c | 98 +- src/knot/dnssec/zone-sign.h | 14 +- src/knot/events/events.c | 3 +- src/knot/events/events.h | 3 +- src/knot/events/handlers.h | 4 +- src/knot/events/handlers/dnskey_sync.c | 4 +- src/knot/events/handlers/ds_push.c | 6 +- src/knot/events/handlers/notify.c | 4 +- src/knot/events/handlers/refresh.c | 39 +- src/knot/events/handlers/update.c | 86 +- src/knot/events/handlers/validate.c | 34 + src/knot/events/replan.c | 5 +- src/knot/include/module.h | 55 +- src/knot/modules/cookies/cookies.c | 19 +- src/knot/modules/probe/probe.c | 13 +- src/knot/modules/rrl/Makefile.inc | 9 +- src/knot/modules/rrl/functions.c | 589 +--- src/knot/modules/rrl/functions.h | 88 +- src/knot/modules/rrl/kru-avx2.c | 66 + src/knot/modules/rrl/kru-generic.c | 20 + src/knot/modules/rrl/kru.h | 90 + src/knot/modules/rrl/kru.inc.c | 615 ++++ src/knot/modules/rrl/rrl.c | 243 +- src/knot/modules/rrl/rrl.rst | 169 +- src/knot/modules/stats/stats.c | 14 +- src/knot/modules/stats/stats.rst | 2 + src/knot/nameserver/axfr.c | 6 +- src/knot/nameserver/axfr.h | 6 +- src/knot/nameserver/internet.c | 50 +- src/knot/nameserver/internet.h | 17 +- src/knot/nameserver/ixfr.c | 10 +- src/knot/nameserver/ixfr.h | 8 +- src/knot/nameserver/log.h | 2 + src/knot/nameserver/notify.c | 6 +- src/knot/nameserver/notify.h | 7 +- src/knot/nameserver/nsec_proofs.c | 6 +- src/knot/nameserver/process_query.c | 83 +- src/knot/nameserver/process_query.h | 13 +- src/knot/nameserver/query_module.c | 50 +- src/knot/nameserver/query_module.h | 31 +- src/knot/nameserver/update.c | 35 +- src/knot/nameserver/update.h | 6 +- src/knot/nameserver/xfr.h | 6 +- src/knot/query/quic-requestor.c | 13 +- src/knot/query/quic-requestor.h | 8 +- src/knot/query/requestor.c | 62 +- src/knot/query/requestor.h | 38 +- src/knot/query/tls-requestor.c | 59 + src/knot/query/tls-requestor.h | 51 + src/knot/server/handler.c | 13 +- src/knot/server/handler.h | 35 +- src/knot/server/quic-handler.c | 11 +- src/knot/server/server.c | 220 +- src/knot/server/server.h | 17 +- src/knot/server/tcp-handler.c | 115 +- src/knot/server/udp-handler.c | 25 +- src/knot/server/xdp-handler.c | 61 +- src/knot/updates/acl.c | 29 +- src/knot/updates/acl.h | 33 +- src/knot/updates/ddns.c | 181 +- src/knot/updates/ddns.h | 14 +- src/knot/updates/zone-update.c | 26 +- src/knot/updates/zone-update.h | 2 + src/knot/zone/backup.c | 8 +- src/knot/zone/backup.h | 6 + src/knot/zone/backup_dir.c | 42 +- src/knot/zone/contents.c | 10 +- src/knot/zone/contents.h | 4 +- src/knot/zone/digest.c | 6 +- src/knot/zone/semantic-check.c | 6 +- src/knot/zone/semantic-check.h | 1 + src/knot/zone/zone-tree.c | 4 +- src/knot/zone/zone.c | 10 +- src/knot/zone/zone.h | 6 +- src/knot/zone/zonedb-load.c | 10 +- src/knot/zone/zonedb.c | 4 +- src/knot/zone/zonefile.c | 15 +- src/libdnssec/key/algorithm.c | 12 +- src/libdnssec/key/convert.c | 22 +- src/libdnssec/pem.c | 21 +- src/libdnssec/sign/sign.c | 41 +- src/libdnssec/version.h | 4 +- src/libknot/Makefile.inc | 4 + src/libknot/attribute.h | 14 +- src/libknot/control/control.c | 23 +- src/libknot/control/control.h | 24 +- src/libknot/dname.c | 36 +- src/libknot/dname.h | 9 +- src/libknot/errcode.h | 3 + src/libknot/error.c | 3 + src/libknot/packet/pkt.h | 1 - src/libknot/packet/rrset-wire.c | 22 +- src/libknot/packet/rrset-wire.h | 6 +- src/libknot/packet/wire.h | 21 +- src/libknot/quic/quic.c | 343 +-- src/libknot/quic/quic.h | 59 +- src/libknot/quic/quic_conn.c | 35 +- src/libknot/quic/quic_conn.h | 20 +- src/libknot/quic/tls.c | 262 ++ src/libknot/quic/tls.h | 135 + src/libknot/quic/tls_common.c | 472 ++++ src/libknot/quic/tls_common.h | 134 + src/libknot/rrset-dump.c | 140 +- src/libknot/rrtype/tsig.c | 6 +- src/libknot/version.h | 4 +- src/libknot/xdp/Makefile.in | 5 +- src/libknot/xdp/bpf-user.h | 12 +- src/libknot/xdp/tcp.c | 266 +- src/libknot/xdp/tcp.h | 13 +- src/libknot/xdp/xdp.c | 253 +- src/libknot/xdp/xdp.h | 58 +- src/libknot/yparser/ypschema.h | 2 + src/libknot/yparser/yptrafo.c | 60 +- src/libzscanner/version.h | 4 +- src/utils/Makefile.inc | 6 +- src/utils/common/msg.h | 16 +- src/utils/common/netio.c | 7 +- src/utils/common/params.c | 2 +- src/utils/common/params.h | 13 +- src/utils/common/quic.h | 4 - src/utils/common/tls.c | 7 +- src/utils/kcatalogprint/main.c | 14 +- src/utils/kdig/kdig_params.c | 13 +- src/utils/keymgr/bind_privkey.c | 8 - src/utils/keymgr/main.c | 10 +- src/utils/keymgr/offline_ksk.c | 31 +- src/utils/khost/khost_params.c | 10 +- src/utils/kjournalprint/main.c | 17 +- src/utils/knotc/commands.c | 9 +- src/utils/knotc/main.c | 6 +- src/utils/knotd/main.c | 256 +- src/utils/knsec3hash/knsec3hash.c | 12 +- src/utils/knsupdate/knsupdate_exec.c | 12 +- src/utils/knsupdate/knsupdate_params.c | 160 +- src/utils/knsupdate/knsupdate_params.h | 8 +- src/utils/kxdpgun/load_queries.c | 241 +- src/utils/kxdpgun/load_queries.h | 14 +- src/utils/kxdpgun/main.c | 578 ++-- src/utils/kxdpgun/main.h | 87 + src/utils/kxdpgun/stats.c | 292 ++ src/utils/kxdpgun/stats.h | 78 + src/utils/kzonecheck/main.c | 6 +- src/utils/kzonesign/main.c | 10 +- tests-fuzz/Makefile.am | 6 +- tests-fuzz/Makefile.in | 13 +- tests/Makefile.am | 4 +- tests/Makefile.in | 104 +- tests/contrib/test_atomic.c | 165 ++ tests/knot/semantic_check_data/soa.duplicate | 5 + tests/knot/semantic_check_data/soa.missing | 3 + tests/knot/semantic_check_data/soa.multiple | 5 + tests/knot/test_confdb.c | 4 +- tests/knot/test_confio.c | 7 +- tests/knot/test_query_module.c | 15 +- tests/knot/test_semantic_check.in | 5 + tests/libdnssec/test_key.c | 2 - tests/libdnssec/test_key_algorithm.c | 6 +- tests/libdnssec/test_key_ds.c | 4 - tests/libdnssec/test_sign.c | 8 +- tests/libknot/test_control.c | 4 +- tests/libknot/test_xdp_tcp.c | 49 +- tests/libknot/test_yptrafo.c | 7 +- tests/modules/test_rrl.c | 482 +++- tests/tap/files.c | 4 +- 342 files changed, 15511 insertions(+), 13751 deletions(-) delete mode 100644 distro/pkg/deb-nolibxdp/libknot14.install delete mode 100644 distro/pkg/deb-nolibxdp/libknot14.symbols create mode 100644 distro/pkg/deb-nolibxdp/libknot15.install create mode 100644 distro/pkg/deb-nolibxdp/libknot15.symbols delete mode 100644 distro/pkg/deb-nolibxdp/ufw/knot delete mode 100644 distro/pkg/deb-noxdp/changelog delete mode 100644 distro/pkg/deb-noxdp/clean delete mode 100644 distro/pkg/deb-noxdp/compat delete mode 100644 distro/pkg/deb-noxdp/control delete mode 100644 distro/pkg/deb-noxdp/copyright delete mode 100644 distro/pkg/deb-noxdp/cz.nic.knotd.conf delete mode 100644 distro/pkg/deb-noxdp/docs delete mode 100644 distro/pkg/deb-noxdp/knot-dnssecutils.install delete mode 100644 distro/pkg/deb-noxdp/knot-dnssecutils.manpages delete mode 100644 distro/pkg/deb-noxdp/knot-dnsutils.install delete mode 100644 distro/pkg/deb-noxdp/knot-dnsutils.manpages delete mode 100644 distro/pkg/deb-noxdp/knot-doc.install delete mode 100644 distro/pkg/deb-noxdp/knot-doc.links delete mode 100644 distro/pkg/deb-noxdp/knot-exporter.install delete mode 100644 distro/pkg/deb-noxdp/knot-host.install delete mode 100644 distro/pkg/deb-noxdp/knot-host.manpages delete mode 100644 distro/pkg/deb-noxdp/knot-module-dnstap.install delete mode 100644 distro/pkg/deb-noxdp/knot-module-geoip.install delete mode 100644 distro/pkg/deb-noxdp/knot.dirs delete mode 100644 distro/pkg/deb-noxdp/knot.init delete mode 100644 distro/pkg/deb-noxdp/knot.install delete mode 100644 distro/pkg/deb-noxdp/knot.manpages delete mode 100644 distro/pkg/deb-noxdp/knot.postinst delete mode 100644 distro/pkg/deb-noxdp/knot.postrm delete mode 100644 distro/pkg/deb-noxdp/knot.service delete mode 100644 distro/pkg/deb-noxdp/libdnssec9.install delete mode 100644 distro/pkg/deb-noxdp/libdnssec9.symbols delete mode 100644 distro/pkg/deb-noxdp/libknot-dev.install delete mode 100644 distro/pkg/deb-noxdp/libknot14.install delete mode 100644 distro/pkg/deb-noxdp/libknot14.symbols delete mode 100644 distro/pkg/deb-noxdp/libzscanner4.install delete mode 100644 distro/pkg/deb-noxdp/libzscanner4.symbols delete mode 100644 distro/pkg/deb-noxdp/not-installed delete mode 100644 distro/pkg/deb-noxdp/patches/05-revert-mod-dnstap-TCP-sink.patch delete mode 100644 distro/pkg/deb-noxdp/patches/series delete mode 100755 distro/pkg/deb-noxdp/prepare-environment delete mode 100644 distro/pkg/deb-noxdp/python3-libknot.install delete mode 100755 distro/pkg/deb-noxdp/rules delete mode 100644 distro/pkg/deb-noxdp/source/format delete mode 100755 distro/pkg/deb-noxdp/tests/authoritative-server delete mode 100644 distro/pkg/deb-noxdp/tests/control delete mode 100755 distro/pkg/deb-noxdp/tests/kdig delete mode 100644 distro/pkg/deb-noxdp/ufw/knot delete mode 100644 distro/pkg/deb-noxdp/watch delete mode 100644 distro/pkg/deb/libknot14.install delete mode 100644 distro/pkg/deb/libknot14.symbols create mode 100644 distro/pkg/deb/libknot15.install create mode 100644 distro/pkg/deb/libknot15.symbols delete mode 100644 distro/pkg/deb/ufw/knot delete mode 100644 distro/pkg/el-7/01-revert-AC_PROG_CC.patch delete mode 100644 distro/pkg/el-7/02-fix-compilation-by-using-SHA-1.patch delete mode 100644 distro/pkg/el-7/03-doc-don-t-try-to-import-sphinx_panels.patch delete mode 100644 distro/pkg/el-7/04-revert-don-t-share-PKCS-11-private-keys.patch delete mode 100644 distro/pkg/el-7/05-revert-mod-dnstap-TCP-sink.patch delete mode 100644 distro/pkg/el-7/knot.service delete mode 100644 distro/pkg/el-7/knot.spec delete mode 100644 distro/pkg/el-7/knot.tmpfiles create mode 100644 doc/man/kcatalogprint.8 delete mode 100644 doc/man/kcatalogprint.8in create mode 100644 doc/man/kdig.1 delete mode 100644 doc/man/kdig.1in create mode 100644 doc/man/keymgr.8 delete mode 100644 doc/man/keymgr.8in create mode 100644 doc/man/khost.1 delete mode 100644 doc/man/khost.1in create mode 100644 doc/man/kjournalprint.8 delete mode 100644 doc/man/kjournalprint.8in create mode 100644 doc/man/knot.conf.5 delete mode 100644 doc/man/knot.conf.5in create mode 100644 doc/man/knotc.8 delete mode 100644 doc/man/knotc.8in create mode 100644 doc/man/knotd.8 delete mode 100644 doc/man/knotd.8in create mode 100644 doc/man/knsec3hash.1 delete mode 100644 doc/man/knsec3hash.1in create mode 100644 doc/man/knsupdate.1 delete mode 100644 doc/man/knsupdate.1in create mode 100644 doc/man/kxdpgun.8 delete mode 100644 doc/man/kxdpgun.8in create mode 100644 doc/man/kzonecheck.1 delete mode 100644 doc/man/kzonecheck.1in create mode 100644 doc/man/kzonesign.1 delete mode 100644 doc/man/kzonesign.1in create mode 100644 src/contrib/atomic.h create mode 100644 src/knot/common/dbus.c create mode 100644 src/knot/common/dbus.h create mode 100644 src/knot/events/handlers/validate.c create mode 100644 src/knot/modules/rrl/kru-avx2.c create mode 100644 src/knot/modules/rrl/kru-generic.c create mode 100644 src/knot/modules/rrl/kru.h create mode 100644 src/knot/modules/rrl/kru.inc.c create mode 100644 src/knot/query/tls-requestor.c create mode 100644 src/knot/query/tls-requestor.h create mode 100644 src/libknot/quic/tls.c create mode 100644 src/libknot/quic/tls.h create mode 100644 src/libknot/quic/tls_common.c create mode 100644 src/libknot/quic/tls_common.h create mode 100644 src/utils/kxdpgun/main.h create mode 100644 src/utils/kxdpgun/stats.c create mode 100644 src/utils/kxdpgun/stats.h create mode 100644 tests/contrib/test_atomic.c create mode 100644 tests/knot/semantic_check_data/soa.duplicate create mode 100644 tests/knot/semantic_check_data/soa.missing create mode 100644 tests/knot/semantic_check_data/soa.multiple diff --git a/Doxyfile.in b/Doxyfile.in index da386e3..51f724b 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -1,4 +1,4 @@ -# Doxyfile 1.8.17 +# Doxyfile 1.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -17,11 +17,11 @@ # Project related configuration options #--------------------------------------------------------------------------- -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See https://www.gnu.org/software/libiconv -# for the list of possible encodings. +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 @@ -93,6 +93,14 @@ ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. @@ -189,6 +197,16 @@ SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus @@ -209,6 +227,14 @@ QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. @@ -236,16 +262,15 @@ TAB_SIZE = 8 # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) ALIASES = -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all @@ -274,28 +299,40 @@ OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: -# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: -# Fortran. In the later case the parser tries to guess whether the code is fixed -# or free formatted code, this is the default for Fortran type files), VHDL. For -# instance to make doxygen treat .inc files as Fortran files (default is PHP), -# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. +# documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. @@ -303,6 +340,15 @@ EXTENSION_MAPPING = MARKDOWN_SUPPORT = YES +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or @@ -328,7 +374,7 @@ BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. @@ -414,6 +460,19 @@ TYPEDEF_HIDES_STRUCT = YES LOOKUP_CACHE_SIZE = 0 +# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which efficively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -434,6 +493,12 @@ EXTRACT_ALL = YES EXTRACT_PRIVATE = NO +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. @@ -471,6 +536,13 @@ EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation @@ -488,8 +560,8 @@ HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO, these declarations will be -# included in the documentation. +# declarations. If set to NO, these declarations will be included in the +# documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO @@ -508,11 +580,18 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. # The default value is: system dependent. CASE_SENSE_NAMES = NO @@ -699,7 +778,7 @@ LAYOUT_FILE = doc/doxygen/DoxygenLayout.xml # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. @@ -744,13 +823,17 @@ WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO @@ -790,8 +873,8 @@ INPUT = doc/doxygen/Doxy.page.h \ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv) for the list of -# possible encodings. +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 @@ -804,11 +887,15 @@ INPUT_ENCODING = UTF-8 # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, -# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, +# *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.h @@ -963,7 +1050,7 @@ INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. +# entity all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO @@ -1000,7 +1087,7 @@ SOURCE_TOOLTIPS = YES # # To use it do the following: # - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # @@ -1023,16 +1110,22 @@ USE_HTAGS = NO VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. # Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse-libclang=ON option for CMake. +# generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO +# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to +# YES then doxygen will add the directory of each input to the include path. +# The default value is: YES. + +CLANG_ADD_INC_PATHS = YES + # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories @@ -1041,6 +1134,19 @@ CLANG_ASSISTED_PARSING = NO CLANG_OPTIONS = +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- @@ -1052,13 +1158,6 @@ CLANG_OPTIONS = ALPHABETICAL_INDEX = YES -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored @@ -1159,7 +1258,7 @@ HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. @@ -1195,6 +1294,17 @@ HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = YES +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. @@ -1218,13 +1328,14 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1263,8 +1374,8 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. +# (see: +# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML @@ -1294,7 +1405,7 @@ CHM_FILE = HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). +# (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1339,7 +1450,8 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1347,8 +1459,8 @@ QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- -# folders). +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1356,30 +1468,30 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = @@ -1456,6 +1568,17 @@ TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML @@ -1476,8 +1599,14 @@ FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering +# https://www.mathjax.org) which uses client side JavaScript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path @@ -1489,7 +1618,7 @@ USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. @@ -1504,8 +1633,8 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest @@ -1519,7 +1648,8 @@ MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1547,7 +1677,7 @@ MATHJAX_CODEFILE = SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a web server instead of a web client using Javascript. There +# implemented using a web server instead of a web client using JavaScript. There # are two flavors of web server based searching depending on the EXTERNAL_SEARCH # setting. When disabled, doxygen will generate a PHP script for searching and # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing @@ -1566,7 +1696,8 @@ SERVER_BASED_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). +# Xapian (see: +# https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1579,8 +1710,9 @@ EXTERNAL_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). See the section "External Indexing and -# Searching" for details. +# Xapian (see: +# https://xapian.org/). See the section "External Indexing and Searching" for +# details. # This tag requires that the tag SEARCHENGINE is set to YES. SEARCHENGINE_URL = @@ -1631,21 +1763,35 @@ LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. # -# Note that when enabling USE_PDFLATEX this option is only used for generating -# bitmaps for formulas in the HTML output, but not in the Makefile that is -# written to the output directory. -# The default file is: latex. +# Note that when not enabling USE_PDFLATEX the default is latex when enabling +# USE_PDFLATEX the default is pdflatex and when in the later case latex is +# chosen this is overwritten by pdflatex. For specific output languages the +# default can have been set differently, this depends on the implementation of +# the output language. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate # index for LaTeX. +# Note: This tag is used in the Makefile / make.bat. +# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file +# (.tex). # The default file is: makeindex. # This tag requires that the tag GENERATE_LATEX is set to YES. MAKEINDEX_CMD_NAME = makeindex +# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. +# Note: This tag is used in the generated output file (.tex). +# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. +# The default value is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_MAKEINDEX_CMD = makeindex + # If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX # documents. This may be useful for small projects and may help to save some # trees in general. @@ -1661,7 +1807,7 @@ COMPACT_LATEX = NO # The default value is: a4. # This tag requires that the tag GENERATE_LATEX is set to YES. -PAPER_TYPE = a4wide +PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names # that should be included in the LaTeX output. The package can be specified just @@ -1730,9 +1876,11 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate -# the PDF file directly from the LaTeX files. Set this option to YES, to get a -# higher quality PDF documentation. +# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as +# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX +# files. Set this option to YES, to get a higher quality PDF documentation. +# +# See also section LATEX_CMD_NAME for selecting the engine. # The default value is: YES. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1766,7 +1914,7 @@ LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See -# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# https://en.wikipedia.org/wiki/BibTeX and \cite for more info. # The default value is: plain. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1780,6 +1928,14 @@ LATEX_BIB_STYLE = plain LATEX_TIMESTAMP = NO +# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) +# path from which the emoji images will be read. If a relative path is entered, +# it will be relative to the LATEX_OUTPUT directory. If left blank the +# LATEX_OUTPUT directory will be used. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EMOJI_DIRECTORY = + #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- @@ -1819,9 +1975,9 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's config -# file, i.e. a series of assignments. You only have to provide replacements, -# missing definitions are set to their default value. +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# configuration file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. # # See also section "Doxygen usage" for information on how to generate the # default style sheet that doxygen normally uses. @@ -1830,8 +1986,8 @@ RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is -# similar to doxygen's config file. A template extensions file can be generated -# using doxygen -e rtf extensionFile. +# similar to doxygen's configuration file. A template extensions file can be +# generated using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_EXTENSIONS_FILE = @@ -1917,6 +2073,13 @@ XML_OUTPUT = xml XML_PROGRAMLISTING = YES +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# namespace members in file scope as well, matching the HTML output. +# The default value is: NO. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_NS_MEMB_FILE_SCOPE = NO + #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- @@ -1949,9 +2112,9 @@ DOCBOOK_PROGRAMLISTING = NO #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an -# AutoGen Definitions (see http://autogen.sf.net) file that captures the -# structure of the code including all documentation. Note that this feature is -# still experimental and incomplete at the moment. +# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# the structure of the code including all documentation. Note that this feature +# is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO @@ -2228,10 +2391,32 @@ UML_LOOK = NO # but if the number exceeds 15, the total amount of fields shown is limited to # 10. # Minimum value: 0, maximum value: 100, default value: 10. -# This tag requires that the tag HAVE_DOT is set to YES. +# This tag requires that the tag UML_LOOK is set to YES. UML_LIMIT_NUM_FIELDS = 10 +# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and +# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS +# tag is set to YES, doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen +# will not generate fields with class member information in the UML graphs. The +# class diagrams will look similar to the default class diagrams but using UML +# notation for the relationships. +# Possible values are: NO, YES and NONE. +# The default value is: NO. +# This tag requires that the tag UML_LOOK is set to YES. + +DOT_UML_DETAILS = NO + +# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters +# to display on a single line. If the actual line length exceeds this threshold +# significantly it will wrapped across multiple lines. Some heuristics are apply +# to avoid ugly line breaks. +# Minimum value: 0, maximum value: 1000, default value: 17. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_WRAP_THRESHOLD = 17 + # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and # collaboration graphs will show the relations between templates and their # instances. @@ -2360,6 +2545,11 @@ DIAFILE_DIRS = PLANTUML_JAR_PATH = +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. + +PLANTUML_CFG_FILE = + # When using plantuml, the specified paths are searched for files specified by # the !include statement in a plantuml block. @@ -2418,9 +2608,11 @@ DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate # files that are used to generate the various graphs. +# +# Note: This setting is not only used for dot files but also for msc and +# plantuml temporary files. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. DOT_CLEANUP = YES diff --git a/Makefile.in b/Makefile.in index 3dfda33..d7ac091 100644 --- a/Makefile.in +++ b/Makefile.in @@ -348,6 +348,8 @@ infodir = @infodir@ install_sh = @install_sh@ libbpf_CFLAGS = @libbpf_CFLAGS@ libbpf_LIBS = @libbpf_LIBS@ +libdbus_CFLAGS = @libdbus_CFLAGS@ +libdbus_LIBS = @libdbus_LIBS@ libdir = @libdir@ libdnssec_SONAME = @libdnssec_SONAME@ libdnssec_SOVERSION = @libdnssec_SOVERSION@ @@ -359,8 +361,6 @@ libfstrm_CFLAGS = @libfstrm_CFLAGS@ libfstrm_LIBS = @libfstrm_LIBS@ libidn2_CFLAGS = @libidn2_CFLAGS@ libidn2_LIBS = @libidn2_LIBS@ -libidn_CFLAGS = @libidn_CFLAGS@ -libidn_LIBS = @libidn_LIBS@ libknot_SONAME = @libknot_SONAME@ libknot_SOVERSION = @libknot_SOVERSION@ libknot_VERSION_INFO = @libknot_VERSION_INFO@ @@ -378,7 +378,6 @@ libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@ libprotobuf_c_LIBS = @libprotobuf_c_LIBS@ liburcu_CFLAGS = @liburcu_CFLAGS@ liburcu_LIBS = @liburcu_LIBS@ -liburcu_PKGCONFIG = @liburcu_PKGCONFIG@ libxdp_CFLAGS = @libxdp_CFLAGS@ libxdp_LIBS = @libxdp_LIBS@ libzscanner_SONAME = @libzscanner_SONAME@ diff --git a/NEWS b/NEWS index 80a44ee..9e9e71d 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,75 @@ +Knot DNS 3.4.0 (2024-09-02) +=========================== + +Features: +--------- + - knotd: full DNS over TLS (DoT, RFC 7858) implementation (see 'DNS over TLS') + - knotd: bidirectional XFR over TLS (XoT) support with opportunistic, strict, + and mutual authentication profiles + - knotd: support for DDNS over QUIC and TLS + - knotd: DNSSEC validation requires the remaining RRSIG validity is longer than 'rrsig-refresh' + - knotd: new event for automatic DNSSEC revalidation + - knotd: if enabled DNSSEC signing, EDNS expire is adjusted to the earliest RRSIG expiration + - knotd: added support for libdbus as an alternative to systemd dbus + (see '--enable-dbus=libdbus' configure parameter) + - knotd: new XDP-related configuration options + (see 'xdp.ring-size', 'xdp.busypoll-budget', and 'xdp.busypoll-timeout') + - knotc: new command for explicit triggering DNSSEC validation (see 'zone-validate' command) + - keymgr: SKR verification requires end of DNSKEY RRSIG validity covers next DNSKEY snapshot + - kdig: +nocrypto applies also to CERT, DS, SSHFP, DHCID, TLSA, ZONEMD, and TSIG + - knsupdate: added support for DDNS over QUIC and TLS (see '-Q' and '-S' parameters) + - kxdpgun: support for reading a binary input file (see '-B' parameter) + - kxdpgun: support for output in JSON (see '-j' parameter) + - kxdpgun: support for periodical output (see '-S' parameter) + - mod-rrl: module offers limiting of non-UDP protocols based on consumed time + (see 'mod-rrl.time-rate-limit' and 'mod-rrl.time-instant-limit') + - utils: -VV option for listing compile time configuration summary + +Improvements: +------------- + - knotd: up to eight DDNS queries can be queued per zone when frozen + - knotd: the number of created/validated RRSIGs is logged + - knotd: overhaul of atomic operations usage + - knotd: unified DNAME semantic errors with the CNAME ones + (see 'Handling CNAME and DNAME-related updates') + - knotd: better DDNS pre-check to prevent dropping a bulk of updates + - knotd: extended SOA presence semantic checks + - knotd: disallowed concurrent control zone and config transactions to avoid deadlock + - knotd: disallowed opening zone transaction when blocking command is running to avoid deadlock + - knotd: new XDP statistic counters + - knotd: remote zone serial is logged upon received incoming transfer + - knotd: zone backup stores and zone restore checks the CPU architecture compatibility + - knotd: time configuration options support 'w', 'M', and 'y' units + - knotd: some control commands can be processed asynchronously + - knotc: zone backup overwrites already existing backupdir in the force mode + - kdig: EDNS is enabled by default + - kdig: the default EDNS payload size was lowered to 1232 + - mod-rrl: completely reimplemented UDP rate limiting using an efficient + query-counting mechanism on several address prefix lengths + - mod-rrl: module no longer requires explicit configuration + - libknot: various XDP improvements and new configuration parameters + - docker: increased -D_FORTIFY_SOURCE to 3 + +Bugfixes: +--------- + - knotd: deadlock during zone-ksk-submitted processing of a frozen zone + - kxdpgun: race condition in SIGUSR1 signal processing + - doc: parallel build is unreliable #928 + +Compatibility: +-------------- + - configure: increase minimal GnuTLS version to 3.6.10 + - configure: removed deprecated libidn 1 support + - configure: removed liburcu search fallback + - configure: required GCC or LLVM Clang compiler with C11 support + - knotd: removed already ignored obsolete configuration options + - keymgr: removed legacy parameter '--brief' + - kjournalprint: removed legacy parameter '--no-color' + - kjournalprint: removed legacy database specification without '--dir' + - kcatalogprint: removed legacy database specification without '--dir' + - packaging: CentOS 7, Debian 10, and Ubuntu 18.04 no longer supported + - doc: removed info pages + Knot DNS 3.3.9 (2024-08-26) =========================== @@ -296,6 +368,76 @@ Packaging: - debian,ubuntu: new self-hosted repository (see https://pkg.labs.nic.cz/doc/) - docker: upgraded to Debian bookworm-slim +Knot DNS 3.2.13 (2024-06-25) +============================ + +Bugfixes: +--------- + - knotd: insufficient metadata check can cause journal corruption + - knotd: failed to build on macOS #909 + - knotd: early NSEC3 salt replanning if 'nsec3-salt-lifetime: -1' + - knotc: zone check complains about missing zone file #913 + - kdig: failed to parse empty QNAME (do not fill question section) + - python: failed to set an empty configuration value + - libzscanner: incorrect alpn processing #923 + - libknot: insufficient check for malformed TCP header options over XDP + - libknot: infinite loop in knot_rrset_to_wire_extra() #916 + +Knot DNS 3.2.12 (2023-12-19) +============================ + +Improvements: +------------- + - knotd: zone purging waits for finished zone expiration for better reliability + - doc: various fixes and extensions + +Bugfixes: +--------- + - knotd: zone backup fails due to improper backup context deinitialization #891 + - knotd: failed to sign the zone if maximum zone's TTL is too high + - knotd: malformed TCP header if used with QUIC in the generic XDP mode + - knotd: incorrect initialization of TCP limits + - knotd: orphaned PEM file not deleted when key generation fails + - knotd: server can crash when processing new TCP connections over XDP + - kdig: crashed when querying DNS over TLS if TLS handshake times out #896 + - kzonecheck: failed to check DS with SHA-1 or GOST if not supported by local policy + +Knot DNS 3.2.11 (2023-10-30) +============================ + +Improvements: +------------- + - keymgr: improved error message if a key file is not accessible + - keymgr: added offline RRSIGs validation at the end of their validity intervals + - doc: fixed some typos + +Bugfixes: +--------- + - knotd: DNAME record returned with query domain name instead of actual name #873 + - knotd: failed to import configuration file if mod-geoip is in use #881 + - knotd: failed to sign RRSet that fits to 64k only if compressed + - keymgr: offline RRSIGs not refreshed if 'rrsig-refresh' is not set + - knsupdate: incorrect processing of @ in the delete operation #879 + +Knot DNS 3.2.10 (2023-09-11) +============================ + +Improvements: +------------- + - knotd: multiple catalog groups per member are tolerated, but only one is used + - knotd: server cleans up stale LMDB readers when opening a RW transaction + +Bugfixes: +--------- + - knotd: server can crash when adjusting a wildcard glue + - knotd: failed to forward DDNS if 'zone.master' points to 'remotes' + - knotd: subsequent addition and removal to catalog zone isn't handled properly + - knotd: server can crash if a shared module is loaded and dynamic configuration used + - knotc: configuration import fails if an explicit shared module is configured + - kdig: double-free on some malformed responses over QUIC #869 + - kdig: some TLS parameters override QUIC parameters + - libs: NULL record with empty RDATA isn't allowed + Knot DNS 3.2.9 (2023-07-27) =========================== diff --git a/README.md b/README.md index 42f4401..249fc0a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ [![Coverity Status](https://img.shields.io/coverity/scan/knot-dns.svg)](https://scan.coverity.com/projects/knot-dns) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/knot-dns.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:knot-dns) -[![Documentation Status](https://readthedocs.org/projects/knot/badge/?version=master)](https://knot.readthedocs.io/en/master/) # Requirements @@ -29,7 +28,7 @@ sudo apt-get install \ #### Install optional packages: ```bash sudo apt-get install \ - libcap-ng-dev libsystemd-dev libidn2-0-dev libprotobuf-c-dev protobuf-c-compiler libfstrm-dev libmaxminddb-dev libnghttp2-dev libbpf-dev libxdp-dev libmnl-dev python3-sphinx python3-sphinx-panels + libcap-ng-dev libsystemd-dev libidn2-dev libprotobuf-c-dev protobuf-c-compiler libfstrm-dev libmaxminddb-dev libnghttp2-dev libbpf-dev libxdp-dev libmnl-dev python3-sphinx python3-sphinx-panels ``` ### Fedora like distributions diff --git a/configure b/configure index 346f99f..26445fe 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for knot 3.3.9. +# Generated by GNU Autoconf 2.71 for knot 3.4.0. # # Report bugs to . # @@ -621,8 +621,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='knot' PACKAGE_TARNAME='knot' -PACKAGE_VERSION='3.3.9' -PACKAGE_STRING='knot 3.3.9' +PACKAGE_VERSION='3.4.0' +PACKAGE_STRING='knot 3.4.0' PACKAGE_BUGREPORT='knot-dns@labs.nic.cz' PACKAGE_URL='' @@ -663,14 +663,6 @@ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS -HAVE_MAKEINFO_FALSE -HAVE_MAKEINFO_TRUE -HAVE_PDFLATEX_FALSE -HAVE_PDFLATEX_TRUE -HAVE_SPHINXBUILD_FALSE -HAVE_SPHINXBUILD_TRUE -PDFLATEX -SPHINXBUILD OSS_FUZZ_FALSE OSS_FUZZ_TRUE FUZZER_FALSE @@ -695,8 +687,6 @@ libmnl_LIBS libmnl_CFLAGS libnghttp2_LIBS libnghttp2_CFLAGS -libidn_LIBS -libidn_CFLAGS libidn2_LIBS libidn2_CFLAGS embedded_libngtcp2_LIBS @@ -782,12 +772,13 @@ SHARED_MODULE_authsignal_FALSE SHARED_MODULE_authsignal_TRUE STATIC_MODULE_authsignal_FALSE STATIC_MODULE_authsignal_TRUE -liburcu_PKGCONFIG liburcu_LIBS liburcu_CFLAGS malloc_LIBS libkqueue_LIBS libkqueue_CFLAGS +libdbus_LIBS +libdbus_CFLAGS systemd_LIBS systemd_CFLAGS libxdp_LIBS @@ -802,10 +793,14 @@ gnutls_LIBS gnutls_CFLAGS FAST_PARSER_FALSE FAST_PARSER_TRUE -HAVE_LIBUTILS_FALSE -HAVE_LIBUTILS_TRUE +HAVE_PDFLATEX_FALSE +HAVE_PDFLATEX_TRUE HAVE_DOCS_FALSE HAVE_DOCS_TRUE +PDFLATEX +SPHINXBUILD +HAVE_LIBUTILS_FALSE +HAVE_LIBUTILS_TRUE HAVE_UTILS_FALSE HAVE_UTILS_TRUE HAVE_DAEMON_FALSE @@ -979,9 +974,9 @@ enable_recvmmsg enable_xdp enable_reuseport enable_systemd +enable_dbus with_socket_polling with_memory_allocator -with_urcu with_module_authsignal with_module_cookies with_module_dnsproxy @@ -1029,6 +1024,8 @@ libxdp_CFLAGS libxdp_LIBS systemd_CFLAGS systemd_LIBS +libdbus_CFLAGS +libdbus_LIBS libkqueue_CFLAGS libkqueue_LIBS liburcu_CFLAGS @@ -1047,8 +1044,6 @@ libngtcp2_CFLAGS libngtcp2_LIBS libidn2_CFLAGS libidn2_LIBS -libidn_CFLAGS -libidn_LIBS libnghttp2_CFLAGS libnghttp2_LIBS libmnl_CFLAGS @@ -1603,7 +1598,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures knot 3.3.9 to adapt to many kinds of systems. +\`configure' configures knot 3.4.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1674,7 +1669,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of knot 3.3.9:";; + short | recursive ) echo "Configuration of knot 3.4.0:";; esac cat <<\_ACEOF @@ -1706,6 +1701,8 @@ Optional Features: enable SO_REUSEPORT(_LB) support [default=auto] --enable-systemd=auto|yes|no enable systemd integration [default=auto] + --enable-dbus=auto|systemd|libdbus|no + enable D-bus support [default=auto] --enable-dnstap Enable dnstap support for kdig (requires fstrm, protobuf-c) --enable-maxminddb=auto|yes|no @@ -1742,7 +1739,6 @@ Optional Packages: --with-memory-allocator=auto|LIBRARY Use specific memory allocator for the server (e.g. jemalloc) [default=auto] - --with-urcu=DIR where to find userspace-rcu library --with-module-authsignal=yes|shared|no Build 'authsignal' module [default="yes"] --with-module-cookies=yes|shared|no @@ -1773,7 +1769,7 @@ Optional Packages: --with-conf-mapsize=NUM Configuration DB mapsize in MiB [default=$conf_mapsize_default] - --with-libidn=DIR Support IDN (needs GNU libidn2 or libidn) + --with-libidn=DIR Support IDN (needs GNU libidn2) --with-libnghttp2=DIR Support DoH (needs libnghttp2) --with-sanitizer Compile with sanitizer [default=no] --with-fuzzer Compile with libfuzzer [default=no] @@ -1808,6 +1804,10 @@ Some influential environment variables: C compiler flags for systemd, overriding pkg-config systemd_LIBS linker flags for systemd, overriding pkg-config + libdbus_CFLAGS + C compiler flags for libdbus, overriding pkg-config + libdbus_LIBS + linker flags for libdbus, overriding pkg-config libkqueue_CFLAGS C compiler flags for libkqueue, overriding pkg-config libkqueue_LIBS @@ -1842,9 +1842,6 @@ Some influential environment variables: C compiler flags for libidn2, overriding pkg-config libidn2_LIBS linker flags for libidn2, overriding pkg-config - libidn_CFLAGS - C compiler flags for libidn, overriding pkg-config - libidn_LIBS linker flags for libidn, overriding pkg-config libnghttp2_CFLAGS C compiler flags for libnghttp2, overriding pkg-config libnghttp2_LIBS @@ -1923,7 +1920,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -knot configure 3.3.9 +knot configure 3.4.0 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2274,7 +2271,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by knot $as_me 3.3.9, which was +It was created by knot $as_me 3.4.0, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -2865,7 +2862,6 @@ as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" as_fn_append ac_header_c_list " wchar.h wchar_h HAVE_WCHAR_H" as_fn_append ac_header_c_list " minix/config.h minix_config_h HAVE_MINIX_CONFIG_H" as_fn_append ac_header_c_list " pthread_np.h pthread_np_h HAVE_PTHREAD_NP_H" -as_fn_append ac_header_c_list " stdatomic.h stdatomic_h HAVE_STDATOMIC_H" as_fn_append ac_header_c_list " sys/uio.h sys_uio_h HAVE_SYS_UIO_H" as_fn_append ac_header_c_list " bsd/string.h bsd_string_h HAVE_BSD_STRING_H" @@ -3549,7 +3545,7 @@ fi # Define the identity of the package. PACKAGE='knot' - VERSION='3.3.9' + VERSION='3.4.0' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -5196,22 +5192,22 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Update library versions # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html - libknot_VERSION_INFO="-version-info 14:0:0" + libknot_VERSION_INFO="-version-info 15:0:0" - libknot_SOVERSION="14" + libknot_SOVERSION="15" case $host_os in #( darwin*) : - libknot_SONAME="libknot.14.dylib" + libknot_SONAME="libknot.15.dylib" ;; #( cygwin*) : - libknot_SONAME="cygknot-14.dll" + libknot_SONAME="cygknot-15.dll" ;; #( msys*) : - libknot_SONAME="msys-knot-14.dll" + libknot_SONAME="msys-knot-15.dll" ;; #( *) : - libknot_SONAME="libknot.so.14" + libknot_SONAME="libknot.so.15" ;; #( *) : @@ -5267,17 +5263,9 @@ esac KNOT_VERSION_MAJOR=3 -KNOT_VERSION_MINOR=3 - -KNOT_VERSION_PATCH=9 - - -# Store ./configure parameters and CFLAGS - -printf "%s\n" "#define CONFIGURE_PARAMS \"$*\"" >>confdefs.h +KNOT_VERSION_MINOR=4 - -printf "%s\n" "#define CONFIGURE_CFLAGS \"$CFLAGS\"" >>confdefs.h +KNOT_VERSION_PATCH=0 ac_config_files="$ac_config_files src/libknot/version.h src/libdnssec/version.h src/libzscanner/version.h" @@ -15272,6 +15260,15 @@ else HAVE_UTILS_FALSE= fi + if test "$enable_utilities" != "no" -o \ + "$enable_daemon" != "no"; then + HAVE_LIBUTILS_TRUE= + HAVE_LIBUTILS_FALSE='#' +else + HAVE_LIBUTILS_TRUE='#' + HAVE_LIBUTILS_FALSE= +fi + # Build Knot DNS documentation # Check whether --enable-documentation was given. @@ -15282,6 +15279,110 @@ else $as_nop enable_documentation=yes fi +if test "$enable_documentation" = "yes" +then : + + # Extract the first word of "sphinx-build", so it can be a program name with args. +set dummy sphinx-build; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_SPHINXBUILD+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $SPHINXBUILD in + [\\/]* | ?:[\\/]*) + ac_cv_path_SPHINXBUILD="$SPHINXBUILD" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_SPHINXBUILD="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_SPHINXBUILD" && ac_cv_path_SPHINXBUILD="false" + ;; +esac +fi +SPHINXBUILD=$ac_cv_path_SPHINXBUILD +if test -n "$SPHINXBUILD"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SPHINXBUILD" >&5 +printf "%s\n" "$SPHINXBUILD" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + if test "$SPHINXBUILD" = "false" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing 'sphinx-build' executable for documentation generation" >&5 +printf "%s\n" "$as_me: WARNING: missing 'sphinx-build' executable for documentation generation" >&2;} + enable_documentation=no + +fi + # Extract the first word of "pdflatex", so it can be a program name with args. +set dummy pdflatex; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PDFLATEX+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $PDFLATEX in + [\\/]* | ?:[\\/]*) + ac_cv_path_PDFLATEX="$PDFLATEX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PDFLATEX="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PDFLATEX" && ac_cv_path_PDFLATEX="false" + ;; +esac +fi +PDFLATEX=$ac_cv_path_PDFLATEX +if test -n "$PDFLATEX"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PDFLATEX" >&5 +printf "%s\n" "$PDFLATEX" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +fi if test "$enable_documentation" = "yes"; then HAVE_DOCS_TRUE= HAVE_DOCS_FALSE='#' @@ -15290,16 +15391,15 @@ else HAVE_DOCS_FALSE= fi - - if test "$enable_utilities" != "no" -o \ - "$enable_daemon" != "no"; then - HAVE_LIBUTILS_TRUE= - HAVE_LIBUTILS_FALSE='#' + if test "$PDFLATEX" != "false"; then + HAVE_PDFLATEX_TRUE= + HAVE_PDFLATEX_FALSE='#' else - HAVE_LIBUTILS_TRUE='#' - HAVE_LIBUTILS_FALSE= + HAVE_PDFLATEX_TRUE='#' + HAVE_PDFLATEX_FALSE= fi + ###################### # Generic dependencies ###################### @@ -15410,19 +15510,19 @@ esac pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gnutls >= 3.3" >&5 -printf %s "checking for gnutls >= 3.3... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gnutls >= 3.6.10" >&5 +printf %s "checking for gnutls >= 3.6.10... " >&6; } if test -n "$gnutls_CFLAGS"; then pkg_cv_gnutls_CFLAGS="$gnutls_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 3.3\""; } >&5 - ($PKG_CONFIG --exists --print-errors "gnutls >= 3.3") 2>&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 3.6.10\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gnutls >= 3.6.10") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_gnutls_CFLAGS=`$PKG_CONFIG --cflags "gnutls >= 3.3" 2>/dev/null` + pkg_cv_gnutls_CFLAGS=`$PKG_CONFIG --cflags "gnutls >= 3.6.10" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -15434,12 +15534,12 @@ if test -n "$gnutls_LIBS"; then pkg_cv_gnutls_LIBS="$gnutls_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 3.3\""; } >&5 - ($PKG_CONFIG --exists --print-errors "gnutls >= 3.3") 2>&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 3.6.10\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gnutls >= 3.6.10") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_gnutls_LIBS=`$PKG_CONFIG --libs "gnutls >= 3.3" 2>/dev/null` + pkg_cv_gnutls_LIBS=`$PKG_CONFIG --libs "gnutls >= 3.6.10" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -15460,14 +15560,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - gnutls_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gnutls >= 3.3" 2>&1` + gnutls_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gnutls >= 3.6.10" 2>&1` else - gnutls_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gnutls >= 3.3" 2>&1` + gnutls_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gnutls >= 3.6.10" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$gnutls_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements (gnutls >= 3.3) were not met: + as_fn_error $? "Package requirements (gnutls >= 3.6.10) were not met: $gnutls_PKG_ERRORS @@ -15516,18 +15616,6 @@ then : printf "%s\n" "#define ENABLE_PKCS11 1" >>confdefs.h -fi - - ac_fn_check_decl "$LINENO" "GNUTLS_PK_EDDSA_ED25519" "ac_cv_have_decl_GNUTLS_PK_EDDSA_ED25519" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_GNUTLS_PK_EDDSA_ED25519" = xyes -then : - -printf "%s\n" "#define HAVE_ED25519 1" >>confdefs.h - - enable_ed25519=yes -else $as_nop - enable_ed25519=no fi ac_fn_check_decl "$LINENO" "GNUTLS_SIGN_EDDSA_ED448" "ac_cv_have_decl_GNUTLS_SIGN_EDDSA_ED448" "#include @@ -15542,56 +15630,6 @@ else $as_nop enable_ed448=no fi - ac_fn_check_decl "$LINENO" "GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE" "ac_cv_have_decl_GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE" = xyes -then : - -printf "%s\n" "#define HAVE_GNUTLS_REPRODUCIBLE 1" >>confdefs.h - - # Ensure the version is at least 3.6.10 - ac_fn_c_check_func "$LINENO" "gnutls_aead_cipher_encryptv2" "ac_cv_func_gnutls_aead_cipher_encryptv2" -if test "x$ac_cv_func_gnutls_aead_cipher_encryptv2" = xyes -then : - enable_repro_signing=yes -else $as_nop - enable_repro_signing=no -fi - -else $as_nop - enable_repro_signing=no -fi - - ac_fn_c_check_func "$LINENO" "gnutls_privkey_sign_data2" "ac_cv_func_gnutls_privkey_sign_data2" -if test "x$ac_cv_func_gnutls_privkey_sign_data2" = xyes -then : - -printf "%s\n" "#define HAVE_SIGN_DATA2 1" >>confdefs.h - -fi - - - ac_fn_c_check_func "$LINENO" "gnutls_privkey_export_x509" "ac_cv_func_gnutls_privkey_export_x509" -if test "x$ac_cv_func_gnutls_privkey_export_x509" = xyes -then : - -printf "%s\n" "#define HAVE_EXPORT_X509 1" >>confdefs.h - -fi - - - ac_fn_c_check_func "$LINENO" "gnutls_memset" "ac_cv_func_gnutls_memset" -if test "x$ac_cv_func_gnutls_memset" = xyes -then : - -printf "%s\n" "#define HAVE_GNUTLS_MEMSET 1" >>confdefs.h - - gnutls_memset=yes -else $as_nop - gnutls_memset=no -fi - - ac_fn_c_check_func "$LINENO" "gnutls_early_cipher_get" "ac_cv_func_gnutls_early_cipher_get" if test "x$ac_cv_func_gnutls_early_cipher_get" = xyes then : @@ -15972,6 +16010,15 @@ else $as_nop fi +# Check whether --enable-dbus was given. +if test ${enable_dbus+y} +then : + enableval=$enable_dbus; enable_dbus="$enableval" +else $as_nop + enable_dbus=auto +fi + + if test "$enable_daemon" = "yes" then : @@ -16462,55 +16509,226 @@ then : printf "%s\n" "#define ENABLE_SYSTEMD 1" >>confdefs.h - ac_fn_c_check_header_compile "$LINENO" "systemd/sd-bus.h" "ac_cv_header_systemd_sd_bus_h" "$ac_includes_default" -if test "x$ac_cv_header_systemd_sd_bus_h" = xyes +fi + +if test "$enable_dbus" != "no" +then : + + case $enable_dbus in #( + auto) : + if test "$enable_systemd" = "yes" then : -printf "%s\n" "#define ENABLE_DBUS 1" >>confdefs.h +printf "%s\n" "#define ENABLE_DBUS_SYSTEMD 1" >>confdefs.h + enable_dbus=systemd else $as_nop - enable_systemd="yes (without D-Bus)" -fi +pkg_failed=no +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dbus-1" >&5 +printf %s "checking for dbus-1... " >&6; } +if test -n "$libdbus_CFLAGS"; then + pkg_cv_libdbus_CFLAGS="$libdbus_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_libdbus_CFLAGS=`$PKG_CONFIG --cflags "dbus-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$libdbus_LIBS"; then + pkg_cv_libdbus_LIBS="$libdbus_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_libdbus_LIBS=`$PKG_CONFIG --libs "dbus-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried fi -fi -# Socket polling method -socket_polling= -# Check whether --with-socket-polling was given. -if test ${with_socket_polling+y} -then : - withval=$with_socket_polling; socket_polling=$withval -else $as_nop - socket_polling=auto +if test $pkg_failed = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no fi + if test $_pkg_short_errors_supported = yes; then + libdbus_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "dbus-1" 2>&1` + else + libdbus_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "dbus-1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$libdbus_PKG_ERRORS" >&5 + enable_dbus=no +elif test $pkg_failed = untried; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + enable_dbus=no +else + libdbus_CFLAGS=$pkg_cv_libdbus_CFLAGS + libdbus_LIBS=$pkg_cv_libdbus_LIBS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } -case $socket_polling in #( - auto) : +printf "%s\n" "#define ENABLE_DBUS_LIBDBUS 1" >>confdefs.h - for ac_func in kqueue -do : - ac_fn_c_check_func "$LINENO" "kqueue" "ac_cv_func_kqueue" -if test "x$ac_cv_func_kqueue" = xyes + enable_dbus=libdbus +fi +fi ;; #( + systemd) : + if test "$enable_systemd" = "yes" then : - printf "%s\n" "#define HAVE_KQUEUE 1" >>confdefs.h -printf "%s\n" "#define HAVE_KQUEUE 1" >>confdefs.h +printf "%s\n" "#define ENABLE_DBUS_SYSTEMD 1" >>confdefs.h - socket_polling=kqueue + enable_dbus=systemd else $as_nop + as_fn_error $? "systemd >= 221 not available." "$LINENO" 5 +fi ;; #( + libdbus) : - for ac_func in epoll_create -do : - ac_fn_c_check_func "$LINENO" "epoll_create" "ac_cv_func_epoll_create" -if test "x$ac_cv_func_epoll_create" = xyes -then : - printf "%s\n" "#define HAVE_EPOLL_CREATE 1" >>confdefs.h +pkg_failed=no +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dbus-1" >&5 +printf %s "checking for dbus-1... " >&6; } + +if test -n "$libdbus_CFLAGS"; then + pkg_cv_libdbus_CFLAGS="$libdbus_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_libdbus_CFLAGS=`$PKG_CONFIG --cflags "dbus-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$libdbus_LIBS"; then + pkg_cv_libdbus_LIBS="$libdbus_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_libdbus_LIBS=`$PKG_CONFIG --libs "dbus-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + libdbus_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "dbus-1" 2>&1` + else + libdbus_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "dbus-1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$libdbus_PKG_ERRORS" >&5 + + as_fn_error $? "libdbus not available." "$LINENO" 5 +elif test $pkg_failed = untried; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + as_fn_error $? "libdbus not available." "$LINENO" 5 +else + libdbus_CFLAGS=$pkg_cv_libdbus_CFLAGS + libdbus_LIBS=$pkg_cv_libdbus_LIBS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + +printf "%s\n" "#define ENABLE_DBUS_LIBDBUS 1" >>confdefs.h + + enable_dbus=libdbus +fi ;; #( + no) : + enable_dbus=no ;; #( + *) : + as_fn_error $? "Invalid value of --enable-dbus." "$LINENO" 5 ;; #( + *) : + ;; +esac + +fi + + +fi +# Socket polling method +socket_polling= + +# Check whether --with-socket-polling was given. +if test ${with_socket_polling+y} +then : + withval=$with_socket_polling; socket_polling=$withval +else $as_nop + socket_polling=auto + +fi + + +case $socket_polling in #( + auto) : + + for ac_func in kqueue +do : + ac_fn_c_check_func "$LINENO" "kqueue" "ac_cv_func_kqueue" +if test "x$ac_cv_func_kqueue" = xyes +then : + printf "%s\n" "#define HAVE_KQUEUE 1" >>confdefs.h + +printf "%s\n" "#define HAVE_KQUEUE 1" >>confdefs.h + + socket_polling=kqueue +else $as_nop + + for ac_func in epoll_create +do : + ac_fn_c_check_func "$LINENO" "epoll_create" "ac_cv_func_epoll_create" +if test "x$ac_cv_func_epoll_create" = xyes +then : + printf "%s\n" "#define HAVE_EPOLL_CREATE 1" >>confdefs.h printf "%s\n" "#define HAVE_EPOLL 1" >>confdefs.h @@ -16666,21 +16884,10 @@ then : fi - -# Check whether --with-urcu was given. -if test ${with_urcu+y} -then : - withval=$with_urcu; -fi - - if test "$enable_daemon" = "yes" then : -if test "$with_urcu" != "no" -then : - pkg_failed=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for liburcu" >&5 @@ -16741,217 +16948,13 @@ fi echo "$liburcu_PKG_ERRORS" >&5 - for try_urcu in "$with_urcu" "" "/usr/local"; do - save_LIBS="$LIBS" - save_CPPFLAGS="$CPPFLAGS" - - if test -d "$try_urcu" -then : - - liburcu_CFLAGS="-I$try_urcu/include" - liburcu_LIBS="-L$try_urcu/lib" - -else $as_nop - - liburcu_CFLAGS="" - liburcu_LIBS="" - -fi - - CPPFLAGS="$CPPFLAGS $liburcu_CFLAGS" - LIBS="$LIBS $liburcu_LIBS" - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing rcu_set_pointer_sym" >&5 -printf %s "checking for library containing rcu_set_pointer_sym... " >&6; } -if test ${ac_cv_search_rcu_set_pointer_sym+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -char rcu_set_pointer_sym (); -int -main (void) -{ -return rcu_set_pointer_sym (); - ; - return 0; -} -_ACEOF -for ac_lib in '' urcu -do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO" -then : - ac_cv_search_rcu_set_pointer_sym=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext - if test ${ac_cv_search_rcu_set_pointer_sym+y} -then : - break -fi -done -if test ${ac_cv_search_rcu_set_pointer_sym+y} -then : - -else $as_nop - ac_cv_search_rcu_set_pointer_sym=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_rcu_set_pointer_sym" >&5 -printf "%s\n" "$ac_cv_search_rcu_set_pointer_sym" >&6; } -ac_res=$ac_cv_search_rcu_set_pointer_sym -if test "$ac_res" != no -then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - - with_urcu=yes - liburcu_LIBS="$liburcu_LIBS -lurcu" - - - break - -else $as_nop - - CPPFLAGS="$save_CPPFLAGS" - LIBS="$save_LIBS" - with_urcu=no - # do not cache result of AC_SEARCH_LIBS test - unset ac_cv_search_rcu_set_pointer_sym - -fi - - done - CPPFLAGS="$save_CPPFLAGS" - LIBS="$save_LIBS" - - if test "$with_urcu" = "no" -then : - - as_fn_error $? "liburcu is required" "$LINENO" 5 - -fi + as_fn_error $? "liburcu not found" "$LINENO" 5 elif test $pkg_failed = untried; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - for try_urcu in "$with_urcu" "" "/usr/local"; do - save_LIBS="$LIBS" - save_CPPFLAGS="$CPPFLAGS" - - if test -d "$try_urcu" -then : - - liburcu_CFLAGS="-I$try_urcu/include" - liburcu_LIBS="-L$try_urcu/lib" - -else $as_nop - - liburcu_CFLAGS="" - liburcu_LIBS="" - -fi - - CPPFLAGS="$CPPFLAGS $liburcu_CFLAGS" - LIBS="$LIBS $liburcu_LIBS" - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing rcu_set_pointer_sym" >&5 -printf %s "checking for library containing rcu_set_pointer_sym... " >&6; } -if test ${ac_cv_search_rcu_set_pointer_sym+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -char rcu_set_pointer_sym (); -int -main (void) -{ -return rcu_set_pointer_sym (); - ; - return 0; -} -_ACEOF -for ac_lib in '' urcu -do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO" -then : - ac_cv_search_rcu_set_pointer_sym=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext - if test ${ac_cv_search_rcu_set_pointer_sym+y} -then : - break -fi -done -if test ${ac_cv_search_rcu_set_pointer_sym+y} -then : - -else $as_nop - ac_cv_search_rcu_set_pointer_sym=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_rcu_set_pointer_sym" >&5 -printf "%s\n" "$ac_cv_search_rcu_set_pointer_sym" >&6; } -ac_res=$ac_cv_search_rcu_set_pointer_sym -if test "$ac_res" != no -then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - - with_urcu=yes - liburcu_LIBS="$liburcu_LIBS -lurcu" - - - break - -else $as_nop - - CPPFLAGS="$save_CPPFLAGS" - LIBS="$save_LIBS" - with_urcu=no - # do not cache result of AC_SEARCH_LIBS test - unset ac_cv_search_rcu_set_pointer_sym - -fi - - done - CPPFLAGS="$save_CPPFLAGS" - LIBS="$save_LIBS" - - if test "$with_urcu" = "no" -then : - - as_fn_error $? "liburcu is required" "$LINENO" 5 - -fi + as_fn_error $? "liburcu not found" "$LINENO" 5 else liburcu_CFLAGS=$pkg_cv_liburcu_CFLAGS @@ -16959,12 +16962,6 @@ else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } - liburcu_PKGCONFIG="liburcu >= 0.4.0" - - with_urcu=yes - -fi - fi @@ -19226,185 +19223,17 @@ fi echo "$libidn2_PKG_ERRORS" >&5 + with_libidn=no + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: libidn2 not found" >&5 +printf "%s\n" "$as_me: WARNING: libidn2 not found" >&2;} -pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libidn >= 0.0.0" >&5 -printf %s "checking for libidn >= 0.0.0... " >&6; } +elif test $pkg_failed = untried; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } -if test -n "$libidn_CFLAGS"; then - pkg_cv_libidn_CFLAGS="$libidn_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libidn >= 0.0.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libidn >= 0.0.0") 2>&5 - ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_libidn_CFLAGS=`$PKG_CONFIG --cflags "libidn >= 0.0.0" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$libidn_LIBS"; then - pkg_cv_libidn_LIBS="$libidn_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libidn >= 0.0.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libidn >= 0.0.0") 2>&5 - ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_libidn_LIBS=`$PKG_CONFIG --libs "libidn >= 0.0.0" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - libidn_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libidn >= 0.0.0" 2>&1` - else - libidn_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libidn >= 0.0.0" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$libidn_PKG_ERRORS" >&5 - - - with_libidn=no - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: libidn2 or libidn not found" >&5 -printf "%s\n" "$as_me: WARNING: libidn2 or libidn not found" >&2;} - -elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - - with_libidn=no - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: libidn2 or libidn not found" >&5 -printf "%s\n" "$as_me: WARNING: libidn2 or libidn not found" >&2;} - -else - libidn_CFLAGS=$pkg_cv_libidn_CFLAGS - libidn_LIBS=$pkg_cv_libidn_LIBS - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - - with_libidn=libidn - -printf "%s\n" "#define LIBIDN 1" >>confdefs.h - - -printf "%s\n" "#define LIBIDN_HEADER " >>confdefs.h - - -fi - -elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - - -pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libidn >= 0.0.0" >&5 -printf %s "checking for libidn >= 0.0.0... " >&6; } - -if test -n "$libidn_CFLAGS"; then - pkg_cv_libidn_CFLAGS="$libidn_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libidn >= 0.0.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libidn >= 0.0.0") 2>&5 - ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_libidn_CFLAGS=`$PKG_CONFIG --cflags "libidn >= 0.0.0" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$libidn_LIBS"; then - pkg_cv_libidn_LIBS="$libidn_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libidn >= 0.0.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libidn >= 0.0.0") 2>&5 - ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_libidn_LIBS=`$PKG_CONFIG --libs "libidn >= 0.0.0" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - libidn_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libidn >= 0.0.0" 2>&1` - else - libidn_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libidn >= 0.0.0" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$libidn_PKG_ERRORS" >&5 - - - with_libidn=no - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: libidn2 or libidn not found" >&5 -printf "%s\n" "$as_me: WARNING: libidn2 or libidn not found" >&2;} - -elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - - with_libidn=no - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: libidn2 or libidn not found" >&5 -printf "%s\n" "$as_me: WARNING: libidn2 or libidn not found" >&2;} - -else - libidn_CFLAGS=$pkg_cv_libidn_CFLAGS - libidn_LIBS=$pkg_cv_libidn_LIBS - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - - with_libidn=libidn - -printf "%s\n" "#define LIBIDN 1" >>confdefs.h - - -printf "%s\n" "#define LIBIDN_HEADER " >>confdefs.h - - -fi + with_libidn=no + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: libidn2 not found" >&5 +printf "%s\n" "$as_me: WARNING: libidn2 not found" >&2;} else libidn2_CFLAGS=$pkg_cv_libidn2_CFLAGS @@ -19417,9 +19246,6 @@ printf "%s\n" "yes" >&6; } printf "%s\n" "#define LIBIDN 1" >>confdefs.h -printf "%s\n" "#define LIBIDN_HEADER " >>confdefs.h - - fi fi @@ -20245,7 +20071,6 @@ fi - # Checks for optional library functions. ac_fn_c_check_func "$LINENO" "accept4" "ac_cv_func_accept4" if test "x$ac_cv_func_accept4" = xyes @@ -20330,7 +20155,7 @@ else $as_nop fi - if test "$explicit_bzero" = "no" -a "$explicit_memset" = "no" -a "$gnutls_memset" = "yes"; then + if test "$explicit_bzero" = "no" -a "$explicit_memset" = "no"; then USE_GNUTLS_MEMSET_TRUE= USE_GNUTLS_MEMSET_FALSE='#' else @@ -20409,14 +20234,19 @@ fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext -# Check for '__atomic' compiler builtin atomic functions. +# Check for a C11 or GCC-style '__atomic' compiler builtin atomic functions. +atomic_type="none" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +#if (__STDC_VERSION__ < 201112L) || defined(__STDC_NO_ATOMICS__) + #error "No C11 atomics" + #endif + #include int main (void) { -uint64_t val = 0; __atomic_add_fetch(&val, 1, __ATOMIC_RELAXED); +atomic_uint_fast64_t val = 0; + atomic_fetch_add_explicit(&val, 1, memory_order_relaxed); ; return 0; } @@ -20424,21 +20254,17 @@ _ACEOF if ac_fn_c_try_link "$LINENO" then : -printf "%s\n" "#define HAVE_ATOMIC 1" >>confdefs.h +printf "%s\n" "#define HAVE_C11_ATOMIC 1" >>confdefs.h - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext - -# Check for '__sync' compiler builtin atomic functions. -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + atomic_type="C11" +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { -int val = 0; __sync_add_and_fetch(&val, 1); +uint64_t val = 0; __atomic_add_fetch(&val, 1, __ATOMIC_RELAXED); ; return 0; } @@ -20446,8 +20272,13 @@ _ACEOF if ac_fn_c_try_link "$LINENO" then : -printf "%s\n" "#define HAVE_SYNC_ATOMIC 1" >>confdefs.h +printf "%s\n" "#define HAVE_GCC_ATOMIC 1" >>confdefs.h + atomic_type="__atomic" + +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ @@ -20799,191 +20630,15 @@ else fi -if test "$enable_documentation" = "yes" -then : - - -# Extract the first word of "sphinx-build", so it can be a program name with args. -set dummy sphinx-build; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_SPHINXBUILD+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $SPHINXBUILD in - [\\/]* | ?:[\\/]*) - ac_cv_path_SPHINXBUILD="$SPHINXBUILD" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_SPHINXBUILD="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - test -z "$ac_cv_path_SPHINXBUILD" && ac_cv_path_SPHINXBUILD="false" - ;; -esac -fi -SPHINXBUILD=$ac_cv_path_SPHINXBUILD -if test -n "$SPHINXBUILD"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SPHINXBUILD" >&5 -printf "%s\n" "$SPHINXBUILD" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - -if test "$SPHINXBUILD" = "false" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing 'sphinx-build' executable for documentation generation" >&5 -printf "%s\n" "$as_me: WARNING: missing 'sphinx-build' executable for documentation generation" >&2;} - -fi -# Extract the first word of "pdflatex", so it can be a program name with args. -set dummy pdflatex; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_PDFLATEX+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $PDFLATEX in - [\\/]* | ?:[\\/]*) - ac_cv_path_PDFLATEX="$PDFLATEX" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_PDFLATEX="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - test -z "$ac_cv_path_PDFLATEX" && ac_cv_path_PDFLATEX="false" - ;; -esac -fi -PDFLATEX=$ac_cv_path_PDFLATEX -if test -n "$PDFLATEX"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PDFLATEX" >&5 -printf "%s\n" "$PDFLATEX" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - -# Extract the first word of "makeinfo", so it can be a program name with args. -set dummy makeinfo; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_MAKEINFO+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $MAKEINFO in - [\\/]* | ?:[\\/]*) - ac_cv_path_MAKEINFO="$MAKEINFO" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_MAKEINFO="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - test -z "$ac_cv_path_MAKEINFO" && ac_cv_path_MAKEINFO="false" - ;; -esac -fi -MAKEINFO=$ac_cv_path_MAKEINFO -if test -n "$MAKEINFO"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAKEINFO" >&5 -printf "%s\n" "$MAKEINFO" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - - - -fi - - if test "$SPHINXBUILD" != "false"; then - HAVE_SPHINXBUILD_TRUE= - HAVE_SPHINXBUILD_FALSE='#' -else - HAVE_SPHINXBUILD_TRUE='#' - HAVE_SPHINXBUILD_FALSE= -fi - - if test "$PDFLATEX" != "false"; then - HAVE_PDFLATEX_TRUE= - HAVE_PDFLATEX_FALSE='#' -else - HAVE_PDFLATEX_TRUE='#' - HAVE_PDFLATEX_FALSE= -fi - - if test "$MAKEINFO" != "false"; then - HAVE_MAKEINFO_TRUE= - HAVE_MAKEINFO_FALSE='#' -else - HAVE_MAKEINFO_TRUE='#' - HAVE_MAKEINFO_FALSE= -fi - - # Strip -fdebug-prefix-map= parameters from flags for better reproducibility of binaries. filtered_cflags=$(echo -n "$CFLAGS" | \ sed 's/[^[:alnum:]]-f[^[:space:]]*-prefix-map=[^[:space:]]*//g') filtered_cppflags=$(echo -n "$CPPFLAGS" | \ sed 's/[^[:alnum:]]-f[^[:space:]]*-prefix-map=[^[:space:]]*//g') +filtered_config_params=$(echo -n "$ac_configure_args" | \ + sed 's/[^[:alnum:]]-f[^[:space:]]*-prefix-map=[^[:space:]]*//g') -result_msg_base=" Knot DNS $VERSION - +result_msg_base=" Target: $host_os $host_cpu $endianity Compiler: ${CC} CFLAGS: ${filtered_cflags} ${filtered_cppflags} @@ -21013,6 +20668,7 @@ result_msg_base=" Knot DNS $VERSION XDP support: ${enable_xdp} DoQ support: ${enable_quic} Socket polling: ${socket_polling} + Atomic support: ${atomic_type} Memory allocator: ${with_memory_allocator} Fast zone parser: ${enable_fastparser} Utilities with IDN: ${with_libidn} @@ -21020,17 +20676,17 @@ result_msg_base=" Knot DNS $VERSION Utilities with Dnstap: ${enable_dnstap} MaxMind DB support: ${enable_maxminddb} Systemd integration: ${enable_systemd} + D-Bus support: ${enable_dbus} POSIX capabilities: ${enable_cap_ng} PKCS #11 support: ${enable_pkcs11} - Ed25519 support: ${enable_ed25519} Ed448 support: ${enable_ed448} - Reproducible signing: ${enable_repro_signing} + Code coverage: ${enable_code_coverage} Sanitizer: ${with_sanitizer} LibFuzzer: ${with_fuzzer} OSS-Fuzz: ${with_oss_fuzz}" -result_msg_esc=$(echo -n "$result_msg_base" | sed '$!s/$/\\n/' | tr -d '\n') +result_msg_esc=$(echo -n " Configure:$filtered_config_params\n$result_msg_base" | sed '$!s/$/\\n/' | tr -d '\n') printf "%s\n" "#define CONFIGURE_SUMMARY \"$result_msg_esc\"" >>confdefs.h @@ -21188,12 +20844,16 @@ if test -z "${HAVE_UTILS_TRUE}" && test -z "${HAVE_UTILS_FALSE}"; then as_fn_error $? "conditional \"HAVE_UTILS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${HAVE_LIBUTILS_TRUE}" && test -z "${HAVE_LIBUTILS_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LIBUTILS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${HAVE_DOCS_TRUE}" && test -z "${HAVE_DOCS_FALSE}"; then as_fn_error $? "conditional \"HAVE_DOCS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_LIBUTILS_TRUE}" && test -z "${HAVE_LIBUTILS_FALSE}"; then - as_fn_error $? "conditional \"HAVE_LIBUTILS\" was never defined. +if test -z "${HAVE_PDFLATEX_TRUE}" && test -z "${HAVE_PDFLATEX_FALSE}"; then + as_fn_error $? "conditional \"HAVE_PDFLATEX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${FAST_PARSER_TRUE}" && test -z "${FAST_PARSER_FALSE}"; then @@ -21348,18 +21008,6 @@ if test -z "${OSS_FUZZ_TRUE}" && test -z "${OSS_FUZZ_FALSE}"; then as_fn_error $? "conditional \"OSS_FUZZ\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${HAVE_SPHINXBUILD_TRUE}" && test -z "${HAVE_SPHINXBUILD_FALSE}"; then - as_fn_error $? "conditional \"HAVE_SPHINXBUILD\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${HAVE_PDFLATEX_TRUE}" && test -z "${HAVE_PDFLATEX_FALSE}"; then - as_fn_error $? "conditional \"HAVE_PDFLATEX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${HAVE_MAKEINFO_TRUE}" && test -z "${HAVE_MAKEINFO_FALSE}"; then - as_fn_error $? "conditional \"HAVE_MAKEINFO\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 @@ -21750,7 +21398,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by knot $as_me 3.3.9, which was +This file was extended by knot $as_me 3.4.0, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -21818,7 +21466,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -knot config.status 3.3.9 +knot config.status 3.4.0 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" @@ -23543,9 +23191,11 @@ printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: + Knot DNS $VERSION $result_msg_base " >&5 printf "%s\n" " + Knot DNS $VERSION $result_msg_base " >&6; } diff --git a/configure.ac b/configure.ac index 5a7ef6f..eb11c14 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ AC_PREREQ([2.69]) m4_define([knot_VERSION_MAJOR], 3)dnl -m4_define([knot_VERSION_MINOR], 3)dnl -m4_define([knot_VERSION_PATCH], 9)dnl Leave empty if the master branch! +m4_define([knot_VERSION_MINOR], 4)dnl +m4_define([knot_VERSION_PATCH], 0)dnl Leave empty if the master branch! m4_include([m4/knot-version.m4]) AC_INIT([knot], [knot_PKG_VERSION], [knot-dns@labs.nic.cz]) @@ -16,7 +16,7 @@ AC_CANONICAL_HOST # Update library versions # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -KNOT_LIB_VERSION([libknot], 14, 0, 0) +KNOT_LIB_VERSION([libknot], 15, 0, 0) KNOT_LIB_VERSION([libdnssec], 9, 0, 0) KNOT_LIB_VERSION([libzscanner], 4, 0, 0) @@ -24,10 +24,6 @@ AC_SUBST([KNOT_VERSION_MAJOR], knot_VERSION_MAJOR) AC_SUBST([KNOT_VERSION_MINOR], knot_VERSION_MINOR) AC_SUBST([KNOT_VERSION_PATCH], knot_VERSION_PATCH) -# Store ./configure parameters and CFLAGS -AC_DEFINE_UNQUOTED([CONFIGURE_PARAMS],["$*"],[Params passed to configure]) -AC_DEFINE_UNQUOTED([CONFIGURE_CFLAGS],["$CFLAGS"],[Passed CFLAGS from environment]) - AC_CONFIG_FILES([src/libknot/version.h src/libdnssec/version.h src/libzscanner/version.h]) @@ -119,14 +115,23 @@ AC_ARG_ENABLE([modules], AC_ARG_ENABLE([utilities], AS_HELP_STRING([--disable-utilities], [Don't build Knot DNS utilities]), [], [enable_utilities=yes]) AM_CONDITIONAL([HAVE_UTILS], [test "$enable_utilities" = "yes"]) +AM_CONDITIONAL([HAVE_LIBUTILS], test "$enable_utilities" != "no" -o \ + "$enable_daemon" != "no") # Build Knot DNS documentation AC_ARG_ENABLE([documentation], AS_HELP_STRING([--disable-documentation], [Don't build Knot DNS documentation]), [], [enable_documentation=yes]) +AS_IF([test "$enable_documentation" = "yes"], [ + AC_PATH_PROG([SPHINXBUILD], [sphinx-build], [false]) + AS_IF([test "$SPHINXBUILD" = "false"], + [AC_MSG_WARN([missing 'sphinx-build' executable for documentation generation]) + enable_documentation=no] + ) + AC_PATH_PROG([PDFLATEX], [pdflatex], [false]) +]) AM_CONDITIONAL([HAVE_DOCS], [test "$enable_documentation" = "yes"]) +AM_CONDITIONAL([HAVE_PDFLATEX], test "$PDFLATEX" != "false") -AM_CONDITIONAL([HAVE_LIBUTILS], test "$enable_utilities" != "no" -o \ - "$enable_daemon" != "no") ###################### # Generic dependencies ###################### @@ -138,7 +143,7 @@ AC_ARG_ENABLE([fastparser], AM_CONDITIONAL([FAST_PARSER], [test "$enable_fastparser" = "yes"]) # GnuTLS crypto backend -PKG_CHECK_MODULES([gnutls], [gnutls >= 3.3], [ +PKG_CHECK_MODULES([gnutls], [gnutls >= 3.6.10], [ save_CFLAGS=$CFLAGS save_LIBS=$LIBS CFLAGS="$CFLAGS $gnutls_CFLAGS" @@ -148,35 +153,12 @@ PKG_CHECK_MODULES([gnutls], [gnutls >= 3.3], [ AS_IF([test "$enable_pkcs11" = yes], [AC_DEFINE([ENABLE_PKCS11], [1], [PKCS #11 support available])]) - AC_CHECK_DECL([GNUTLS_PK_EDDSA_ED25519], - [AC_DEFINE([HAVE_ED25519], [1], [GnuTLS ED25519 support available]) - enable_ed25519=yes], - [enable_ed25519=no], - [#include ]) - AC_CHECK_DECL([GNUTLS_SIGN_EDDSA_ED448], [AC_DEFINE([HAVE_ED448], [1], [GnuTLS ED448 support available]) enable_ed448=yes], [enable_ed448=no], [#include ]) - AC_CHECK_DECL([GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE], - [AC_DEFINE([HAVE_GNUTLS_REPRODUCIBLE], [1], [GnuTLS reproducible signing available]) - # Ensure the version is at least 3.6.10 - AC_CHECK_FUNC([gnutls_aead_cipher_encryptv2], [enable_repro_signing=yes], [enable_repro_signing=no])], - [enable_repro_signing=no], - [#include ]) - - AC_CHECK_FUNC([gnutls_privkey_sign_data2], - [AC_DEFINE([HAVE_SIGN_DATA2], [1], [gnutls_privkey_sign_data2 available])]) - - AC_CHECK_FUNC([gnutls_privkey_export_x509], - [AC_DEFINE([HAVE_EXPORT_X509], [1], [gnutls_privkey_export_x509 available])]) - - AC_CHECK_FUNC([gnutls_memset], - [AC_DEFINE([HAVE_GNUTLS_MEMSET], [1], [gnutls_memset available]) - gnutls_memset=yes], [gnutls_memset=no]) - AC_CHECK_FUNC([gnutls_early_cipher_get], [AC_DEFINE([HAVE_GNUTLS_QUIC], [1], [gnutls_early_cipher_get available]) gnutls_quic=yes], [gnutls_quic=no]) @@ -281,6 +263,10 @@ AC_ARG_ENABLE([systemd], AS_HELP_STRING([--enable-systemd=auto|yes|no], [enable systemd integration [default=auto]]), [enable_systemd="$enableval"], [enable_systemd=auto]) +AC_ARG_ENABLE([dbus], + AS_HELP_STRING([--enable-dbus=auto|systemd|libdbus|no], [enable D-bus support [default=auto]]), + [enable_dbus="$enableval"], [enable_dbus=auto]) + AS_IF([test "$enable_daemon" = "yes"],[ AS_IF([test "$enable_systemd" != "no"],[ @@ -293,11 +279,28 @@ AS_IF([test "$enable_systemd" != "no"],[ ]) AS_IF([test "$enable_systemd" = "yes"],[ - AC_DEFINE([ENABLE_SYSTEMD], [1], [Use systemd integration.]) - AC_CHECK_HEADER([systemd/sd-bus.h], - [AC_DEFINE([ENABLE_DBUS], [1], [systemd D-Bus available])], - [enable_systemd="yes (without D-Bus)"]) -]) + AC_DEFINE([ENABLE_SYSTEMD], [1], [Use systemd integration.])]) + +AS_IF([test "$enable_dbus" != "no"],[ + AS_CASE([$enable_dbus], + [auto],[AS_IF([test "$enable_systemd" = "yes"], + [AC_DEFINE([ENABLE_DBUS_SYSTEMD], [1], [systemd D-Bus available]) + enable_dbus=systemd], + [PKG_CHECK_MODULES([libdbus], [dbus-1], + [AC_DEFINE([ENABLE_DBUS_LIBDBUS], [1], [libdbus D-Bus available]) + enable_dbus=libdbus], + [enable_dbus=no])])], + [systemd],[AS_IF([test "$enable_systemd" = "yes"], + [AC_DEFINE([ENABLE_DBUS_SYSTEMD], [1], [systemd D-Bus available]) + enable_dbus=systemd], + [AC_MSG_ERROR([systemd >= 221 not available.])])], + [libdbus],[PKG_CHECK_MODULES([libdbus], [dbus-1], + [AC_DEFINE([ENABLE_DBUS_LIBDBUS], [1], [libdbus D-Bus available]) + enable_dbus=libdbus], + [AC_MSG_ERROR([libdbus not available.])])], + [no],[enable_dbus=no], + [*],[AC_MSG_ERROR([Invalid value of --enable-dbus.])]) + ]) ]) dnl enable_daemon @@ -347,54 +350,10 @@ AC_ARG_WITH([memory-allocator], AS_IF([test "$with_memory_allocator" = ""], [with_memory_allocator="auto"]) AC_SUBST([malloc_LIBS]) -dnl Check for userspace-rcu library -AC_ARG_WITH(urcu, -[ --with-urcu=DIR where to find userspace-rcu library]) - AS_IF([test "$enable_daemon" = "yes"],[ -AS_IF([test "$with_urcu" != "no"], [ - PKG_CHECK_MODULES([liburcu], liburcu, [ - liburcu_PKGCONFIG="liburcu >= 0.4.0" - AC_SUBST([liburcu_PKGCONFIG]) - with_urcu=yes - ],[ - for try_urcu in "$with_urcu" "" "/usr/local"; do - save_LIBS="$LIBS" - save_CPPFLAGS="$CPPFLAGS" - - AS_IF([test -d "$try_urcu"], [ - liburcu_CFLAGS="-I$try_urcu/include" - liburcu_LIBS="-L$try_urcu/lib" - ],[ - liburcu_CFLAGS="" - liburcu_LIBS="" - ]) - - CPPFLAGS="$CPPFLAGS $liburcu_CFLAGS" - LIBS="$LIBS $liburcu_LIBS" - - AC_SEARCH_LIBS([rcu_set_pointer_sym], [urcu], [ - with_urcu=yes - liburcu_LIBS="$liburcu_LIBS -lurcu" - AC_SUBST([liburcu_CFLAGS]) - AC_SUBST([liburcu_LIBS]) - break - ],[ - CPPFLAGS="$save_CPPFLAGS" - LIBS="$save_LIBS" - with_urcu=no - # do not cache result of AC_SEARCH_LIBS test - unset ac_cv_search_rcu_set_pointer_sym - ]) - done - CPPFLAGS="$save_CPPFLAGS" - LIBS="$save_LIBS" - - AS_IF([test "$with_urcu" = "no"],[ - AC_MSG_ERROR([liburcu is required]) - ]) - ]) +PKG_CHECK_MODULES([liburcu], [liburcu], [], [ + AC_MSG_ERROR([liburcu not found]) ]) ]) @@ -604,9 +563,9 @@ AS_IF([test "$enable_quic" != "no"], [ # Dependencies needed for Knot DNS utilities ############################################ -dnl Check for libidn. +dnl Check for libidn2. AC_ARG_WITH(libidn, - AS_HELP_STRING([--with-libidn=[DIR]], [Support IDN (needs GNU libidn2 or libidn)]), + AS_HELP_STRING([--with-libidn=[DIR]], [Support IDN (needs GNU libidn2)]), with_libidn=$withval, with_libidn=yes ) @@ -623,16 +582,9 @@ AS_IF([test "$enable_utilities" = "yes"], [ PKG_CHECK_MODULES([libidn2], [libidn2 >= 2.0.0], [ with_libidn=libidn2 AC_DEFINE([LIBIDN], [1], [Define to 1 to enable IDN support]) - AC_DEFINE([LIBIDN_HEADER], [], [Define to proper libidn header]) ], [ - PKG_CHECK_MODULES([libidn], [libidn >= 0.0.0], [ - with_libidn=libidn - AC_DEFINE([LIBIDN], [1], [Define to 1 to enable IDN support]) - AC_DEFINE([LIBIDN_HEADER], [], [Define to proper libidn header]) - ], [ - with_libidn=no - AC_MSG_WARN([libidn2 or libidn not found]) - ]) + with_libidn=no + AC_MSG_WARN([libidn2 not found]) ]) ]) @@ -721,7 +673,7 @@ LIBS="$save_LIBS" # Checks for header files. AC_HEADER_RESOLV -AC_CHECK_HEADERS_ONCE([pthread_np.h stdatomic.h sys/uio.h bsd/string.h]) +AC_CHECK_HEADERS_ONCE([pthread_np.h sys/uio.h bsd/string.h]) # Checks for optional library functions. AC_CHECK_FUNCS([accept4 fgetln getline initgroups malloc_trim \ @@ -736,7 +688,7 @@ AC_CHECK_FUNC([explicit_memset], [ AC_DEFINE([HAVE_EXPLICIT_MEMSET], [1], [explicit_memset available]) explicit_memset=yes], [explicit_memset=no] ) -AM_CONDITIONAL([USE_GNUTLS_MEMSET], [test "$explicit_bzero" = "no" -a "$explicit_memset" = "no" -a "$gnutls_memset" = "yes"]) +AM_CONDITIONAL([USE_GNUTLS_MEMSET], [test "$explicit_bzero" = "no" -a "$explicit_memset" = "no"]) # Check for mandatory library functions. AC_CHECK_FUNC([vasprintf], [], [ @@ -750,18 +702,23 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[cpuset_t set; CPU AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[cpuset_t* set = cpuset_create(); cpuset_destroy(set);]])], [AC_DEFINE(HAVE_CPUSET_NETBSD, 1, [Define if cpuset_t and cpuset(3) exists.])]) -# Check for '__atomic' compiler builtin atomic functions. -AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[#include ]], - [[uint64_t val = 0; __atomic_add_fetch(&val, 1, __ATOMIC_RELAXED);]])], - [AC_DEFINE(HAVE_ATOMIC, 1, [Define to 1 if you have '__atomic' functions.])] -) - -# Check for '__sync' compiler builtin atomic functions. +# Check for a C11 or GCC-style '__atomic' compiler builtin atomic functions. +atomic_type="none" AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[#include ]], - [[int val = 0; __sync_add_and_fetch(&val, 1);]])], - [AC_DEFINE(HAVE_SYNC_ATOMIC, 1, [Define to 1 if you have '__sync' functions.])] + [AC_LANG_PROGRAM([[#if (__STDC_VERSION__ < 201112L) || defined(__STDC_NO_ATOMICS__) + #error "No C11 atomics" + #endif + #include ]], + [[atomic_uint_fast64_t val = 0;]] + [[atomic_fetch_add_explicit(&val, 1, memory_order_relaxed);]])], + [AC_DEFINE(HAVE_C11_ATOMIC, 1, [Define to 1 if you have C11 'atomic' functions.]) + atomic_type="C11"], + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[uint64_t val = 0; __atomic_add_fetch(&val, 1, __ATOMIC_RELAXED);]])], + [AC_DEFINE(HAVE_GCC_ATOMIC, 1, [Define to 1 if you have GCC-style '__atomic' functions.]) + atomic_type="__atomic"] + ) ) # Prepare CFLAG_VISIBILITY to be used where needed @@ -775,29 +732,15 @@ AS_IF([test -n "$sanitizer_CFLAGS"], [CFLAGS="$CFLAGS $sanitizer_CFLAGS"]) AM_CONDITIONAL([FUZZER], [test "$with_fuzzer" != "no"]) AM_CONDITIONAL([OSS_FUZZ], [test "$with_oss_fuzz" != "no"]) -AS_IF([test "$enable_documentation" = "yes"],[ - -AC_PATH_PROG([SPHINXBUILD], [sphinx-build], [false]) -AS_IF([test "$SPHINXBUILD" = "false"], - [AC_MSG_WARN([missing 'sphinx-build' executable for documentation generation])] -) -AC_PATH_PROG([PDFLATEX], [pdflatex], [false]) -AC_PATH_PROG([MAKEINFO], [makeinfo], [false]) - -]) - -AM_CONDITIONAL([HAVE_SPHINXBUILD], test "$SPHINXBUILD" != "false") -AM_CONDITIONAL([HAVE_PDFLATEX], test "$PDFLATEX" != "false") -AM_CONDITIONAL([HAVE_MAKEINFO], test "$MAKEINFO" != "false") - # Strip -fdebug-prefix-map= parameters from flags for better reproducibility of binaries. filtered_cflags=$(echo -n "$CFLAGS" | \ sed 's/[[^[:alnum:]]]-f[[^[:space:]]]*-prefix-map=[[^[:space:]]]*//g') filtered_cppflags=$(echo -n "$CPPFLAGS" | \ sed 's/[[^[:alnum:]]]-f[[^[:space:]]]*-prefix-map=[[^[:space:]]]*//g') +filtered_config_params=$(echo -n "$ac_configure_args" | \ + sed 's/[[^[:alnum:]]]-f[[^[:space:]]]*-prefix-map=[[^[:space:]]]*//g') -result_msg_base=" Knot DNS $VERSION - +result_msg_base=" Target: $host_os $host_cpu $endianity Compiler: ${CC} CFLAGS: ${filtered_cflags} ${filtered_cppflags} @@ -827,6 +770,7 @@ result_msg_base=" Knot DNS $VERSION XDP support: ${enable_xdp} DoQ support: ${enable_quic} Socket polling: ${socket_polling} + Atomic support: ${atomic_type} Memory allocator: ${with_memory_allocator} Fast zone parser: ${enable_fastparser} Utilities with IDN: ${with_libidn} @@ -834,17 +778,17 @@ result_msg_base=" Knot DNS $VERSION Utilities with Dnstap: ${enable_dnstap} MaxMind DB support: ${enable_maxminddb} Systemd integration: ${enable_systemd} + D-Bus support: ${enable_dbus} POSIX capabilities: ${enable_cap_ng} PKCS #11 support: ${enable_pkcs11} - Ed25519 support: ${enable_ed25519} Ed448 support: ${enable_ed448} - Reproducible signing: ${enable_repro_signing} + Code coverage: ${enable_code_coverage} Sanitizer: ${with_sanitizer} LibFuzzer: ${with_fuzzer} OSS-Fuzz: ${with_oss_fuzz}" -result_msg_esc=$(echo -n "$result_msg_base" | sed '$!s/$/\\n/' | tr -d '\n') +result_msg_esc=$(echo -n " Configure:$filtered_config_params\n$result_msg_base" | sed '$!s/$/\\n/' | tr -d '\n') AC_DEFINE_UNQUOTED([CONFIGURE_SUMMARY],["$result_msg_esc"],[Configure summary]) @@ -875,5 +819,6 @@ AC_CONFIG_FILES([doc/modules.rst], AC_OUTPUT AC_MSG_RESULT([ + Knot DNS $VERSION $result_msg_base ]) diff --git a/distro/Makefile.in b/distro/Makefile.in index c19943d..a492ba7 100644 --- a/distro/Makefile.in +++ b/distro/Makefile.in @@ -259,6 +259,8 @@ infodir = @infodir@ install_sh = @install_sh@ libbpf_CFLAGS = @libbpf_CFLAGS@ libbpf_LIBS = @libbpf_LIBS@ +libdbus_CFLAGS = @libdbus_CFLAGS@ +libdbus_LIBS = @libdbus_LIBS@ libdir = @libdir@ libdnssec_SONAME = @libdnssec_SONAME@ libdnssec_SOVERSION = @libdnssec_SOVERSION@ @@ -270,8 +272,6 @@ libfstrm_CFLAGS = @libfstrm_CFLAGS@ libfstrm_LIBS = @libfstrm_LIBS@ libidn2_CFLAGS = @libidn2_CFLAGS@ libidn2_LIBS = @libidn2_LIBS@ -libidn_CFLAGS = @libidn_CFLAGS@ -libidn_LIBS = @libidn_LIBS@ libknot_SONAME = @libknot_SONAME@ libknot_SOVERSION = @libknot_SOVERSION@ libknot_VERSION_INFO = @libknot_VERSION_INFO@ @@ -289,7 +289,6 @@ libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@ libprotobuf_c_LIBS = @libprotobuf_c_LIBS@ liburcu_CFLAGS = @liburcu_CFLAGS@ liburcu_LIBS = @liburcu_LIBS@ -liburcu_PKGCONFIG = @liburcu_PKGCONFIG@ libxdp_CFLAGS = @libxdp_CFLAGS@ libxdp_LIBS = @libxdp_LIBS@ libzscanner_SONAME = @libzscanner_SONAME@ diff --git a/distro/config/apkg.toml b/distro/config/apkg.toml index 0b9f0eb..3483ac2 100644 --- a/distro/config/apkg.toml +++ b/distro/config/apkg.toml @@ -11,14 +11,6 @@ signature_url = "https://secure.nic.cz/files/knot-dns/knot-{{ version }}.tar.xz. [apkg] compat = 3 -[[distro.aliases]] -name = "el-7" -distro = ["centos == 7", "rhel == 7"] - [[distro.aliases]] name = "deb-nolibxdp" distro = ["debian == 11", "ubuntu == 20.04", "ubuntu == 22.04"] - -[[distro.aliases]] -name = "deb-noxdp" -distro = ["debian == 10", "ubuntu == 18.04"] diff --git a/distro/pkg/deb-nolibxdp/control b/distro/pkg/deb-nolibxdp/control index ac5211b..30dc1fd 100644 --- a/distro/pkg/deb-nolibxdp/control +++ b/distro/pkg/deb-nolibxdp/control @@ -43,7 +43,7 @@ Architecture: any Depends: adduser, libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), libzscanner4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}, @@ -59,7 +59,7 @@ Description: Authoritative domain name server registry and hence is well suited to run anything from the root zone, the top-level domain, to many smaller standard domain names. -Package: libknot14 +Package: libknot15 Architecture: any Depends: ${misc:Depends}, @@ -115,10 +115,9 @@ Architecture: any Depends: libdnssec9 (= ${binary:Version}), libgnutls28-dev, - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), libzscanner4 (= ${binary:Version}), ${misc:Depends}, - ${shlibs:Depends}, Section: libdevel Description: Knot DNS shared library development files Knot DNS is a fast, authoritative only, high performance, feature @@ -134,7 +133,7 @@ Package: knot-dnsutils Architecture: any Depends: libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), libzscanner4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}, @@ -161,7 +160,7 @@ Package: knot-dnssecutils Architecture: any Depends: libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), libzscanner4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}, @@ -183,7 +182,7 @@ Package: knot-host Architecture: any Depends: libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), libzscanner4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}, @@ -269,7 +268,7 @@ Description: Prometheus exporter for Knot DNS Package: python3-libknot Architecture: all Depends: - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), ${misc:Depends}, ${python3:Depends}, Section: python diff --git a/distro/pkg/deb-nolibxdp/knot.install b/distro/pkg/deb-nolibxdp/knot.install index 5c716fc..a31224f 100644 --- a/distro/pkg/deb-nolibxdp/knot.install +++ b/distro/pkg/deb-nolibxdp/knot.install @@ -1,5 +1,4 @@ debian/cz.nic.knotd.conf usr/share/dbus-1/system.d/ -debian/ufw/knot etc/ufw/applications.d/ etc/knot/knot.conf usr/sbin/kcatalogprint usr/sbin/keymgr diff --git a/distro/pkg/deb-nolibxdp/libknot14.install b/distro/pkg/deb-nolibxdp/libknot14.install deleted file mode 100644 index f9b9f93..0000000 --- a/distro/pkg/deb-nolibxdp/libknot14.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/*/libknot.so.* diff --git a/distro/pkg/deb-nolibxdp/libknot14.symbols b/distro/pkg/deb-nolibxdp/libknot14.symbols deleted file mode 100644 index 174d517..0000000 --- a/distro/pkg/deb-nolibxdp/libknot14.symbols +++ /dev/null @@ -1,277 +0,0 @@ -libknot.so.14 libknot14 #MINVER# -* Build-Depends-Package: libknot-dev - KNOT_DB_LMDB_DUPSORT@Base 3.3.0 - KNOT_DB_LMDB_INTEGERKEY@Base 3.3.0 - KNOT_DB_LMDB_MAPASYNC@Base 3.3.0 - KNOT_DB_LMDB_NOSYNC@Base 3.3.0 - KNOT_DB_LMDB_NOTLS@Base 3.3.0 - KNOT_DB_LMDB_RDONLY@Base 3.3.0 - KNOT_DB_LMDB_WRITEMAP@Base 3.3.0 - KNOT_DUMP_STYLE_DEFAULT@Base 3.3.0 - knot_ctl_accept@Base 3.3.0 - knot_ctl_alloc@Base 3.3.0 - knot_ctl_bind@Base 3.3.0 - knot_ctl_bind2@Base 3.3.6 - knot_ctl_close@Base 3.3.0 - knot_ctl_connect@Base 3.3.0 - knot_ctl_free@Base 3.3.0 - knot_ctl_receive@Base 3.3.0 - knot_ctl_send@Base 3.3.0 - knot_ctl_set_timeout@Base 3.3.0 - knot_ctl_unbind@Base 3.3.0 - knot_db_lmdb_api@Base 3.3.0 - knot_db_lmdb_del_exact@Base 3.3.0 - knot_db_lmdb_get_mapsize@Base 3.3.0 - knot_db_lmdb_get_path@Base 3.3.0 - knot_db_lmdb_get_usage@Base 3.3.0 - knot_db_lmdb_iter_del@Base 3.3.0 - knot_db_lmdb_txn_begin@Base 3.3.0 - knot_db_trie_api@Base 3.3.0 - knot_dname_cmp@Base 3.3.0 - knot_dname_copy@Base 3.3.0 - knot_dname_copy_lower@Base 3.3.0 - knot_dname_free@Base 3.3.0 - knot_dname_from_str@Base 3.3.0 - knot_dname_in_bailiwick@Base 3.3.0 - knot_dname_is_case_equal@Base 3.3.0 - knot_dname_is_equal@Base 3.3.0 - knot_dname_labels@Base 3.3.0 - knot_dname_lf@Base 3.3.0 - knot_dname_matched_labels@Base 3.3.0 - knot_dname_prefixlen@Base 3.3.0 - knot_dname_realsize@Base 3.3.0 - knot_dname_replace_suffix@Base 3.3.0 - knot_dname_size@Base 3.3.0 - knot_dname_store@Base 3.3.0 - knot_dname_to_lower@Base 3.3.0 - knot_dname_to_str@Base 3.3.0 - knot_dname_to_wire@Base 3.3.0 - knot_dname_unpack@Base 3.3.0 - knot_dname_wire_check@Base 3.3.0 - knot_dnssec_alg_names@Base 3.3.0 - knot_edns_add_option@Base 3.3.0 - knot_edns_alignment_size@Base 3.3.0 - knot_edns_chain_parse@Base 3.3.0 - knot_edns_chain_size@Base 3.3.0 - knot_edns_chain_write@Base 3.3.0 - knot_edns_client_subnet_get_addr@Base 3.3.0 - knot_edns_client_subnet_parse@Base 3.3.0 - knot_edns_client_subnet_set_addr@Base 3.3.0 - knot_edns_client_subnet_size@Base 3.3.0 - knot_edns_client_subnet_write@Base 3.3.0 - knot_edns_cookie_client_check@Base 3.3.0 - knot_edns_cookie_client_generate@Base 3.3.0 - knot_edns_cookie_parse@Base 3.3.0 - knot_edns_cookie_server_check@Base 3.3.0 - knot_edns_cookie_server_generate@Base 3.3.0 - knot_edns_cookie_size@Base 3.3.0 - knot_edns_cookie_write@Base 3.3.0 - knot_edns_ede_names@Base 3.3.0 - knot_edns_get_ext_rcode@Base 3.3.0 - knot_edns_get_option@Base 3.3.0 - knot_edns_get_options@Base 3.3.0 - knot_edns_get_version@Base 3.3.0 - knot_edns_init@Base 3.3.0 - knot_edns_keepalive_parse@Base 3.3.0 - knot_edns_keepalive_size@Base 3.3.0 - knot_edns_keepalive_write@Base 3.3.0 - knot_edns_opt_names@Base 3.3.0 - knot_edns_reserve_option@Base 3.3.0 - knot_edns_set_ext_rcode@Base 3.3.0 - knot_edns_set_version@Base 3.3.0 - knot_error_from_libdnssec@Base 3.3.0 - knot_eth_mtu@Base 3.3.0 - knot_eth_name_from_addr@Base 3.3.0 - knot_eth_queues@Base 3.3.0 - knot_eth_rss@Base 3.3.0 - knot_eth_vlans@Base 3.3.0 - knot_eth_xdp_mode@Base 3.3.0 - knot_get_obsolete_rdata_descriptor@Base 3.3.0 - knot_get_rdata_descriptor@Base 3.3.0 - knot_naptr_header_size@Base 3.3.0 - knot_opcode_names@Base 3.3.0 - knot_opt_code_to_string@Base 3.3.0 - knot_pkt_begin@Base 3.3.0 - knot_pkt_clear@Base 3.3.0 - knot_pkt_copy@Base 3.3.0 - knot_pkt_ext_rcode@Base 3.3.0 - knot_pkt_ext_rcode_name@Base 3.3.0 - knot_pkt_free@Base 3.3.0 - knot_pkt_init_response@Base 3.3.0 - knot_pkt_new@Base 3.3.0 - knot_pkt_parse@Base 3.3.0 - knot_pkt_parse_question@Base 3.3.0 - knot_pkt_put_question@Base 3.3.0 - knot_pkt_put_rotate@Base 3.3.0 - knot_pkt_reclaim@Base 3.3.0 - knot_pkt_reserve@Base 3.3.0 - knot_probe_alloc@Base 3.3.0 - knot_probe_consume@Base 3.3.0 - knot_probe_data_set@Base 3.3.0 - knot_probe_fd@Base 3.3.0 - knot_probe_free@Base 3.3.0 - knot_probe_produce@Base 3.3.0 - knot_probe_set_consumer@Base 3.3.0 - knot_probe_set_producer@Base 3.3.0 - knot_probe_tcp_rtt@Base 3.3.0 - knot_quic_cleanup@Base 3.3.0 - knot_quic_client@Base 3.3.0 - knot_quic_conn_get_stream@Base 3.3.0 - knot_quic_conn_local_port@Base 3.3.0 - knot_quic_conn_new_stream@Base 3.3.0 - knot_quic_conn_next_timeout@Base 3.3.3 - knot_quic_conn_pin@Base 3.3.0 - knot_quic_conn_rtt@Base 3.3.0 - knot_quic_conn_stream_free@Base 3.3.0 - knot_quic_creds_cert@Base 3.3.0 - knot_quic_free_creds@Base 3.3.0 - knot_quic_handle@Base 3.3.0 - knot_quic_hanle_expiry@Base 3.3.3 - knot_quic_init_creds@Base 3.3.0 - knot_quic_init_creds_peer@Base 3.3.0 - knot_quic_send@Base 3.3.0 - knot_quic_session_available@Base 3.3.0 - knot_quic_session_load@Base 3.3.0 - knot_quic_session_save@Base 3.3.0 - knot_quic_stream_add_data@Base 3.3.0 - knot_quic_stream_get_process@Base 3.3.0 - knot_quic_table_free@Base 3.3.0 - knot_quic_table_new@Base 3.3.0 - knot_quic_table_rem@Base 3.3.0 - knot_quic_table_sweep@Base 3.3.0 - knot_rcode_names@Base 3.3.0 - knot_rdataset_add@Base 3.3.0 - knot_rdataset_at@Base 3.3.0 - knot_rdataset_clear@Base 3.3.0 - knot_rdataset_copy@Base 3.3.0 - knot_rdataset_eq@Base 3.3.0 - knot_rdataset_intersect@Base 3.3.0 - knot_rdataset_intersect2@Base 3.3.0 - knot_rdataset_member@Base 3.3.0 - knot_rdataset_merge@Base 3.3.0 - knot_rdataset_subset@Base 3.3.0 - knot_rdataset_subtract@Base 3.3.0 - knot_rrclass_from_string@Base 3.3.0 - knot_rrclass_to_string@Base 3.3.0 - knot_rrset_add_rdata@Base 3.3.0 - knot_rrset_clear@Base 3.3.0 - knot_rrset_copy@Base 3.3.0 - knot_rrset_equal@Base 3.3.0 - knot_rrset_free@Base 3.3.0 - knot_rrset_is_nsec3rel@Base 3.3.0 - knot_rrset_new@Base 3.3.0 - knot_rrset_rr_from_wire@Base 3.3.0 - knot_rrset_rr_to_canonical@Base 3.3.0 - knot_rrset_size@Base 3.3.0 - knot_rrset_to_wire_extra@Base 3.3.0 - knot_rrset_txt_dump@Base 3.3.0 - knot_rrset_txt_dump_data@Base 3.3.0 - knot_rrset_txt_dump_edns@Base 3.3.0 - knot_rrset_txt_dump_header@Base 3.3.0 - knot_rrtype_additional_needed@Base 3.3.0 - knot_rrtype_from_string@Base 3.3.0 - knot_rrtype_is_dnssec@Base 3.3.0 - knot_rrtype_is_metatype@Base 3.3.0 - knot_rrtype_should_be_lowercased@Base 3.3.0 - knot_rrtype_to_string@Base 3.3.0 - knot_strerror@Base 3.3.0 - knot_svcb_param_names@Base 3.3.0 - knot_tcp_cleanup@Base 3.3.0 - knot_tcp_inbufs_upd@Base 3.3.0 - knot_tcp_outbufs_ack@Base 3.3.0 - knot_tcp_outbufs_add@Base 3.3.0 - knot_tcp_outbufs_can_send@Base 3.3.0 - knot_tcp_outbufs_usage@Base 3.3.0 - knot_tcp_recv@Base 3.3.0 - knot_tcp_reply_data@Base 3.3.0 - knot_tcp_send@Base 3.3.0 - knot_tcp_sweep@Base 3.3.0 - knot_tcp_table_free@Base 3.3.0 - knot_tcp_table_new@Base 3.3.0 - knot_tsig_add@Base 3.3.0 - knot_tsig_append@Base 3.3.0 - knot_tsig_client_check@Base 3.3.0 - knot_tsig_client_check_next@Base 3.3.0 - knot_tsig_create_rdata@Base 3.3.0 - knot_tsig_key_copy@Base 3.3.0 - knot_tsig_key_deinit@Base 3.3.0 - knot_tsig_key_init@Base 3.3.0 - knot_tsig_key_init_file@Base 3.3.0 - knot_tsig_key_init_str@Base 3.3.0 - knot_tsig_rcode_names@Base 3.3.0 - knot_tsig_rdata_alg@Base 3.3.0 - knot_tsig_rdata_alg_name@Base 3.3.0 - knot_tsig_rdata_error@Base 3.3.0 - knot_tsig_rdata_fudge@Base 3.3.0 - knot_tsig_rdata_is_ok@Base 3.3.0 - knot_tsig_rdata_mac@Base 3.3.0 - knot_tsig_rdata_mac_length@Base 3.3.0 - knot_tsig_rdata_orig_id@Base 3.3.0 - knot_tsig_rdata_other_data@Base 3.3.0 - knot_tsig_rdata_other_data_length@Base 3.3.0 - knot_tsig_rdata_set_fudge@Base 3.3.0 - knot_tsig_rdata_set_mac@Base 3.3.0 - knot_tsig_rdata_set_orig_id@Base 3.3.0 - knot_tsig_rdata_set_other_data@Base 3.3.0 - knot_tsig_rdata_set_time_signed@Base 3.3.0 - knot_tsig_rdata_time_signed@Base 3.3.0 - knot_tsig_rdata_tsig_timers_length@Base 3.3.0 - knot_tsig_rdata_tsig_variables_length@Base 3.3.0 - knot_tsig_server_check@Base 3.3.0 - knot_tsig_sign@Base 3.3.0 - knot_tsig_sign_next@Base 3.3.0 - knot_tsig_wire_maxsize@Base 3.3.0 - knot_tsig_wire_size@Base 3.3.0 - knot_xdp_deinit@Base 3.3.0 - knot_xdp_init@Base 3.3.0 - knot_xdp_recv@Base 3.3.0 - knot_xdp_recv_finish@Base 3.3.0 - knot_xdp_reply_alloc@Base 3.3.0 - knot_xdp_send@Base 3.3.0 - knot_xdp_send_alloc@Base 3.3.0 - knot_xdp_send_finish@Base 3.3.0 - knot_xdp_send_free@Base 3.3.0 - knot_xdp_send_prepare@Base 3.3.0 - knot_xdp_socket_info@Base 3.3.0 - knot_xdp_socket_fd@Base 3.3.0 - yp_addr@Base 3.3.0 - yp_addr_noport@Base 3.3.0 - yp_addr_noport_to_bin@Base 3.3.0 - yp_addr_noport_to_txt@Base 3.3.0 - yp_addr_range_to_bin@Base 3.3.0 - yp_addr_range_to_txt@Base 3.3.0 - yp_addr_to_bin@Base 3.3.0 - yp_addr_to_txt@Base 3.3.0 - yp_base64_to_bin@Base 3.3.0 - yp_base64_to_txt@Base 3.3.0 - yp_bool_to_bin@Base 3.3.0 - yp_bool_to_txt@Base 3.3.0 - yp_deinit@Base 3.3.0 - yp_dname_to_bin@Base 3.3.0 - yp_dname_to_txt@Base 3.3.0 - yp_format_id@Base 3.3.0 - yp_format_key0@Base 3.3.0 - yp_format_key1@Base 3.3.0 - yp_hex_to_bin@Base 3.3.0 - yp_hex_to_txt@Base 3.3.0 - yp_init@Base 3.3.0 - yp_int_to_bin@Base 3.3.0 - yp_int_to_txt@Base 3.3.0 - yp_item_to_bin@Base 3.3.0 - yp_item_to_txt@Base 3.3.0 - yp_option_to_bin@Base 3.3.0 - yp_option_to_txt@Base 3.3.0 - yp_parse@Base 3.3.0 - yp_schema_check_deinit@Base 3.3.0 - yp_schema_check_init@Base 3.3.0 - yp_schema_check_parser@Base 3.3.0 - yp_schema_check_str@Base 3.3.0 - yp_schema_copy@Base 3.3.0 - yp_schema_find@Base 3.3.0 - yp_schema_free@Base 3.3.0 - yp_schema_merge@Base 3.3.0 - yp_schema_purge_dynamic@Base 3.3.0 - yp_set_input_file@Base 3.3.0 - yp_set_input_string@Base 3.3.0 - yp_str_to_bin@Base 3.3.0 - yp_str_to_txt@Base 3.3.0 diff --git a/distro/pkg/deb-nolibxdp/libknot15.install b/distro/pkg/deb-nolibxdp/libknot15.install new file mode 100644 index 0000000..f9b9f93 --- /dev/null +++ b/distro/pkg/deb-nolibxdp/libknot15.install @@ -0,0 +1 @@ +usr/lib/*/libknot.so.* diff --git a/distro/pkg/deb-nolibxdp/libknot15.symbols b/distro/pkg/deb-nolibxdp/libknot15.symbols new file mode 100644 index 0000000..77dd5b0 --- /dev/null +++ b/distro/pkg/deb-nolibxdp/libknot15.symbols @@ -0,0 +1,290 @@ +libknot.so.15 libknot15 #MINVER# +* Build-Depends-Package: libknot-dev + KNOT_DB_LMDB_DUPSORT@Base 3.4.0 + KNOT_DB_LMDB_INTEGERKEY@Base 3.4.0 + KNOT_DB_LMDB_MAPASYNC@Base 3.4.0 + KNOT_DB_LMDB_NOSYNC@Base 3.4.0 + KNOT_DB_LMDB_NOTLS@Base 3.4.0 + KNOT_DB_LMDB_RDONLY@Base 3.4.0 + KNOT_DB_LMDB_WRITEMAP@Base 3.4.0 + KNOT_DUMP_STYLE_DEFAULT@Base 3.4.0 + knot_creds_cert@Base 3.4.0 + knot_creds_free@Base 3.4.0 + knot_creds_init@Base 3.4.0 + knot_creds_init_peer@Base 3.4.0 + knot_creds_update@Base 3.4.0 + knot_ctl_accept@Base 3.4.0 + knot_ctl_alloc@Base 3.4.0 + knot_ctl_bind@Base 3.4.0 + knot_ctl_clone@Base 3.4.0 + knot_ctl_close@Base 3.4.0 + knot_ctl_connect@Base 3.4.0 + knot_ctl_free@Base 3.4.0 + knot_ctl_receive@Base 3.4.0 + knot_ctl_send@Base 3.4.0 + knot_ctl_set_timeout@Base 3.4.0 + knot_ctl_unbind@Base 3.4.0 + knot_db_lmdb_api@Base 3.4.0 + knot_db_lmdb_del_exact@Base 3.4.0 + knot_db_lmdb_get_mapsize@Base 3.4.0 + knot_db_lmdb_get_path@Base 3.4.0 + knot_db_lmdb_get_usage@Base 3.4.0 + knot_db_lmdb_iter_del@Base 3.4.0 + knot_db_lmdb_txn_begin@Base 3.4.0 + knot_db_trie_api@Base 3.4.0 + knot_dname_cmp@Base 3.4.0 + knot_dname_copy@Base 3.4.0 + knot_dname_copy_lower@Base 3.4.0 + knot_dname_free@Base 3.4.0 + knot_dname_from_str@Base 3.4.0 + knot_dname_in_bailiwick@Base 3.4.0 + knot_dname_is_case_equal@Base 3.4.0 + knot_dname_is_equal@Base 3.4.0 + knot_dname_labels@Base 3.4.0 + knot_dname_lf@Base 3.4.0 + knot_dname_matched_labels@Base 3.4.0 + knot_dname_prefixlen@Base 3.4.0 + knot_dname_realsize@Base 3.4.0 + knot_dname_replace_suffix@Base 3.4.0 + knot_dname_size@Base 3.4.0 + knot_dname_store@Base 3.4.0 + knot_dname_to_lower@Base 3.4.0 + knot_dname_to_str@Base 3.4.0 + knot_dname_to_wire@Base 3.4.0 + knot_dname_unpack@Base 3.4.0 + knot_dname_wire_check@Base 3.4.0 + knot_dnssec_alg_names@Base 3.4.0 + knot_edns_add_option@Base 3.4.0 + knot_edns_alignment_size@Base 3.4.0 + knot_edns_chain_parse@Base 3.4.0 + knot_edns_chain_size@Base 3.4.0 + knot_edns_chain_write@Base 3.4.0 + knot_edns_client_subnet_get_addr@Base 3.4.0 + knot_edns_client_subnet_parse@Base 3.4.0 + knot_edns_client_subnet_set_addr@Base 3.4.0 + knot_edns_client_subnet_size@Base 3.4.0 + knot_edns_client_subnet_write@Base 3.4.0 + knot_edns_cookie_client_check@Base 3.4.0 + knot_edns_cookie_client_generate@Base 3.4.0 + knot_edns_cookie_parse@Base 3.4.0 + knot_edns_cookie_server_check@Base 3.4.0 + knot_edns_cookie_server_generate@Base 3.4.0 + knot_edns_cookie_size@Base 3.4.0 + knot_edns_cookie_write@Base 3.4.0 + knot_edns_ede_names@Base 3.4.0 + knot_edns_get_ext_rcode@Base 3.4.0 + knot_edns_get_option@Base 3.4.0 + knot_edns_get_options@Base 3.4.0 + knot_edns_get_version@Base 3.4.0 + knot_edns_init@Base 3.4.0 + knot_edns_keepalive_parse@Base 3.4.0 + knot_edns_keepalive_size@Base 3.4.0 + knot_edns_keepalive_write@Base 3.4.0 + knot_edns_opt_names@Base 3.4.0 + knot_edns_reserve_option@Base 3.4.0 + knot_edns_set_ext_rcode@Base 3.4.0 + knot_edns_set_version@Base 3.4.0 + knot_error_from_libdnssec@Base 3.4.0 + knot_eth_mtu@Base 3.4.0 + knot_eth_name_from_addr@Base 3.4.0 + knot_eth_queues@Base 3.4.0 + knot_eth_rss@Base 3.4.0 + knot_eth_vlans@Base 3.4.0 + knot_eth_xdp_mode@Base 3.4.0 + knot_get_obsolete_rdata_descriptor@Base 3.4.0 + knot_get_rdata_descriptor@Base 3.4.0 + knot_naptr_header_size@Base 3.4.0 + knot_opcode_names@Base 3.4.0 + knot_opt_code_to_string@Base 3.4.0 + knot_pkt_begin@Base 3.4.0 + knot_pkt_clear@Base 3.4.0 + knot_pkt_copy@Base 3.4.0 + knot_pkt_ext_rcode@Base 3.4.0 + knot_pkt_ext_rcode_name@Base 3.4.0 + knot_pkt_free@Base 3.4.0 + knot_pkt_init_response@Base 3.4.0 + knot_pkt_new@Base 3.4.0 + knot_pkt_parse@Base 3.4.0 + knot_pkt_parse_question@Base 3.4.0 + knot_pkt_put_question@Base 3.4.0 + knot_pkt_put_rotate@Base 3.4.0 + knot_pkt_reclaim@Base 3.4.0 + knot_pkt_reserve@Base 3.4.0 + knot_probe_alloc@Base 3.4.0 + knot_probe_consume@Base 3.4.0 + knot_probe_data_set@Base 3.4.0 + knot_probe_fd@Base 3.4.0 + knot_probe_free@Base 3.4.0 + knot_probe_produce@Base 3.4.0 + knot_probe_set_consumer@Base 3.4.0 + knot_probe_set_producer@Base 3.4.0 + knot_probe_tcp_rtt@Base 3.4.0 + knot_quic_cleanup@Base 3.4.0 + knot_quic_client@Base 3.4.0 + knot_quic_conn_block@Base 3.4.0 + knot_quic_conn_get_stream@Base 3.4.0 + knot_quic_conn_local_port@Base 3.4.0 + knot_quic_conn_new_stream@Base 3.4.0 + knot_quic_conn_next_timeout@Base 3.4.0 + knot_quic_conn_rtt@Base 3.4.0 + knot_quic_conn_stream_free@Base 3.4.0 + knot_quic_handle@Base 3.4.0 + knot_quic_hanle_expiry@Base 3.4.0 + knot_quic_send@Base 3.4.0 + knot_quic_session_available@Base 3.4.0 + knot_quic_session_load@Base 3.4.0 + knot_quic_session_save@Base 3.4.0 + knot_quic_stream_add_data@Base 3.4.0 + knot_quic_stream_get_process@Base 3.4.0 + knot_quic_table_free@Base 3.4.0 + knot_quic_table_new@Base 3.4.0 + knot_quic_table_rem@Base 3.4.0 + knot_quic_table_sweep@Base 3.4.0 + knot_rcode_names@Base 3.4.0 + knot_rdataset_add@Base 3.4.0 + knot_rdataset_at@Base 3.4.0 + knot_rdataset_clear@Base 3.4.0 + knot_rdataset_copy@Base 3.4.0 + knot_rdataset_eq@Base 3.4.0 + knot_rdataset_intersect@Base 3.4.0 + knot_rdataset_intersect2@Base 3.4.0 + knot_rdataset_member@Base 3.4.0 + knot_rdataset_merge@Base 3.4.0 + knot_rdataset_subset@Base 3.4.0 + knot_rdataset_subtract@Base 3.4.0 + knot_rrclass_from_string@Base 3.4.0 + knot_rrclass_to_string@Base 3.4.0 + knot_rrset_add_rdata@Base 3.4.0 + knot_rrset_clear@Base 3.4.0 + knot_rrset_copy@Base 3.4.0 + knot_rrset_equal@Base 3.4.0 + knot_rrset_free@Base 3.4.0 + knot_rrset_is_nsec3rel@Base 3.4.0 + knot_rrset_new@Base 3.4.0 + knot_rrset_rr_from_wire@Base 3.4.0 + knot_rrset_rr_to_canonical@Base 3.4.0 + knot_rrset_size@Base 3.4.0 + knot_rrset_to_wire_extra@Base 3.4.0 + knot_rrset_txt_dump@Base 3.4.0 + knot_rrset_txt_dump_data@Base 3.4.0 + knot_rrset_txt_dump_edns@Base 3.4.0 + knot_rrset_txt_dump_header@Base 3.4.0 + knot_rrtype_additional_needed@Base 3.4.0 + knot_rrtype_from_string@Base 3.4.0 + knot_rrtype_is_dnssec@Base 3.4.0 + knot_rrtype_is_metatype@Base 3.4.0 + knot_rrtype_should_be_lowercased@Base 3.4.0 + knot_rrtype_to_string@Base 3.4.0 + knot_strerror@Base 3.4.0 + knot_svcb_param_names@Base 3.4.0 + knot_tcp_cleanup@Base 3.4.0 + knot_tcp_inbufs_upd@Base 3.4.0 + knot_tcp_outbufs_ack@Base 3.4.0 + knot_tcp_outbufs_add@Base 3.4.0 + knot_tcp_outbufs_can_send@Base 3.4.0 + knot_tcp_outbufs_usage@Base 3.4.0 + knot_tcp_recv@Base 3.4.0 + knot_tcp_reply_data@Base 3.4.0 + knot_tcp_send@Base 3.4.0 + knot_tcp_sweep@Base 3.4.0 + knot_tcp_table_free@Base 3.4.0 + knot_tcp_table_new@Base 3.4.0 + knot_tls_conn_block@Base 3.4.0 + knot_tls_conn_del@Base 3.4.0 + knot_tls_conn_new@Base 3.4.0 + knot_tls_ctx_free@Base 3.4.0 + knot_tls_ctx_new@Base 3.4.0 + knot_tls_handshake@Base 3.4.0 + knot_tls_pin@Base 3.4.0 + knot_tls_pin_check@Base 3.4.0 + knot_tls_recv_dns@Base 3.4.0 + knot_tls_send_dns@Base 3.4.0 + knot_tls_session@Base 3.4.0 + knot_tsig_add@Base 3.4.0 + knot_tsig_append@Base 3.4.0 + knot_tsig_client_check@Base 3.4.0 + knot_tsig_client_check_next@Base 3.4.0 + knot_tsig_create_rdata@Base 3.4.0 + knot_tsig_key_copy@Base 3.4.0 + knot_tsig_key_deinit@Base 3.4.0 + knot_tsig_key_init@Base 3.4.0 + knot_tsig_key_init_file@Base 3.4.0 + knot_tsig_key_init_str@Base 3.4.0 + knot_tsig_rcode_names@Base 3.4.0 + knot_tsig_rdata_alg@Base 3.4.0 + knot_tsig_rdata_alg_name@Base 3.4.0 + knot_tsig_rdata_error@Base 3.4.0 + knot_tsig_rdata_fudge@Base 3.4.0 + knot_tsig_rdata_is_ok@Base 3.4.0 + knot_tsig_rdata_mac@Base 3.4.0 + knot_tsig_rdata_mac_length@Base 3.4.0 + knot_tsig_rdata_orig_id@Base 3.4.0 + knot_tsig_rdata_other_data@Base 3.4.0 + knot_tsig_rdata_other_data_length@Base 3.4.0 + knot_tsig_rdata_set_fudge@Base 3.4.0 + knot_tsig_rdata_set_mac@Base 3.4.0 + knot_tsig_rdata_set_orig_id@Base 3.4.0 + knot_tsig_rdata_set_other_data@Base 3.4.0 + knot_tsig_rdata_set_time_signed@Base 3.4.0 + knot_tsig_rdata_time_signed@Base 3.4.0 + knot_tsig_rdata_tsig_timers_length@Base 3.4.0 + knot_tsig_rdata_tsig_variables_length@Base 3.4.0 + knot_tsig_server_check@Base 3.4.0 + knot_tsig_sign@Base 3.4.0 + knot_tsig_sign_next@Base 3.4.0 + knot_tsig_wire_maxsize@Base 3.4.0 + knot_tsig_wire_size@Base 3.4.0 + knot_xdp_deinit@Base 3.4.0 + knot_xdp_init@Base 3.4.0 + knot_xdp_recv@Base 3.4.0 + knot_xdp_recv_finish@Base 3.4.0 + knot_xdp_reply_alloc@Base 3.4.0 + knot_xdp_send@Base 3.4.0 + knot_xdp_send_alloc@Base 3.4.0 + knot_xdp_send_finish@Base 3.4.0 + knot_xdp_send_free@Base 3.4.0 + knot_xdp_send_prepare@Base 3.4.0 + knot_xdp_socket_info@Base 3.4.0 + knot_xdp_socket_stats@Base 3.4.0 + knot_xdp_socket_fd@Base 3.4.0 + yp_addr@Base 3.4.0 + yp_addr_noport@Base 3.4.0 + yp_addr_noport_to_bin@Base 3.4.0 + yp_addr_noport_to_txt@Base 3.4.0 + yp_addr_range_to_bin@Base 3.4.0 + yp_addr_range_to_txt@Base 3.4.0 + yp_addr_to_bin@Base 3.4.0 + yp_addr_to_txt@Base 3.4.0 + yp_base64_to_bin@Base 3.4.0 + yp_base64_to_txt@Base 3.4.0 + yp_bool_to_bin@Base 3.4.0 + yp_bool_to_txt@Base 3.4.0 + yp_deinit@Base 3.4.0 + yp_dname_to_bin@Base 3.4.0 + yp_dname_to_txt@Base 3.4.0 + yp_format_id@Base 3.4.0 + yp_format_key0@Base 3.4.0 + yp_format_key1@Base 3.4.0 + yp_hex_to_bin@Base 3.4.0 + yp_hex_to_txt@Base 3.4.0 + yp_init@Base 3.4.0 + yp_int_to_bin@Base 3.4.0 + yp_int_to_txt@Base 3.4.0 + yp_item_to_bin@Base 3.4.0 + yp_item_to_txt@Base 3.4.0 + yp_option_to_bin@Base 3.4.0 + yp_option_to_txt@Base 3.4.0 + yp_parse@Base 3.4.0 + yp_schema_check_deinit@Base 3.4.0 + yp_schema_check_init@Base 3.4.0 + yp_schema_check_parser@Base 3.4.0 + yp_schema_check_str@Base 3.4.0 + yp_schema_copy@Base 3.4.0 + yp_schema_find@Base 3.4.0 + yp_schema_free@Base 3.4.0 + yp_schema_merge@Base 3.4.0 + yp_schema_purge_dynamic@Base 3.4.0 + yp_set_input_file@Base 3.4.0 + yp_set_input_string@Base 3.4.0 + yp_str_to_bin@Base 3.4.0 + yp_str_to_txt@Base 3.4.0 diff --git a/distro/pkg/deb-nolibxdp/rules b/distro/pkg/deb-nolibxdp/rules index 82cc34b..c5c81d0 100755 --- a/distro/pkg/deb-nolibxdp/rules +++ b/distro/pkg/deb-nolibxdp/rules @@ -36,11 +36,9 @@ BASE_VERSION := $(shell echo $(DEB_VERSION) | sed 's/^\([^.]\+\.[^.]\+\).*/\1/') # invocation due to bug in dh-python's plugin_pyproject.py wheel unpack export PYBUILD_SYSTEM = distutils - %: dh $@ \ - --exclude=.la --exclude=example.com.zone \ - --with python3 + --with python3 override_dh_auto_configure: dh_auto_configure -- \ @@ -95,7 +93,7 @@ ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) endif override_dh_missing: - dh_missing --fail-missing + dh_missing --exclude=.la --fail-missing override_dh_installchangelogs: dh_installchangelogs NEWS diff --git a/distro/pkg/deb-nolibxdp/ufw/knot b/distro/pkg/deb-nolibxdp/ufw/knot deleted file mode 100644 index ee36916..0000000 --- a/distro/pkg/deb-nolibxdp/ufw/knot +++ /dev/null @@ -1,4 +0,0 @@ -[Knot] -title=Internet Domain Name Server -description=The Knot DNS implements an Internet domain name server. -ports=53 diff --git a/distro/pkg/deb-noxdp/changelog b/distro/pkg/deb-noxdp/changelog deleted file mode 100644 index 123f92b..0000000 --- a/distro/pkg/deb-noxdp/changelog +++ /dev/null @@ -1,6 +0,0 @@ -knot ({{ version }}-cznic.{{ release }}) unstable; urgency=medium - - * upstream package - * see https://www.knot-dns.cz - - -- Knot DNS {{ now }} diff --git a/distro/pkg/deb-noxdp/clean b/distro/pkg/deb-noxdp/clean deleted file mode 100644 index b2a9f3f..0000000 --- a/distro/pkg/deb-noxdp/clean +++ /dev/null @@ -1,2 +0,0 @@ -doc/modules -.pybuild/ diff --git a/distro/pkg/deb-noxdp/compat b/distro/pkg/deb-noxdp/compat deleted file mode 100644 index b4de394..0000000 --- a/distro/pkg/deb-noxdp/compat +++ /dev/null @@ -1 +0,0 @@ -11 diff --git a/distro/pkg/deb-noxdp/control b/distro/pkg/deb-noxdp/control deleted file mode 100644 index be9dd3f..0000000 --- a/distro/pkg/deb-noxdp/control +++ /dev/null @@ -1,288 +0,0 @@ -Source: knot -Section: net -Priority: optional -Maintainer: Knot DNS -Uploaders: - Jakub Ružička , - Daniel Salzman , -Build-Depends-Indep: - python3-setuptools, - python3-sphinx, -Build-Depends: - autoconf, - automake, - debhelper (>= 11), - dh-python, - libcap-ng-dev, - libedit-dev, - libfstrm-dev, - libgnutls28-dev, - libidn2-dev, - liblmdb-dev, - libmaxminddb-dev, - libmnl-dev, - libnghttp2-dev, - libprotobuf-c-dev, - libsofthsm2 , - libsystemd-dev [linux-any] | libsystemd-daemon-dev [linux-any], - libsystemd-dev [linux-any] | libsystemd-journal-dev [linux-any], - libtool, - liburcu-dev, - pkg-config, - protobuf-c-compiler, - python3-all, -Standards-Version: 4.5.0 -Homepage: https://www.knot-dns.cz/ -Vcs-Browser: https://gitlab.nic.cz/knot/knot-dns -Vcs-Git: https://gitlab.nic.cz/knot/knot-dns.git -Rules-Requires-Root: no - -Package: knot -Architecture: any -Depends: - adduser, - libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), - libzscanner4 (= ${binary:Version}), - lsb-base (>= 3.0-6), - ${misc:Depends}, - ${shlibs:Depends}, -Pre-Depends: - ${misc:Pre-Depends}, -Suggests: - systemd, -Description: Authoritative domain name server - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - -Package: libknot14 -Architecture: any -Multi-Arch: same -Depends: - ${misc:Depends}, - ${shlibs:Depends}, -Section: libs -Description: DNS shared library from Knot DNS - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package provides a DNS shared library used by Knot DNS and - Knot Resolver. - -Package: libzscanner4 -Architecture: any -Multi-Arch: same -Depends: - ${misc:Depends}, - ${shlibs:Depends}, -Section: libs -Description: DNS zone-parsing shared library from Knot DNS - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package provides a fast zone parser shared library used by Knot - DNS and Knot Resolver. - -Package: libdnssec9 -Architecture: any -Multi-Arch: same -Depends: - ${misc:Depends}, - ${shlibs:Depends}, -Section: libs -Description: DNSSEC shared library from Knot DNS - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package provides common DNSSEC shared library used by Knot DNS - and Knot Resolver. - -Package: libknot-dev -Architecture: any -Depends: - libdnssec9 (= ${binary:Version}), - libgnutls28-dev, - libknot14 (= ${binary:Version}), - libzscanner4 (= ${binary:Version}), - ${misc:Depends}, - ${shlibs:Depends}, -Section: libdevel -Description: Knot DNS shared library development files - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package provides development files for shared libraries from Knot DNS. - -Package: knot-dnsutils -Architecture: any -Depends: - libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), - libzscanner4 (= ${binary:Version}), - ${misc:Depends}, - ${shlibs:Depends}, -Description: DNS clients provided with Knot DNS (kdig, knsupdate) - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package delivers various DNS client programs from Knot DNS. - . - - kdig - query a DNS server in various ways - - knsupdate - perform dynamic updates (See RFC2136) - . - Those clients were designed to be almost 1:1 compatible with BIND dnsutils, - but they provide some enhancements, which are documented. - . - WARNING: knslookup is not provided as it is considered obsolete. - -Package: knot-dnssecutils -Architecture: any -Depends: - libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), - libzscanner4 (= ${binary:Version}), - ${misc:Depends}, - ${shlibs:Depends}, -Description: DNSSEC tools provided with Knot DNS - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package delivers various DNSSEC tools from Knot DNS. - . - - kzonecheck - - kzonesign - - knsec3hash - -Package: knot-host -Architecture: any -Depends: - libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), - libzscanner4 (= ${binary:Version}), - ${misc:Depends}, - ${shlibs:Depends}, -Description: Version of 'host' bundled with Knot DNS - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package provides the 'host' program from Knot DNS. This program is - designed to be almost 1:1 compatible with BIND 9.x 'host' program. - -Package: knot-module-dnstap -Architecture: any -Multi-Arch: same -Depends: - knot (= ${binary:Version}), - ${misc:Depends}, - ${shlibs:Depends}, -Description: dnstap module for Knot DNS - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package contains dnstap module for logging DNS traffic. - -Package: knot-module-geoip -Architecture: any -Multi-Arch: same -Depends: - knot (= ${binary:Version}), - ${misc:Depends}, - ${shlibs:Depends}, -Description: geoip module for Knot DNS - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package contains geoip module for geography-based responses. - -Package: knot-doc -Architecture: all -Multi-Arch: foreign -Depends: - libjs-jquery, - libjs-sphinxdoc, - libjs-underscore, - ${misc:Depends}, -Section: doc -Description: Documentation for Knot DNS - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package provides various documents that are useful for - maintaining a working Knot DNS installation. - -Package: knot-exporter -Architecture: all -Depends: - ${misc:Depends}, - ${python3:Depends}, -Section: python -Description: Prometheus exporter for Knot DNS - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package provides Python Prometheus exporter for Knot DNS. - -Package: python3-libknot -Architecture: all -Depends: - libknot14 (= ${binary:Version}), - ${misc:Depends}, - ${python3:Depends}, -Section: python -Description: Python bindings for libknot - Knot DNS is a fast, authoritative only, high performance, feature - full and open source name server. - . - Knot DNS is developed by CZ.NIC Labs, the R&D department of .CZ - registry and hence is well suited to run anything from the root - zone, the top-level domain, to many smaller standard domain names. - . - This package provides Python bindings for the libknot shared library. diff --git a/distro/pkg/deb-noxdp/copyright b/distro/pkg/deb-noxdp/copyright deleted file mode 100644 index 20c8b97..0000000 --- a/distro/pkg/deb-noxdp/copyright +++ /dev/null @@ -1,179 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: Knot DNS -Upstream-Contact: knot-dns@labs.nic.cz -Source: https://secure.nic.cz/files/knot-dns/ - -Files: * -Copyright: 2011-2023 CZ.NIC, z.s.p.o. -License: GPL-3+ - -Files: m4/* -Copyright: 2011-2022 CZ.NIC, z.s.p.o. - 1996-2001, 2003-2015 Free Software Foundation, Inc. -License: GPL-3+ - -Files: install-sh -Copyright: 1994 X Consortium -License: MIT - -Files: debian/* distro/pkg/deb/* -Copyright: 2011-2023 CZ.NIC, z.s.p.o. - 2011 Ondřej Surý -License: GPL-3+ - -Files: tests/tap/* -Copyright: 2000-2001, 2004, 2006-2012 Russ Allbery - 2006, 2007, 2008, 2013 The Board of Trustees of the Leland Stanford Junior University -License: MIT - -Files: tests/tap/files.* -Copyright: 2011-2019 CZ.NIC, z.s.p.o. -License: GPL-3+ - -Files: src/contrib/dnstap/* -Copyright: 2014, Farsight Security, Inc. - 2011-2022 CZ.NIC, z.s.p.o. -License: GPL-3+ - -Files: src/contrib/libngtcp2/* -Copyright: 2016-2023 ngtcp2 contributors - 2012-2017 nghttp2 contributors -License: MIT - -Files: src/contrib/musl/* -Copyright: 2005-2020 Rich Felker, et al. -License: MIT - -Files: src/contrib/openbsd/siphash.* -Copyright: 2013 Andre Oppermann -License: BSD-3-Clause - -Files: src/contrib/openbsd/strl* -Copyright: 1998 Todd C. Miller -License: 0BSD - -Files: src/contrib/proxyv2/* -Copyright: 2022 CZ.NIC, z.s.p.o. - 2021 Fastly, Inc. -License: GPL-3+ - -Files: src/contrib/qp-trie/* -Copyright: 2011-2019 CZ.NIC, z.s.p.o. - 2018 Tony Finch -License: GPL-3+ - -Files: src/contrib/ucw/* -Copyright: 2011-2022 CZ.NIC, z.s.p.o. - 1997-2017 Martin Mares - 2007 Pavel Charvat - 2012 Ondrej Filip -License: LGPL-2.0 - -Files: src/contrib/ucw/heap.h -Copyright: 2011-2022 CZ.NIC, z.s.p.o. -License: GPL-3+ - -Files: src/contrib/url-parser/* -Copyright: 2020 Igor Sysoev - 2020 Nginx, Inc. - 2020 Joyent, Inc. -License: MIT - -Files: src/contrib/vpool/* -Copyright: 2006, 2008 Alexey Vatchenko -License: 0BSD - -Files: tests-fuzz/main.c -Copyright: 2011-2019 CZ.NIC, z.s.p.o. - 2017 Tim Ruehsen -License: MIT - -License: GPL-3+ - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public 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 . - . - On Debian systems, the full text of the GNU General Public License - version 3 can be found in the file `/usr/share/common-licenses/GPL-3'. - -License: LGPL-2.0 - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - . - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - . - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - -License: 0BSD - Permission to use, copy, modify, and distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - . - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -License: BSD-3-Clause - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - . - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - OF THE POSSIBILITY OF SUCH DAMAGE. - -License: MIT - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - . - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. diff --git a/distro/pkg/deb-noxdp/cz.nic.knotd.conf b/distro/pkg/deb-noxdp/cz.nic.knotd.conf deleted file mode 100644 index 50af87a..0000000 --- a/distro/pkg/deb-noxdp/cz.nic.knotd.conf +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/distro/pkg/deb-noxdp/docs b/distro/pkg/deb-noxdp/docs deleted file mode 100644 index b43bf86..0000000 --- a/distro/pkg/deb-noxdp/docs +++ /dev/null @@ -1 +0,0 @@ -README.md diff --git a/distro/pkg/deb-noxdp/knot-dnssecutils.install b/distro/pkg/deb-noxdp/knot-dnssecutils.install deleted file mode 100644 index 20009e8..0000000 --- a/distro/pkg/deb-noxdp/knot-dnssecutils.install +++ /dev/null @@ -1,3 +0,0 @@ -usr/bin/knsec3hash -usr/bin/kzonecheck -usr/bin/kzonesign diff --git a/distro/pkg/deb-noxdp/knot-dnssecutils.manpages b/distro/pkg/deb-noxdp/knot-dnssecutils.manpages deleted file mode 100644 index 913c4cb..0000000 --- a/distro/pkg/deb-noxdp/knot-dnssecutils.manpages +++ /dev/null @@ -1,3 +0,0 @@ -usr/share/man/man1/knsec3hash.1 -usr/share/man/man1/kzonecheck.1 -usr/share/man/man1/kzonesign.1 diff --git a/distro/pkg/deb-noxdp/knot-dnsutils.install b/distro/pkg/deb-noxdp/knot-dnsutils.install deleted file mode 100644 index 960fa92..0000000 --- a/distro/pkg/deb-noxdp/knot-dnsutils.install +++ /dev/null @@ -1,2 +0,0 @@ -usr/bin/kdig -usr/bin/knsupdate diff --git a/distro/pkg/deb-noxdp/knot-dnsutils.manpages b/distro/pkg/deb-noxdp/knot-dnsutils.manpages deleted file mode 100644 index 3cc29ec..0000000 --- a/distro/pkg/deb-noxdp/knot-dnsutils.manpages +++ /dev/null @@ -1,2 +0,0 @@ -usr/share/man/man1/kdig.1 -usr/share/man/man1/knsupdate.1 diff --git a/distro/pkg/deb-noxdp/knot-doc.install b/distro/pkg/deb-noxdp/knot-doc.install deleted file mode 100644 index c2a345d..0000000 --- a/distro/pkg/deb-noxdp/knot-doc.install +++ /dev/null @@ -1 +0,0 @@ -usr/share/doc/knot/* /usr/share/doc/knot-doc/ diff --git a/distro/pkg/deb-noxdp/knot-doc.links b/distro/pkg/deb-noxdp/knot-doc.links deleted file mode 100644 index 1376b3a..0000000 --- a/distro/pkg/deb-noxdp/knot-doc.links +++ /dev/null @@ -1,5 +0,0 @@ -usr/share/javascript/jquery/jquery.min.js usr/share/doc/knot-doc/_static/jquery.js -usr/share/javascript/sphinxdoc/1.0/doctools.js usr/share/doc/knot-doc/_static/doctools.js -usr/share/javascript/sphinxdoc/1.0/language_data.js usr/share/doc/knot-doc/_static/language_data.js -usr/share/javascript/sphinxdoc/1.0/searchtools.js usr/share/doc/knot-doc/_static/searchtools.js -usr/share/javascript/underscore/underscore.min.js usr/share/doc/knot-doc/_static/underscore.js diff --git a/distro/pkg/deb-noxdp/knot-exporter.install b/distro/pkg/deb-noxdp/knot-exporter.install deleted file mode 100644 index 4c2d5ed..0000000 --- a/distro/pkg/deb-noxdp/knot-exporter.install +++ /dev/null @@ -1,3 +0,0 @@ -usr/lib/python3*/dist-packages/knot_exporter-*.egg-info -usr/lib/python3*/dist-packages/knot_exporter/*.py -usr/bin/knot-exporter /usr/sbin/knot-exporter diff --git a/distro/pkg/deb-noxdp/knot-host.install b/distro/pkg/deb-noxdp/knot-host.install deleted file mode 100644 index 51bacf0..0000000 --- a/distro/pkg/deb-noxdp/knot-host.install +++ /dev/null @@ -1 +0,0 @@ -usr/bin/khost diff --git a/distro/pkg/deb-noxdp/knot-host.manpages b/distro/pkg/deb-noxdp/knot-host.manpages deleted file mode 100644 index 4891e2c..0000000 --- a/distro/pkg/deb-noxdp/knot-host.manpages +++ /dev/null @@ -1 +0,0 @@ -usr/share/man/man1/khost.1 diff --git a/distro/pkg/deb-noxdp/knot-module-dnstap.install b/distro/pkg/deb-noxdp/knot-module-dnstap.install deleted file mode 100644 index 983455e..0000000 --- a/distro/pkg/deb-noxdp/knot-module-dnstap.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/*/knot/modules-*/dnstap.so diff --git a/distro/pkg/deb-noxdp/knot-module-geoip.install b/distro/pkg/deb-noxdp/knot-module-geoip.install deleted file mode 100644 index 16d87c3..0000000 --- a/distro/pkg/deb-noxdp/knot-module-geoip.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/*/knot/modules-*/geoip.so diff --git a/distro/pkg/deb-noxdp/knot.dirs b/distro/pkg/deb-noxdp/knot.dirs deleted file mode 100644 index 6e937aa..0000000 --- a/distro/pkg/deb-noxdp/knot.dirs +++ /dev/null @@ -1 +0,0 @@ -var/lib/knot diff --git a/distro/pkg/deb-noxdp/knot.init b/distro/pkg/deb-noxdp/knot.init deleted file mode 100644 index 3f8fcae..0000000 --- a/distro/pkg/deb-noxdp/knot.init +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/sh -### BEGIN INIT INFO -# Provides: knot -# Required-Start: $network $local_fs $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: authoritative domain name server -# Description: Knot DNS is a authoritative-only domain name server -### END INIT INFO - -# Author: Ondřej Surý - -# PATH should only include /usr/* if it runs after the mountnfs.sh script -PATH=/sbin:/usr/sbin:/bin:/usr/bin -DESC="Knot DNS server" # Introduce a short description here -NAME=knotd # Introduce the short server's name here -DAEMON=/usr/sbin/$NAME # Introduce the server's location here -PIDFILE=/run/knot/knot.pid -SCRIPTNAME=/etc/init.d/knot -KNOTC=/usr/sbin/knotc -RUNDIR=/run/knot - -# Exit if the package is not installed -[ -x $DAEMON ] || exit 0 - -KNOTD_ARGS="" - -# Read configuration variable file if it is present -[ -r /etc/default/knot ] && . /etc/default/knot - -DAEMON_ARGS="-d $KNOTD_ARGS" - -# Define LSB log_* functions. -# Depend on sysvinit-utils (>= 2.96) to ensure that this file is present. -. /lib/lsb/init-functions - -# -# Function that starts the daemon/service -# -do_start() -{ - # Return - # 0 if daemon has been started - # 1 if daemon was already running - # 2 if daemon could not be started - - $KNOTC status >/dev/null 2>/dev/null \ - && return 1 - - start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ - || return 1 - start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ - $DAEMON_ARGS \ - || return 2 -} - -# -# Function that stops the daemon/service -# -do_stop() -{ - # Return - # 0 if daemon has been stopped - # 1 if daemon was already stopped - # 2 if daemon could not be stopped - # other if a failure occurred - - $KNOTC status >/dev/null 2>/dev/null \ - || return 1 - - $KNOTC stop >/dev/null - RETVAL="$?" - [ $? = 1 ] && return 2 - - # Many daemons don't delete their pidfiles when they exit. - rm -f $PIDFILE - return 0 -} - -do_reload() { - $KNOTC reload >/dev/null - return $? -} - -do_mkrundir() { - mkdir -p $RUNDIR - chmod 0755 $RUNDIR - chown knot:knot $RUNDIR -} - -case "$1" in - start) - do_mkrundir - log_daemon_msg "Starting $DESC " "$NAME" - do_start - case "$?" in - 0|1) log_end_msg 0 ;; - 2) log_end_msg 1 ;; - esac - ;; - stop) - log_daemon_msg "Stopping $DESC" "$NAME" - do_stop - case "$?" in - 0|1) log_end_msg 0 ;; - 2) log_end_msg 1 ;; - esac - ;; - status) - STATUS=$($KNOTC status 2>&1 >/dev/null) - RETVAL=$? - if [ $RETVAL = 0 ]; then - log_success_msg "$NAME is running" - else - log_failure_msg "$NAME is not running ($STATUS)" - fi - exit $RETVAL - ;; - reload|force-reload) - log_daemon_msg "Reloading $DESC" "$NAME" - do_reload - log_end_msg $? - ;; - restart) - log_daemon_msg "Restarting $DESC" "$NAME" - do_stop - case "$?" in - 0|1) - do_start - case "$?" in - 0) log_end_msg 0 ;; - 1) log_end_msg 1 ;; # Old process is still running - *) log_end_msg 1 ;; # Failed to start - esac - ;; - *) - # Failed to stop - log_end_msg 1 - ;; - esac - ;; - *) - echo "Usage: $SCRIPTNAME {start|stop|status|restart|reload|force-reload}" >&2 - exit 3 - ;; -esac - -: diff --git a/distro/pkg/deb-noxdp/knot.install b/distro/pkg/deb-noxdp/knot.install deleted file mode 100644 index 5c716fc..0000000 --- a/distro/pkg/deb-noxdp/knot.install +++ /dev/null @@ -1,8 +0,0 @@ -debian/cz.nic.knotd.conf usr/share/dbus-1/system.d/ -debian/ufw/knot etc/ufw/applications.d/ -etc/knot/knot.conf -usr/sbin/kcatalogprint -usr/sbin/keymgr -usr/sbin/kjournalprint -usr/sbin/knotc -usr/sbin/knotd diff --git a/distro/pkg/deb-noxdp/knot.manpages b/distro/pkg/deb-noxdp/knot.manpages deleted file mode 100644 index 5d23e9f..0000000 --- a/distro/pkg/deb-noxdp/knot.manpages +++ /dev/null @@ -1,6 +0,0 @@ -usr/share/man/man5/knot.conf.5 -usr/share/man/man8/kcatalogprint.8 -usr/share/man/man8/keymgr.8 -usr/share/man/man8/kjournalprint.8 -usr/share/man/man8/knotc.8 -usr/share/man/man8/knotd.8 diff --git a/distro/pkg/deb-noxdp/knot.postinst b/distro/pkg/deb-noxdp/knot.postinst deleted file mode 100644 index da747c8..0000000 --- a/distro/pkg/deb-noxdp/knot.postinst +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -set -e - -if [ "$1" = "configure" ]; then - if ! getent passwd knot > /dev/null; then - adduser --quiet --system --group --no-create-home --home /var/lib/knot knot - fi - - dpkg-statoverride --list /var/lib/knot >/dev/null 2>&1 || dpkg-statoverride --update --add root knot 0770 /var/lib/knot - dpkg-statoverride --list /etc/knot/knot.conf >/dev/null 2>&1 || dpkg-statoverride --update --add root knot 0640 /etc/knot/knot.conf - dpkg-statoverride --list /etc/knot >/dev/null 2>&1 || dpkg-statoverride --update --add root knot 0750 /etc/knot -fi - -#DEBHELPER# - -exit 0 diff --git a/distro/pkg/deb-noxdp/knot.postrm b/distro/pkg/deb-noxdp/knot.postrm deleted file mode 100644 index 14b3d69..0000000 --- a/distro/pkg/deb-noxdp/knot.postrm +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -set -e - -if test "$1" = "purge"; then - state_dir=/var/lib/knot - for db_name in "catalog" "confdb" "journal" "keys" "timers"; do - rm -rf $state_dir/$db_name >/dev/null 2>&1 || true - done - rmdir $state_dir >/dev/null 2>&1 || true - [ -e $state_dir/* ] && echo "Notice: there are still data in ${state_dir}, please check." - - dpkg-statoverride --remove /var/lib/knot >/dev/null 2>&1 || true - dpkg-statoverride --remove /etc/knot/knot.conf >/dev/null 2>&1 || true - dpkg-statoverride --remove /etc/knot >/dev/null 2>&1 || true - - deluser --quiet knot >/dev/null 2>&1 || true -fi - -#DEBHELPER# - -exit 0 diff --git a/distro/pkg/deb-noxdp/knot.service b/distro/pkg/deb-noxdp/knot.service deleted file mode 100644 index e6c13ed..0000000 --- a/distro/pkg/deb-noxdp/knot.service +++ /dev/null @@ -1,30 +0,0 @@ -[Unit] -Description=Knot DNS server -Wants=network-online.target -After=network-online.target -Documentation=man:knotd(8) man:knot.conf(5) man:knotc(8) - -[Service] -Type=notify -User=knot -Group=knot -CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETPCAP -AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_SETPCAP -ExecStartPre=/usr/sbin/knotc conf-check -ExecStart=/usr/sbin/knotd -m "$KNOT_CONF_MAX_SIZE" -ExecReload=/bin/kill -HUP $MAINPID -Restart=on-abort -LimitNOFILE=1048576 -TimeoutStopSec=300 -# Extend the systemd startup timeout by this value (seconds) for each zone -Environment="KNOT_ZONE_LOAD_TIMEOUT_SEC=180" -# Maximum size (MiB) of a configuration database -Environment="KNOT_CONF_MAX_SIZE=512" - -# Expected systemd >= v239 -RuntimeDirectory=knot -StateDirectory=knot -NoNewPrivileges=yes - -[Install] -WantedBy=multi-user.target diff --git a/distro/pkg/deb-noxdp/libdnssec9.install b/distro/pkg/deb-noxdp/libdnssec9.install deleted file mode 100644 index 17a9fe6..0000000 --- a/distro/pkg/deb-noxdp/libdnssec9.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/*/libdnssec.so.* diff --git a/distro/pkg/deb-noxdp/libdnssec9.symbols b/distro/pkg/deb-noxdp/libdnssec9.symbols deleted file mode 100644 index c3ab2ed..0000000 --- a/distro/pkg/deb-noxdp/libdnssec9.symbols +++ /dev/null @@ -1,96 +0,0 @@ -libdnssec.so.9 libdnssec9 #MINVER# -* Build-Depends-Package: libknot-dev - dnssec_algorithm_digest_support@Base 3.2.0 - dnssec_algorithm_key_size_check@Base 3.2.0 - dnssec_algorithm_key_size_default@Base 3.2.0 - dnssec_algorithm_key_size_range@Base 3.2.0 - dnssec_algorithm_key_support@Base 3.2.0 - dnssec_algorithm_reproducible@Base 3.2.0 - dnssec_binary_alloc@Base 3.2.0 - dnssec_binary_cmp@Base 3.2.0 - dnssec_binary_dup@Base 3.2.0 - dnssec_binary_free@Base 3.2.0 - dnssec_binary_from_base64@Base 3.2.0 - dnssec_binary_resize@Base 3.2.0 - dnssec_binary_to_base64@Base 3.2.0 - dnssec_crypto_cleanup@Base 3.2.0 - dnssec_crypto_init@Base 3.2.0 - dnssec_crypto_reinit@Base 3.2.0 - dnssec_digest@Base 3.2.0 - dnssec_digest_finish@Base 3.2.0 - dnssec_digest_init@Base 3.2.0 - dnssec_key_can_sign@Base 3.2.0 - dnssec_key_can_verify@Base 3.2.0 - dnssec_key_clear@Base 3.2.0 - dnssec_key_create_ds@Base 3.2.0 - dnssec_key_dup@Base 3.2.0 - dnssec_key_free@Base 3.2.0 - dnssec_key_get_algorithm@Base 3.2.0 - dnssec_key_get_dname@Base 3.2.0 - dnssec_key_get_flags@Base 3.2.0 - dnssec_key_get_keyid@Base 3.2.0 - dnssec_key_get_keytag@Base 3.2.0 - dnssec_key_get_protocol@Base 3.2.0 - dnssec_key_get_pubkey@Base 3.2.0 - dnssec_key_get_rdata@Base 3.2.0 - dnssec_key_get_size@Base 3.2.0 - dnssec_key_load_pkcs8@Base 3.2.0 - dnssec_key_new@Base 3.2.0 - dnssec_key_set_algorithm@Base 3.2.0 - dnssec_key_set_dname@Base 3.2.0 - dnssec_key_set_flags@Base 3.2.0 - dnssec_key_set_protocol@Base 3.2.0 - dnssec_key_set_pubkey@Base 3.2.0 - dnssec_key_set_rdata@Base 3.2.0 - dnssec_keyid_copy@Base 3.2.0 - dnssec_keyid_equal@Base 3.2.0 - dnssec_keyid_is_valid@Base 3.2.0 - dnssec_keyid_normalize@Base 3.2.0 - dnssec_keystore_close@Base 3.2.0 - dnssec_keystore_deinit@Base 3.2.0 - dnssec_keystore_generate@Base 3.2.0 - dnssec_keystore_get_private@Base 3.2.0 - dnssec_keystore_import@Base 3.2.0 - dnssec_keystore_init@Base 3.2.0 - dnssec_keystore_init_pkcs11@Base 3.2.0 - dnssec_keystore_init_pkcs8@Base 3.2.0 - dnssec_keystore_open@Base 3.2.0 - dnssec_keystore_remove@Base 3.2.0 - dnssec_keystore_set_private@Base 3.2.0 - dnssec_keytag@Base 3.2.0 - dnssec_nsec3_hash@Base 3.2.0 - dnssec_nsec3_hash_length@Base 3.2.0 - dnssec_nsec3_params_free@Base 3.2.0 - dnssec_nsec3_params_from_rdata@Base 3.2.0 - dnssec_nsec3_params_match@Base 3.2.0 - dnssec_nsec_bitmap_add@Base 3.2.0 - dnssec_nsec_bitmap_clear@Base 3.2.0 - dnssec_nsec_bitmap_contains@Base 3.2.0 - dnssec_nsec_bitmap_free@Base 3.2.0 - dnssec_nsec_bitmap_new@Base 3.2.0 - dnssec_nsec_bitmap_size@Base 3.2.0 - dnssec_nsec_bitmap_write@Base 3.2.0 - dnssec_pem_from_privkey@Base 3.2.0 - dnssec_pem_from_x509@Base 3.2.0 - dnssec_pem_to_privkey@Base 3.2.0 - dnssec_pem_to_x509@Base 3.2.0 - dnssec_random_binary@Base 3.2.0 - dnssec_random_buffer@Base 3.2.0 - dnssec_sign_add@Base 3.2.0 - dnssec_sign_free@Base 3.2.0 - dnssec_sign_init@Base 3.2.0 - dnssec_sign_new@Base 3.2.0 - dnssec_sign_verify@Base 3.2.0 - dnssec_sign_write@Base 3.2.0 - dnssec_strerror@Base 3.2.0 - dnssec_tsig_add@Base 3.2.0 - dnssec_tsig_algorithm_from_dname@Base 3.2.0 - dnssec_tsig_algorithm_from_name@Base 3.2.0 - dnssec_tsig_algorithm_size@Base 3.2.0 - dnssec_tsig_algorithm_to_dname@Base 3.2.0 - dnssec_tsig_algorithm_to_name@Base 3.2.0 - dnssec_tsig_free@Base 3.2.0 - dnssec_tsig_new@Base 3.2.0 - dnssec_tsig_optimal_key_size@Base 3.2.0 - dnssec_tsig_size@Base 3.2.0 - dnssec_tsig_write@Base 3.2.0 diff --git a/distro/pkg/deb-noxdp/libknot-dev.install b/distro/pkg/deb-noxdp/libknot-dev.install deleted file mode 100644 index cb60d88..0000000 --- a/distro/pkg/deb-noxdp/libknot-dev.install +++ /dev/null @@ -1,3 +0,0 @@ -usr/include/ -usr/lib/*/*.so -usr/lib/*/pkgconfig/* diff --git a/distro/pkg/deb-noxdp/libknot14.install b/distro/pkg/deb-noxdp/libknot14.install deleted file mode 100644 index f9b9f93..0000000 --- a/distro/pkg/deb-noxdp/libknot14.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/*/libknot.so.* diff --git a/distro/pkg/deb-noxdp/libknot14.symbols b/distro/pkg/deb-noxdp/libknot14.symbols deleted file mode 100644 index ba2024a..0000000 --- a/distro/pkg/deb-noxdp/libknot14.symbols +++ /dev/null @@ -1,226 +0,0 @@ -libknot.so.14 libknot14 #MINVER# - KNOT_DB_LMDB_DUPSORT@Base 3.3.0 - KNOT_DB_LMDB_INTEGERKEY@Base 3.3.0 - KNOT_DB_LMDB_MAPASYNC@Base 3.3.0 - KNOT_DB_LMDB_NOSYNC@Base 3.3.0 - KNOT_DB_LMDB_NOTLS@Base 3.3.0 - KNOT_DB_LMDB_RDONLY@Base 3.3.0 - KNOT_DB_LMDB_WRITEMAP@Base 3.3.0 - KNOT_DUMP_STYLE_DEFAULT@Base 3.3.0 - knot_ctl_accept@Base 3.3.0 - knot_ctl_alloc@Base 3.3.0 - knot_ctl_bind@Base 3.3.0 - knot_ctl_bind2@Base 3.3.6 - knot_ctl_close@Base 3.3.0 - knot_ctl_connect@Base 3.3.0 - knot_ctl_free@Base 3.3.0 - knot_ctl_receive@Base 3.3.0 - knot_ctl_send@Base 3.3.0 - knot_ctl_set_timeout@Base 3.3.0 - knot_ctl_unbind@Base 3.3.0 - knot_db_lmdb_api@Base 3.3.0 - knot_db_lmdb_del_exact@Base 3.3.0 - knot_db_lmdb_get_mapsize@Base 3.3.0 - knot_db_lmdb_get_path@Base 3.3.0 - knot_db_lmdb_get_usage@Base 3.3.0 - knot_db_lmdb_iter_del@Base 3.3.0 - knot_db_lmdb_txn_begin@Base 3.3.0 - knot_db_trie_api@Base 3.3.0 - knot_dname_cmp@Base 3.3.0 - knot_dname_copy@Base 3.3.0 - knot_dname_copy_lower@Base 3.3.0 - knot_dname_free@Base 3.3.0 - knot_dname_from_str@Base 3.3.0 - knot_dname_in_bailiwick@Base 3.3.0 - knot_dname_is_case_equal@Base 3.3.0 - knot_dname_is_equal@Base 3.3.0 - knot_dname_labels@Base 3.3.0 - knot_dname_lf@Base 3.3.0 - knot_dname_matched_labels@Base 3.3.0 - knot_dname_prefixlen@Base 3.3.0 - knot_dname_realsize@Base 3.3.0 - knot_dname_replace_suffix@Base 3.3.0 - knot_dname_size@Base 3.3.0 - knot_dname_store@Base 3.3.0 - knot_dname_to_lower@Base 3.3.0 - knot_dname_to_str@Base 3.3.0 - knot_dname_to_wire@Base 3.3.0 - knot_dname_unpack@Base 3.3.0 - knot_dname_wire_check@Base 3.3.0 - knot_dnssec_alg_names@Base 3.3.0 - knot_edns_add_option@Base 3.3.0 - knot_edns_alignment_size@Base 3.3.0 - knot_edns_chain_parse@Base 3.3.0 - knot_edns_chain_size@Base 3.3.0 - knot_edns_chain_write@Base 3.3.0 - knot_edns_client_subnet_get_addr@Base 3.3.0 - knot_edns_client_subnet_parse@Base 3.3.0 - knot_edns_client_subnet_set_addr@Base 3.3.0 - knot_edns_client_subnet_size@Base 3.3.0 - knot_edns_client_subnet_write@Base 3.3.0 - knot_edns_cookie_client_check@Base 3.3.0 - knot_edns_cookie_client_generate@Base 3.3.0 - knot_edns_cookie_parse@Base 3.3.0 - knot_edns_cookie_server_check@Base 3.3.0 - knot_edns_cookie_server_generate@Base 3.3.0 - knot_edns_cookie_size@Base 3.3.0 - knot_edns_cookie_write@Base 3.3.0 - knot_edns_ede_names@Base 3.3.0 - knot_edns_get_ext_rcode@Base 3.3.0 - knot_edns_get_option@Base 3.3.0 - knot_edns_get_options@Base 3.3.0 - knot_edns_get_version@Base 3.3.0 - knot_edns_init@Base 3.3.0 - knot_edns_keepalive_parse@Base 3.3.0 - knot_edns_keepalive_size@Base 3.3.0 - knot_edns_keepalive_write@Base 3.3.0 - knot_edns_opt_names@Base 3.3.0 - knot_edns_reserve_option@Base 3.3.0 - knot_edns_set_ext_rcode@Base 3.3.0 - knot_edns_set_version@Base 3.3.0 - knot_error_from_libdnssec@Base 3.3.0 - knot_get_obsolete_rdata_descriptor@Base 3.3.0 - knot_get_rdata_descriptor@Base 3.3.0 - knot_naptr_header_size@Base 3.3.0 - knot_opcode_names@Base 3.3.0 - knot_opt_code_to_string@Base 3.3.0 - knot_pkt_begin@Base 3.3.0 - knot_pkt_clear@Base 3.3.0 - knot_pkt_copy@Base 3.3.0 - knot_pkt_ext_rcode@Base 3.3.0 - knot_pkt_ext_rcode_name@Base 3.3.0 - knot_pkt_free@Base 3.3.0 - knot_pkt_init_response@Base 3.3.0 - knot_pkt_new@Base 3.3.0 - knot_pkt_parse@Base 3.3.0 - knot_pkt_parse_question@Base 3.3.0 - knot_pkt_put_question@Base 3.3.0 - knot_pkt_put_rotate@Base 3.3.0 - knot_pkt_reclaim@Base 3.3.0 - knot_pkt_reserve@Base 3.3.0 - knot_probe_alloc@Base 3.3.0 - knot_probe_consume@Base 3.3.0 - knot_probe_data_set@Base 3.3.0 - knot_probe_fd@Base 3.3.0 - knot_probe_free@Base 3.3.0 - knot_probe_produce@Base 3.3.0 - knot_probe_set_consumer@Base 3.3.0 - knot_probe_set_producer@Base 3.3.0 - knot_probe_tcp_rtt@Base 3.3.0 - knot_rcode_names@Base 3.3.0 - knot_rdataset_add@Base 3.3.0 - knot_rdataset_at@Base 3.3.0 - knot_rdataset_clear@Base 3.3.0 - knot_rdataset_copy@Base 3.3.0 - knot_rdataset_eq@Base 3.3.0 - knot_rdataset_intersect@Base 3.3.0 - knot_rdataset_intersect2@Base 3.3.0 - knot_rdataset_member@Base 3.3.0 - knot_rdataset_merge@Base 3.3.0 - knot_rdataset_subset@Base 3.3.0 - knot_rdataset_subtract@Base 3.3.0 - knot_rrclass_from_string@Base 3.3.0 - knot_rrclass_to_string@Base 3.3.0 - knot_rrset_add_rdata@Base 3.3.0 - knot_rrset_clear@Base 3.3.0 - knot_rrset_copy@Base 3.3.0 - knot_rrset_equal@Base 3.3.0 - knot_rrset_free@Base 3.3.0 - knot_rrset_is_nsec3rel@Base 3.3.0 - knot_rrset_new@Base 3.3.0 - knot_rrset_rr_from_wire@Base 3.3.0 - knot_rrset_rr_to_canonical@Base 3.3.0 - knot_rrset_size@Base 3.3.0 - knot_rrset_to_wire_extra@Base 3.3.0 - knot_rrset_txt_dump@Base 3.3.0 - knot_rrset_txt_dump_data@Base 3.3.0 - knot_rrset_txt_dump_edns@Base 3.3.0 - knot_rrset_txt_dump_header@Base 3.3.0 - knot_rrtype_additional_needed@Base 3.3.0 - knot_rrtype_from_string@Base 3.3.0 - knot_rrtype_is_dnssec@Base 3.3.0 - knot_rrtype_is_metatype@Base 3.3.0 - knot_rrtype_should_be_lowercased@Base 3.3.0 - knot_rrtype_to_string@Base 3.3.0 - knot_strerror@Base 3.3.0 - knot_svcb_param_names@Base 3.3.0 - knot_tcp_inbufs_upd@Base 3.3.0 - knot_tcp_outbufs_ack@Base 3.3.0 - knot_tcp_outbufs_add@Base 3.3.0 - knot_tcp_outbufs_can_send@Base 3.3.0 - knot_tcp_outbufs_usage@Base 3.3.0 - knot_tsig_add@Base 3.3.0 - knot_tsig_append@Base 3.3.0 - knot_tsig_client_check@Base 3.3.0 - knot_tsig_client_check_next@Base 3.3.0 - knot_tsig_create_rdata@Base 3.3.0 - knot_tsig_key_copy@Base 3.3.0 - knot_tsig_key_deinit@Base 3.3.0 - knot_tsig_key_init@Base 3.3.0 - knot_tsig_key_init_file@Base 3.3.0 - knot_tsig_key_init_str@Base 3.3.0 - knot_tsig_rcode_names@Base 3.3.0 - knot_tsig_rdata_alg@Base 3.3.0 - knot_tsig_rdata_alg_name@Base 3.3.0 - knot_tsig_rdata_error@Base 3.3.0 - knot_tsig_rdata_fudge@Base 3.3.0 - knot_tsig_rdata_is_ok@Base 3.3.0 - knot_tsig_rdata_mac@Base 3.3.0 - knot_tsig_rdata_mac_length@Base 3.3.0 - knot_tsig_rdata_orig_id@Base 3.3.0 - knot_tsig_rdata_other_data@Base 3.3.0 - knot_tsig_rdata_other_data_length@Base 3.3.0 - knot_tsig_rdata_set_fudge@Base 3.3.0 - knot_tsig_rdata_set_mac@Base 3.3.0 - knot_tsig_rdata_set_orig_id@Base 3.3.0 - knot_tsig_rdata_set_other_data@Base 3.3.0 - knot_tsig_rdata_set_time_signed@Base 3.3.0 - knot_tsig_rdata_time_signed@Base 3.3.0 - knot_tsig_rdata_tsig_timers_length@Base 3.3.0 - knot_tsig_rdata_tsig_variables_length@Base 3.3.0 - knot_tsig_server_check@Base 3.3.0 - knot_tsig_sign@Base 3.3.0 - knot_tsig_sign_next@Base 3.3.0 - knot_tsig_wire_maxsize@Base 3.3.0 - knot_tsig_wire_size@Base 3.3.0 - yp_addr@Base 3.3.0 - yp_addr_noport@Base 3.3.0 - yp_addr_noport_to_bin@Base 3.3.0 - yp_addr_noport_to_txt@Base 3.3.0 - yp_addr_range_to_bin@Base 3.3.0 - yp_addr_range_to_txt@Base 3.3.0 - yp_addr_to_bin@Base 3.3.0 - yp_addr_to_txt@Base 3.3.0 - yp_base64_to_bin@Base 3.3.0 - yp_base64_to_txt@Base 3.3.0 - yp_bool_to_bin@Base 3.3.0 - yp_bool_to_txt@Base 3.3.0 - yp_deinit@Base 3.3.0 - yp_dname_to_bin@Base 3.3.0 - yp_dname_to_txt@Base 3.3.0 - yp_format_id@Base 3.3.0 - yp_format_key0@Base 3.3.0 - yp_format_key1@Base 3.3.0 - yp_hex_to_bin@Base 3.3.0 - yp_hex_to_txt@Base 3.3.0 - yp_init@Base 3.3.0 - yp_int_to_bin@Base 3.3.0 - yp_int_to_txt@Base 3.3.0 - yp_item_to_bin@Base 3.3.0 - yp_item_to_txt@Base 3.3.0 - yp_option_to_bin@Base 3.3.0 - yp_option_to_txt@Base 3.3.0 - yp_parse@Base 3.3.0 - yp_schema_check_deinit@Base 3.3.0 - yp_schema_check_init@Base 3.3.0 - yp_schema_check_parser@Base 3.3.0 - yp_schema_check_str@Base 3.3.0 - yp_schema_copy@Base 3.3.0 - yp_schema_find@Base 3.3.0 - yp_schema_free@Base 3.3.0 - yp_schema_merge@Base 3.3.0 - yp_schema_purge_dynamic@Base 3.3.0 - yp_set_input_file@Base 3.3.0 - yp_set_input_string@Base 3.3.0 - yp_str_to_bin@Base 3.3.0 - yp_str_to_txt@Base 3.3.0 diff --git a/distro/pkg/deb-noxdp/libzscanner4.install b/distro/pkg/deb-noxdp/libzscanner4.install deleted file mode 100644 index a8dc226..0000000 --- a/distro/pkg/deb-noxdp/libzscanner4.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/*/libzscanner.so.* diff --git a/distro/pkg/deb-noxdp/libzscanner4.symbols b/distro/pkg/deb-noxdp/libzscanner4.symbols deleted file mode 100644 index 99ac3b7..0000000 --- a/distro/pkg/deb-noxdp/libzscanner4.symbols +++ /dev/null @@ -1,12 +0,0 @@ -libzscanner.so.4 libzscanner4 #MINVER# -* Build-Depends-Package: libknot-dev - zs_deinit@Base 3.1.0 - zs_errorname@Base 3.1.0 - zs_init@Base 3.1.0 - zs_parse_all@Base 3.1.0 - zs_parse_record@Base 3.1.0 - zs_set_input_file@Base 3.1.0 - zs_set_input_string@Base 3.1.0 - zs_set_processing@Base 3.1.0 - zs_set_processing_comment@Base 3.1.0 - zs_strerror@Base 3.1.0 diff --git a/distro/pkg/deb-noxdp/not-installed b/distro/pkg/deb-noxdp/not-installed deleted file mode 100644 index c928be1..0000000 --- a/distro/pkg/deb-noxdp/not-installed +++ /dev/null @@ -1 +0,0 @@ -etc/knot/example.com.zone diff --git a/distro/pkg/deb-noxdp/patches/05-revert-mod-dnstap-TCP-sink.patch b/distro/pkg/deb-noxdp/patches/05-revert-mod-dnstap-TCP-sink.patch deleted file mode 100644 index dae0fac..0000000 --- a/distro/pkg/deb-noxdp/patches/05-revert-mod-dnstap-TCP-sink.patch +++ /dev/null @@ -1,160 +0,0 @@ -From d236d2b7fcd5fa607f7bfd38044eb6f510fac7ce Mon Sep 17 00:00:00 2001 -From: Daniel Salzman -Date: Wed, 12 Jun 2024 11:18:31 +0200 -Subject: [PATCH] Revert "mod-dnstap: add sink for TCP connection" - -This reverts commit 2ffd7dfa58ddcd1b860f0c9980fd082c3852d3e6. ---- - src/knot/modules/dnstap/dnstap.c | 74 +++++------------------------- - src/knot/modules/dnstap/dnstap.rst | 9 ++-- - 2 files changed, 15 insertions(+), 68 deletions(-) - -diff --git a/src/knot/modules/dnstap/dnstap.c b/src/knot/modules/dnstap/dnstap.c -index 612e48869..c8c82eaa4 100644 ---- a/src/knot/modules/dnstap/dnstap.c -+++ b/src/knot/modules/dnstap/dnstap.c -@@ -1,4 +1,4 @@ --/* Copyright (C) 2024 CZ.NIC, z.s.p.o. -+/* Copyright (C) 2023 CZ.NIC, z.s.p.o. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by -@@ -185,33 +185,6 @@ finish: - return writer; - } - --static struct fstrm_writer* dnstap_tcp_writer(const char *address, const char *port) --{ -- struct fstrm_tcp_writer_options *opt = NULL; -- struct fstrm_writer_options *wopt = NULL; -- struct fstrm_writer *writer = NULL; -- -- opt = fstrm_tcp_writer_options_init(); -- if (opt == NULL) { -- goto finish; -- } -- -- fstrm_tcp_writer_options_set_socket_address(opt, address); -- fstrm_tcp_writer_options_set_socket_port(opt, port); -- -- wopt = fstrm_writer_options_init(); -- if (wopt == NULL) { -- goto finish; -- } -- fstrm_writer_options_add_content_type(wopt, DNSTAP_CONTENT_TYPE, -- strlen(DNSTAP_CONTENT_TYPE)); -- writer = fstrm_tcp_writer_init(opt, wopt); --finish: -- fstrm_tcp_writer_options_destroy(&opt); -- fstrm_writer_options_destroy(&wopt); -- return writer; --} -- - /*! \brief Create a basic file writer sink. */ - static struct fstrm_writer* dnstap_file_writer(const char *path) - { -@@ -240,42 +213,17 @@ finish: - } - - /*! \brief Create a log sink according to the path string. */ --static struct fstrm_writer* dnstap_writer(knotd_mod_t *mod, const char *path) -+static struct fstrm_writer* dnstap_writer(const char *path) - { -- const char *unix_prefix = "unix:"; -- const size_t unix_prefix_len = strlen(unix_prefix); -- -- const char *tcp_prefix = "tcp:"; -- const size_t tcp_prefix_len = strlen(tcp_prefix); -- -- const size_t path_len = strlen(path); -+ const char *prefix = "unix:"; -+ const size_t prefix_len = strlen(prefix); - - /* UNIX socket prefix. */ -- if (path_len > unix_prefix_len && -- strncmp(path, unix_prefix, unix_prefix_len) == 0) { -- knotd_mod_log(mod, LOG_DEBUG, "using sink UNIX socket '%s'", path); -- return dnstap_unix_writer(path + unix_prefix_len); -- /* TCP socket prefix. */ -- } else if (path_len > tcp_prefix_len && -- strncmp(path, tcp_prefix, tcp_prefix_len) == 0) { -- char addr[INET6_ADDRSTRLEN] = { 0 }; -- const char *delimiter = strchr(path + tcp_prefix_len, '@'); -- if (delimiter == NULL) { -- return NULL; -- } -- size_t addr_len = delimiter - path - tcp_prefix_len; -- if (addr_len >= sizeof(addr)) { -- return NULL; -- } -- memcpy(addr, path + tcp_prefix_len, addr_len); -- knotd_mod_log(mod, LOG_DEBUG, "using sink TCP address '%s' port '%s'", -- addr, delimiter + 1); -- return dnstap_tcp_writer(addr, delimiter + 1); -- /* File path. */ -- } else { -- knotd_mod_log(mod, LOG_DEBUG, "using sink file '%s'", path); -- return dnstap_file_writer(path); -+ if (strlen(path) > prefix_len && strncmp(path, prefix, prefix_len) == 0) { -+ return dnstap_unix_writer(path + prefix_len); - } -+ -+ return dnstap_file_writer(path); - } - - int dnstap_load(knotd_mod_t *mod) -@@ -325,7 +273,7 @@ int dnstap_load(knotd_mod_t *mod) - const bool log_responses = conf.single.boolean; - - /* Initialize the writer and the options. */ -- struct fstrm_writer *writer = dnstap_writer(mod, sink); -+ struct fstrm_writer *writer = dnstap_writer(sink); - if (writer == NULL) { - goto fail; - } -@@ -359,13 +307,13 @@ int dnstap_load(knotd_mod_t *mod) - - return KNOT_EOK; - fail: -- knotd_mod_log(mod, LOG_ERR, "failed to initialize sink '%s'", sink); -+ knotd_mod_log(mod, LOG_ERR, "failed to init sink '%s'", sink); - - free(ctx->identity); - free(ctx->version); - free(ctx); - -- return KNOT_EINVAL; -+ return KNOT_ENOMEM; - } - - void dnstap_unload(knotd_mod_t *mod) -diff --git a/src/knot/modules/dnstap/dnstap.rst b/src/knot/modules/dnstap/dnstap.rst -index 05eac09ab..358977da0 100644 ---- a/src/knot/modules/dnstap/dnstap.rst -+++ b/src/knot/modules/dnstap/dnstap.rst -@@ -11,7 +11,7 @@ Example - ------- - - The configuration comprises only a :ref:`mod-dnstap_sink` path parameter, --which can be either a file, a UNIX socket, or a TCP address:: -+which can be either a file or a UNIX socket:: - - mod-dnstap: - - id: capture_all -@@ -60,10 +60,9 @@ A module identifier. - sink - .... - --A sink path, which can be either a file, a UNIX socket when prefixed with --``unix:``, or a TCP `address@port` when prefixed with ``tcp:``. The file may --be specified as an absolute path or a path relative to --the :doc:`knotd` startup directory. -+A sink path, which can be either a file or a UNIX socket when prefixed with -+``unix:``. The file may be specified as an absolute path or a path relative -+to the :doc:`knotd` startup directory. - - *Required* - --- -2.34.1 - diff --git a/distro/pkg/deb-noxdp/patches/series b/distro/pkg/deb-noxdp/patches/series deleted file mode 100644 index 54de4e3..0000000 --- a/distro/pkg/deb-noxdp/patches/series +++ /dev/null @@ -1 +0,0 @@ -05-revert-mod-dnstap-TCP-sink.patch diff --git a/distro/pkg/deb-noxdp/prepare-environment b/distro/pkg/deb-noxdp/prepare-environment deleted file mode 100755 index 7176f5e..0000000 --- a/distro/pkg/deb-noxdp/prepare-environment +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -set -eu - -CONFFILE=${1:-/etc/knot/knot.conf} - -if [ ! -r $CONFFILE ]; then - echo "$CONFFILE doesn't exist or has wrong permissions." - exit 1; -fi - -KNOT_RUNDIR=$(sed -ne "s/#.*$//;s/.*rundir: \"*\([^\";]*\\).*/\\1/p;" $CONFFILE) -[ -z "$KNOT_RUNDIR" ] && KNOT_RUNDIR=/run/knot - -mkdir --parents "$KNOT_RUNDIR"; - -KNOT_USER=$(sed -ne "s/#.*$//;s/.*user:[ \"]*\\([^\\:\"]*\\)[ \"]*/\\1/p;" $CONFFILE) - -if [ -n "$KNOT_USER" ]; then - if ! getent passwd $KNOT_USER >/dev/null; then - echo "Configured user '$KNOT_USER' doesn't exist." - exit 1 - fi - - KNOT_GROUP=$(sed -ne "s/#.*$//;s/.*user:[ \"]*[^\\:\"]*\\:\\([^\"]*\\)[ \"]*/\\1/p;" $CONFFILE) - if [ -z "$KNOT_GROUP" ]; then - KNOT_GROUP=$(getent group $(getent passwd "$KNOT_USER" | cut -f 4 -d :) | cut -f 1 -d :) - fi - - if ! getent group $KNOT_GROUP >/dev/null; then - echo "Configured group '$KNOT_GROUP' doesn't exist." - exit 1 - fi - chown --silent "$KNOT_USER:$KNOT_GROUP" "$KNOT_RUNDIR" - chmod 775 "$KNOT_RUNDIR" -fi - -: diff --git a/distro/pkg/deb-noxdp/python3-libknot.install b/distro/pkg/deb-noxdp/python3-libknot.install deleted file mode 100644 index ce92dec..0000000 --- a/distro/pkg/deb-noxdp/python3-libknot.install +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/python3*/dist-packages/libknot-*.egg-info -usr/lib/python3*/dist-packages/libknot/*.py diff --git a/distro/pkg/deb-noxdp/rules b/distro/pkg/deb-noxdp/rules deleted file mode 100755 index 2372f70..0000000 --- a/distro/pkg/deb-noxdp/rules +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/make -f - -export DEB_BUILD_MAINT_OPTIONS = hardening=+all -export DEB_CFLAGS_MAINT_APPEND = -Wall -DNDEBUG -export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed - -export DPKG_GENSYMBOLS_CHECK_LEVEL := 4 -export KNOT_SOFTHSM2_DSO = /usr/lib/softhsm/libsofthsm2.so - -include /usr/share/dpkg/default.mk - -ifeq (maint,$(filter $(DEB_BUILD_OPTIONS),maint)) - FASTPARSER := --disable-fastparser -else - FASTPARSER := --enable-fastparser -endif - -ifeq ($(DEB_HOST_ARCH),$(filter $(DEB_HOST_ARCH),hurd-i386)) - RECVMMSG:=--enable-recvmmsg=no -else - RECVMMSG:=--enable-recvmmsg=yes -endif - -ifeq ($(DEB_HOST_ARCH),$(filter $(DEB_HOST_ARCH),amd64 i386)) - RUN_TEST := -else - RUN_TEST := -timeout --kill-after=5s 5m -endif - -LIBKNOT_SYMBOLS := $(wildcard $(CURDIR)/debian/libknot*.symbols) - -# MAJOR.MINOR version part -BASE_VERSION := $(shell echo $(DEB_VERSION) | sed 's/^\([^.]\+\.[^.]\+\).*/\1/') - -# pyproject is supported by knot but fails on second `pybuild --build` -# invocation due to bug in dh-python's plugin_pyproject.py wheel unpack -export PYBUILD_SYSTEM = distutils - - -%: - dh $@ \ - --exclude=.la --exclude=example.com.zone \ - --with python3 - -override_dh_auto_configure: - dh_auto_configure -- \ - --sysconfdir=/etc \ - --localstatedir=/var/lib \ - --libexecdir=/usr/lib/knot \ - --with-rundir=/run/knot \ - --with-moduledir=/usr/lib/$(DEB_HOST_MULTIARCH)/knot/modules-$(BASE_VERSION) \ - --with-storage=/var/lib/knot \ - --enable-systemd=auto \ - --enable-dnstap \ - --with-module-dnstap=shared \ - --with-module-geoip=shared \ - $(RECVMMSG) \ - $(FASTPARSER) \ - --disable-silent-rules \ - --disable-static - -override_dh_auto_configure-indep: - pybuild --dir python/libknot --configure - pybuild --dir python/knot_exporter --configure - -override_dh_auto_build-indep: - dh_auto_build -- html - pybuild --dir python/libknot --build - pybuild --dir python/knot_exporter --build - -override_dh_auto_install-arch: - dh_auto_install -- install - # rename knot.sample.conf to knot.conf - mv $(CURDIR)/debian/tmp/etc/knot/knot.sample.conf $(CURDIR)/debian/tmp/etc/knot/knot.conf - -override_dh_auto_install-indep: - dh_auto_install -- install-html - # rename knot.sample.conf to knot.conf - mv $(CURDIR)/debian/tmp/etc/knot/knot.sample.conf $(CURDIR)/debian/tmp/etc/knot/knot.conf - pybuild --dir python/libknot --install - pybuild --dir python/knot_exporter --install - rm -rf $(CURDIR)/debian/tmp/usr/lib/python*/dist-packages/libknot/__pycache__ - rm -rf $(CURDIR)/debian/tmp/usr/lib/python*/dist-packages/knot_exporter/__pycache__ - -override_dh_auto_test-indep: -override_dh_auto_test-arch: -ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) - $(RUN_TEST) dh_auto_test -endif - -override_dh_missing: - dh_missing --fail-missing - -override_dh_installchangelogs: - dh_installchangelogs NEWS diff --git a/distro/pkg/deb-noxdp/source/format b/distro/pkg/deb-noxdp/source/format deleted file mode 100644 index 163aaf8..0000000 --- a/distro/pkg/deb-noxdp/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/distro/pkg/deb-noxdp/tests/authoritative-server b/distro/pkg/deb-noxdp/tests/authoritative-server deleted file mode 100755 index 028dfbf..0000000 --- a/distro/pkg/deb-noxdp/tests/authoritative-server +++ /dev/null @@ -1,150 +0,0 @@ -#!/bin/bash - -# Author: Daniel Kahn Gillmor -# 2018-11-02 -# License: GPLv3+ - -# error on exit -set -e -# for handling jobspecs: -set -m - -if [ -z "$AUTOPKGTEST_ARTIFACTS" ]; then - d="$(mktemp -d)" - remove="$d" -else - d="$AUTOPKGTEST_ARTIFACTS" -fi -ip="${TESTIP:-127.$(( $RANDOM % 256 )).$(( $RANDOM % 256 )).$(( $RANDOM % 256 ))}" -port="${PORT:-8123}" -knotc="${KNOTC:-/usr/sbin/knotc}" -knotd="${KNOTD:-/usr/sbin/knotd}" -keymgr="${KEYMGR:-/usr/sbin/keymgr}" -kdig="${KDIG:-$(command -v kdig)}" -kzonecheck="${KZONECHECK:-$(command -v kzonecheck)}" -test_address="${TEST_ADDRESS:-192.0.2.199}" - -declare -a knot_conf="--config=$d/knot.conf" -declare -a knot_args=("$knot_conf" --verbose) - -printf "%s + %s roundtrip tests\n------------\n workdir: %s\n IP addr: %s\n knot args: %s\n" "$knotd" "$kdig" "$d" "$ip" "${knot_args[*]}" - -section() { - printf "\n%s\n" "$1" - sed 's/./-/g' <<<"$1" -} - -cleanup () { - section "cleaning up" - find "$d" -ls - "${knotc}" "${knot_args[@]}" stop - wait %1 - tail -n +1 -v "$d"/*.err - if [ "$remove" ]; then - printf "\ncleaning up working directory %s\n" "$remove" - rm -rf "$remove" - fi -} -trap cleanup EXIT - -section "set up config file and zonefile" - -user=$(id -nu) -group=$(id -ng) -cat > "$d/knot.conf" < "$d/example.net.zone" < "$d/knotd.err" & - -# FIXME: this is an annoying poll -- would be better if we could be -# alerted when the daemon is done setting up the socket, but i don't -# want to "--daemonize" if i can avoid it because i want the shell to -# remain in direct supervision of all its processes -tried=0 -while [ $tried -lt 10 ] ; do - if "${knotc}" "${knot_args[@]}" status 2>&1; then - break; - fi - sleep 0.5 - tried=$(( $tried + 1 )) -done -if [ $tried -ge 10 ]; then - printf "failed to use %s\n" "${knotc}" >&2 - exit 1 -fi - -section "querying knot" -"${kdig}" -p "${port}" @"${ip}" -t A test.example.net test2.example.net -answer="$("${kdig}" +short -p "${port}" @"${ip}" -t A test.example.net)" -if ! [ "$answer" = "$test_address" ]; then - printf "test.example.net mismatch!\nexpected: %s\n got: %s\n" "$test_address" "$answer" >&2 - exit 1 -fi -answer2="$("${kdig}" +short -p "${port}" @"${ip}" -t A test2.example.net)" -if ! [ "$answer2" = "" ]; then - printf "test2.example.net gave unexpected answer!\n got: %s\n" "$answer2" >&2 - exit 1 -fi - -section "modifying zone" -printf "test2 1D IN A $test_address\n" >>"$d/example.net.zone" -sed -i 's/^@ 1D IN SOA.*/@ 1D IN SOA a.ns hostmaster 2018110100 3h 15m 1w 1d/' "$d/example.net.zone" -"${knotc}" "${knot_args[@]}" reload -sleep 1 - -section "querying again" -"${kdig}" -p "${port}" @"${ip}" -t A test.example.net test2.example.net -answer="$("${kdig}" +short -p "${port}" @"${ip}" -t A test.example.net)" -if ! [ "$answer" = "$test_address" ]; then - printf "test.example.net mismatch!\nexpected: %s\n got: %s\n" "$test_address" "$answer" >&2 - exit 1 -fi -answer2="$("${kdig}" +short -p "${port}" @"${ip}" -t A test2.example.net)" -if ! [ "$answer2" = "$test_address" ]; then - printf "test2.example.net mismatch!\nexpected: %s\n got: %s\n" "$test_address" "$answer2" >&2 - exit 1 -fi - -section "querying DNSSEC" -"${kdig}" -p "${port}" @"${ip}" -t DNSKEY example.net. +dnssec -if ! "${kdig}" -p "${port}" @"${ip}" -t DNSKEY example.net. +dnssec 2>&1 | grep -q "RRSIG[[:space:]]*DNSKEY"; then - printf "DNSSEC query not successful" >&2 - exit 1 -fi - -section "listing keys with keymgr" -"${keymgr}" "$knot_conf" -e example.net. list -if ! "${keymgr}" "$knot_conf" -e example.net. list 2>&1 | grep -q "ksk=yes"; then - printf "keymgr did not list KSK as expected" >&2 - exit 1 -fi diff --git a/distro/pkg/deb-noxdp/tests/control b/distro/pkg/deb-noxdp/tests/control deleted file mode 100644 index e8b3dcb..0000000 --- a/distro/pkg/deb-noxdp/tests/control +++ /dev/null @@ -1,13 +0,0 @@ -Tests: kdig -Restrictions: skippable -Depends: - ca-certificates, - iputils-ping, - knot-dnsutils, - -Tests: authoritative-server -Depends: - findutils, - knot, - knot-dnsutils, - knot-dnssecutils, diff --git a/distro/pkg/deb-noxdp/tests/kdig b/distro/pkg/deb-noxdp/tests/kdig deleted file mode 100755 index f1dbe5a..0000000 --- a/distro/pkg/deb-noxdp/tests/kdig +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -set -e - -# Skip the test if no internet access -ping -c1 1.1.1.1 2>&1 || exit 77 - -expected=198.41.0.4 -answer=$(kdig +short +tls-ca @1.1.1.1 -q a.root-servers.net. -t A 2>&1 || true) - -if [ "$answer" != "$expected" ]; then - printf "expected: %s\ngot: %s\n" "$expected" "$answer" >&2 - kdig -d +tls-ca @1.1.1.1 -q a.root-servers.net. -t A -fi diff --git a/distro/pkg/deb-noxdp/ufw/knot b/distro/pkg/deb-noxdp/ufw/knot deleted file mode 100644 index ee36916..0000000 --- a/distro/pkg/deb-noxdp/ufw/knot +++ /dev/null @@ -1,4 +0,0 @@ -[Knot] -title=Internet Domain Name Server -description=The Knot DNS implements an Internet domain name server. -ports=53 diff --git a/distro/pkg/deb-noxdp/watch b/distro/pkg/deb-noxdp/watch deleted file mode 100644 index 7cf9ea1..0000000 --- a/distro/pkg/deb-noxdp/watch +++ /dev/null @@ -1,4 +0,0 @@ -version=4 -opts=uversionmangle=s/-((alpha|beta|rc)\d*)$/~$1/,pgpsigurlmangle=s/$/.asc/,dversionmangle=s/\+hotfix// \ -https://secure.nic.cz/files/knot-dns/ \ -(?:|.*/)knot(?:[_\-]v?|)(\d\S*)\.(?:tar\.xz|txz|tar\.bz2|tbz2|tar\.gz|tgz) diff --git a/distro/pkg/deb/control b/distro/pkg/deb/control index 5df1b62..b98dc4a 100644 --- a/distro/pkg/deb/control +++ b/distro/pkg/deb/control @@ -45,7 +45,7 @@ Architecture: any Depends: adduser, libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), libzscanner4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}, @@ -61,7 +61,7 @@ Description: Authoritative domain name server registry and hence is well suited to run anything from the root zone, the top-level domain, to many smaller standard domain names. -Package: libknot14 +Package: libknot15 Architecture: any Depends: ${misc:Depends}, @@ -117,7 +117,7 @@ Architecture: any Depends: libdnssec9 (= ${binary:Version}), libgnutls28-dev, - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), libzscanner4 (= ${binary:Version}), ${misc:Depends}, Section: libdevel @@ -135,7 +135,7 @@ Package: knot-dnsutils Architecture: any Depends: libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), libzscanner4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}, @@ -162,7 +162,7 @@ Package: knot-dnssecutils Architecture: any Depends: libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), libzscanner4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}, @@ -184,7 +184,7 @@ Package: knot-host Architecture: any Depends: libdnssec9 (= ${binary:Version}), - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), libzscanner4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}, @@ -270,7 +270,7 @@ Description: Prometheus exporter for Knot DNS Package: python3-libknot Architecture: all Depends: - libknot14 (= ${binary:Version}), + libknot15 (= ${binary:Version}), ${misc:Depends}, ${python3:Depends}, Section: python diff --git a/distro/pkg/deb/knot.install b/distro/pkg/deb/knot.install index 5c716fc..a31224f 100644 --- a/distro/pkg/deb/knot.install +++ b/distro/pkg/deb/knot.install @@ -1,5 +1,4 @@ debian/cz.nic.knotd.conf usr/share/dbus-1/system.d/ -debian/ufw/knot etc/ufw/applications.d/ etc/knot/knot.conf usr/sbin/kcatalogprint usr/sbin/keymgr diff --git a/distro/pkg/deb/libknot14.install b/distro/pkg/deb/libknot14.install deleted file mode 100644 index f9b9f93..0000000 --- a/distro/pkg/deb/libknot14.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/*/libknot.so.* diff --git a/distro/pkg/deb/libknot14.symbols b/distro/pkg/deb/libknot14.symbols deleted file mode 100644 index 174d517..0000000 --- a/distro/pkg/deb/libknot14.symbols +++ /dev/null @@ -1,277 +0,0 @@ -libknot.so.14 libknot14 #MINVER# -* Build-Depends-Package: libknot-dev - KNOT_DB_LMDB_DUPSORT@Base 3.3.0 - KNOT_DB_LMDB_INTEGERKEY@Base 3.3.0 - KNOT_DB_LMDB_MAPASYNC@Base 3.3.0 - KNOT_DB_LMDB_NOSYNC@Base 3.3.0 - KNOT_DB_LMDB_NOTLS@Base 3.3.0 - KNOT_DB_LMDB_RDONLY@Base 3.3.0 - KNOT_DB_LMDB_WRITEMAP@Base 3.3.0 - KNOT_DUMP_STYLE_DEFAULT@Base 3.3.0 - knot_ctl_accept@Base 3.3.0 - knot_ctl_alloc@Base 3.3.0 - knot_ctl_bind@Base 3.3.0 - knot_ctl_bind2@Base 3.3.6 - knot_ctl_close@Base 3.3.0 - knot_ctl_connect@Base 3.3.0 - knot_ctl_free@Base 3.3.0 - knot_ctl_receive@Base 3.3.0 - knot_ctl_send@Base 3.3.0 - knot_ctl_set_timeout@Base 3.3.0 - knot_ctl_unbind@Base 3.3.0 - knot_db_lmdb_api@Base 3.3.0 - knot_db_lmdb_del_exact@Base 3.3.0 - knot_db_lmdb_get_mapsize@Base 3.3.0 - knot_db_lmdb_get_path@Base 3.3.0 - knot_db_lmdb_get_usage@Base 3.3.0 - knot_db_lmdb_iter_del@Base 3.3.0 - knot_db_lmdb_txn_begin@Base 3.3.0 - knot_db_trie_api@Base 3.3.0 - knot_dname_cmp@Base 3.3.0 - knot_dname_copy@Base 3.3.0 - knot_dname_copy_lower@Base 3.3.0 - knot_dname_free@Base 3.3.0 - knot_dname_from_str@Base 3.3.0 - knot_dname_in_bailiwick@Base 3.3.0 - knot_dname_is_case_equal@Base 3.3.0 - knot_dname_is_equal@Base 3.3.0 - knot_dname_labels@Base 3.3.0 - knot_dname_lf@Base 3.3.0 - knot_dname_matched_labels@Base 3.3.0 - knot_dname_prefixlen@Base 3.3.0 - knot_dname_realsize@Base 3.3.0 - knot_dname_replace_suffix@Base 3.3.0 - knot_dname_size@Base 3.3.0 - knot_dname_store@Base 3.3.0 - knot_dname_to_lower@Base 3.3.0 - knot_dname_to_str@Base 3.3.0 - knot_dname_to_wire@Base 3.3.0 - knot_dname_unpack@Base 3.3.0 - knot_dname_wire_check@Base 3.3.0 - knot_dnssec_alg_names@Base 3.3.0 - knot_edns_add_option@Base 3.3.0 - knot_edns_alignment_size@Base 3.3.0 - knot_edns_chain_parse@Base 3.3.0 - knot_edns_chain_size@Base 3.3.0 - knot_edns_chain_write@Base 3.3.0 - knot_edns_client_subnet_get_addr@Base 3.3.0 - knot_edns_client_subnet_parse@Base 3.3.0 - knot_edns_client_subnet_set_addr@Base 3.3.0 - knot_edns_client_subnet_size@Base 3.3.0 - knot_edns_client_subnet_write@Base 3.3.0 - knot_edns_cookie_client_check@Base 3.3.0 - knot_edns_cookie_client_generate@Base 3.3.0 - knot_edns_cookie_parse@Base 3.3.0 - knot_edns_cookie_server_check@Base 3.3.0 - knot_edns_cookie_server_generate@Base 3.3.0 - knot_edns_cookie_size@Base 3.3.0 - knot_edns_cookie_write@Base 3.3.0 - knot_edns_ede_names@Base 3.3.0 - knot_edns_get_ext_rcode@Base 3.3.0 - knot_edns_get_option@Base 3.3.0 - knot_edns_get_options@Base 3.3.0 - knot_edns_get_version@Base 3.3.0 - knot_edns_init@Base 3.3.0 - knot_edns_keepalive_parse@Base 3.3.0 - knot_edns_keepalive_size@Base 3.3.0 - knot_edns_keepalive_write@Base 3.3.0 - knot_edns_opt_names@Base 3.3.0 - knot_edns_reserve_option@Base 3.3.0 - knot_edns_set_ext_rcode@Base 3.3.0 - knot_edns_set_version@Base 3.3.0 - knot_error_from_libdnssec@Base 3.3.0 - knot_eth_mtu@Base 3.3.0 - knot_eth_name_from_addr@Base 3.3.0 - knot_eth_queues@Base 3.3.0 - knot_eth_rss@Base 3.3.0 - knot_eth_vlans@Base 3.3.0 - knot_eth_xdp_mode@Base 3.3.0 - knot_get_obsolete_rdata_descriptor@Base 3.3.0 - knot_get_rdata_descriptor@Base 3.3.0 - knot_naptr_header_size@Base 3.3.0 - knot_opcode_names@Base 3.3.0 - knot_opt_code_to_string@Base 3.3.0 - knot_pkt_begin@Base 3.3.0 - knot_pkt_clear@Base 3.3.0 - knot_pkt_copy@Base 3.3.0 - knot_pkt_ext_rcode@Base 3.3.0 - knot_pkt_ext_rcode_name@Base 3.3.0 - knot_pkt_free@Base 3.3.0 - knot_pkt_init_response@Base 3.3.0 - knot_pkt_new@Base 3.3.0 - knot_pkt_parse@Base 3.3.0 - knot_pkt_parse_question@Base 3.3.0 - knot_pkt_put_question@Base 3.3.0 - knot_pkt_put_rotate@Base 3.3.0 - knot_pkt_reclaim@Base 3.3.0 - knot_pkt_reserve@Base 3.3.0 - knot_probe_alloc@Base 3.3.0 - knot_probe_consume@Base 3.3.0 - knot_probe_data_set@Base 3.3.0 - knot_probe_fd@Base 3.3.0 - knot_probe_free@Base 3.3.0 - knot_probe_produce@Base 3.3.0 - knot_probe_set_consumer@Base 3.3.0 - knot_probe_set_producer@Base 3.3.0 - knot_probe_tcp_rtt@Base 3.3.0 - knot_quic_cleanup@Base 3.3.0 - knot_quic_client@Base 3.3.0 - knot_quic_conn_get_stream@Base 3.3.0 - knot_quic_conn_local_port@Base 3.3.0 - knot_quic_conn_new_stream@Base 3.3.0 - knot_quic_conn_next_timeout@Base 3.3.3 - knot_quic_conn_pin@Base 3.3.0 - knot_quic_conn_rtt@Base 3.3.0 - knot_quic_conn_stream_free@Base 3.3.0 - knot_quic_creds_cert@Base 3.3.0 - knot_quic_free_creds@Base 3.3.0 - knot_quic_handle@Base 3.3.0 - knot_quic_hanle_expiry@Base 3.3.3 - knot_quic_init_creds@Base 3.3.0 - knot_quic_init_creds_peer@Base 3.3.0 - knot_quic_send@Base 3.3.0 - knot_quic_session_available@Base 3.3.0 - knot_quic_session_load@Base 3.3.0 - knot_quic_session_save@Base 3.3.0 - knot_quic_stream_add_data@Base 3.3.0 - knot_quic_stream_get_process@Base 3.3.0 - knot_quic_table_free@Base 3.3.0 - knot_quic_table_new@Base 3.3.0 - knot_quic_table_rem@Base 3.3.0 - knot_quic_table_sweep@Base 3.3.0 - knot_rcode_names@Base 3.3.0 - knot_rdataset_add@Base 3.3.0 - knot_rdataset_at@Base 3.3.0 - knot_rdataset_clear@Base 3.3.0 - knot_rdataset_copy@Base 3.3.0 - knot_rdataset_eq@Base 3.3.0 - knot_rdataset_intersect@Base 3.3.0 - knot_rdataset_intersect2@Base 3.3.0 - knot_rdataset_member@Base 3.3.0 - knot_rdataset_merge@Base 3.3.0 - knot_rdataset_subset@Base 3.3.0 - knot_rdataset_subtract@Base 3.3.0 - knot_rrclass_from_string@Base 3.3.0 - knot_rrclass_to_string@Base 3.3.0 - knot_rrset_add_rdata@Base 3.3.0 - knot_rrset_clear@Base 3.3.0 - knot_rrset_copy@Base 3.3.0 - knot_rrset_equal@Base 3.3.0 - knot_rrset_free@Base 3.3.0 - knot_rrset_is_nsec3rel@Base 3.3.0 - knot_rrset_new@Base 3.3.0 - knot_rrset_rr_from_wire@Base 3.3.0 - knot_rrset_rr_to_canonical@Base 3.3.0 - knot_rrset_size@Base 3.3.0 - knot_rrset_to_wire_extra@Base 3.3.0 - knot_rrset_txt_dump@Base 3.3.0 - knot_rrset_txt_dump_data@Base 3.3.0 - knot_rrset_txt_dump_edns@Base 3.3.0 - knot_rrset_txt_dump_header@Base 3.3.0 - knot_rrtype_additional_needed@Base 3.3.0 - knot_rrtype_from_string@Base 3.3.0 - knot_rrtype_is_dnssec@Base 3.3.0 - knot_rrtype_is_metatype@Base 3.3.0 - knot_rrtype_should_be_lowercased@Base 3.3.0 - knot_rrtype_to_string@Base 3.3.0 - knot_strerror@Base 3.3.0 - knot_svcb_param_names@Base 3.3.0 - knot_tcp_cleanup@Base 3.3.0 - knot_tcp_inbufs_upd@Base 3.3.0 - knot_tcp_outbufs_ack@Base 3.3.0 - knot_tcp_outbufs_add@Base 3.3.0 - knot_tcp_outbufs_can_send@Base 3.3.0 - knot_tcp_outbufs_usage@Base 3.3.0 - knot_tcp_recv@Base 3.3.0 - knot_tcp_reply_data@Base 3.3.0 - knot_tcp_send@Base 3.3.0 - knot_tcp_sweep@Base 3.3.0 - knot_tcp_table_free@Base 3.3.0 - knot_tcp_table_new@Base 3.3.0 - knot_tsig_add@Base 3.3.0 - knot_tsig_append@Base 3.3.0 - knot_tsig_client_check@Base 3.3.0 - knot_tsig_client_check_next@Base 3.3.0 - knot_tsig_create_rdata@Base 3.3.0 - knot_tsig_key_copy@Base 3.3.0 - knot_tsig_key_deinit@Base 3.3.0 - knot_tsig_key_init@Base 3.3.0 - knot_tsig_key_init_file@Base 3.3.0 - knot_tsig_key_init_str@Base 3.3.0 - knot_tsig_rcode_names@Base 3.3.0 - knot_tsig_rdata_alg@Base 3.3.0 - knot_tsig_rdata_alg_name@Base 3.3.0 - knot_tsig_rdata_error@Base 3.3.0 - knot_tsig_rdata_fudge@Base 3.3.0 - knot_tsig_rdata_is_ok@Base 3.3.0 - knot_tsig_rdata_mac@Base 3.3.0 - knot_tsig_rdata_mac_length@Base 3.3.0 - knot_tsig_rdata_orig_id@Base 3.3.0 - knot_tsig_rdata_other_data@Base 3.3.0 - knot_tsig_rdata_other_data_length@Base 3.3.0 - knot_tsig_rdata_set_fudge@Base 3.3.0 - knot_tsig_rdata_set_mac@Base 3.3.0 - knot_tsig_rdata_set_orig_id@Base 3.3.0 - knot_tsig_rdata_set_other_data@Base 3.3.0 - knot_tsig_rdata_set_time_signed@Base 3.3.0 - knot_tsig_rdata_time_signed@Base 3.3.0 - knot_tsig_rdata_tsig_timers_length@Base 3.3.0 - knot_tsig_rdata_tsig_variables_length@Base 3.3.0 - knot_tsig_server_check@Base 3.3.0 - knot_tsig_sign@Base 3.3.0 - knot_tsig_sign_next@Base 3.3.0 - knot_tsig_wire_maxsize@Base 3.3.0 - knot_tsig_wire_size@Base 3.3.0 - knot_xdp_deinit@Base 3.3.0 - knot_xdp_init@Base 3.3.0 - knot_xdp_recv@Base 3.3.0 - knot_xdp_recv_finish@Base 3.3.0 - knot_xdp_reply_alloc@Base 3.3.0 - knot_xdp_send@Base 3.3.0 - knot_xdp_send_alloc@Base 3.3.0 - knot_xdp_send_finish@Base 3.3.0 - knot_xdp_send_free@Base 3.3.0 - knot_xdp_send_prepare@Base 3.3.0 - knot_xdp_socket_info@Base 3.3.0 - knot_xdp_socket_fd@Base 3.3.0 - yp_addr@Base 3.3.0 - yp_addr_noport@Base 3.3.0 - yp_addr_noport_to_bin@Base 3.3.0 - yp_addr_noport_to_txt@Base 3.3.0 - yp_addr_range_to_bin@Base 3.3.0 - yp_addr_range_to_txt@Base 3.3.0 - yp_addr_to_bin@Base 3.3.0 - yp_addr_to_txt@Base 3.3.0 - yp_base64_to_bin@Base 3.3.0 - yp_base64_to_txt@Base 3.3.0 - yp_bool_to_bin@Base 3.3.0 - yp_bool_to_txt@Base 3.3.0 - yp_deinit@Base 3.3.0 - yp_dname_to_bin@Base 3.3.0 - yp_dname_to_txt@Base 3.3.0 - yp_format_id@Base 3.3.0 - yp_format_key0@Base 3.3.0 - yp_format_key1@Base 3.3.0 - yp_hex_to_bin@Base 3.3.0 - yp_hex_to_txt@Base 3.3.0 - yp_init@Base 3.3.0 - yp_int_to_bin@Base 3.3.0 - yp_int_to_txt@Base 3.3.0 - yp_item_to_bin@Base 3.3.0 - yp_item_to_txt@Base 3.3.0 - yp_option_to_bin@Base 3.3.0 - yp_option_to_txt@Base 3.3.0 - yp_parse@Base 3.3.0 - yp_schema_check_deinit@Base 3.3.0 - yp_schema_check_init@Base 3.3.0 - yp_schema_check_parser@Base 3.3.0 - yp_schema_check_str@Base 3.3.0 - yp_schema_copy@Base 3.3.0 - yp_schema_find@Base 3.3.0 - yp_schema_free@Base 3.3.0 - yp_schema_merge@Base 3.3.0 - yp_schema_purge_dynamic@Base 3.3.0 - yp_set_input_file@Base 3.3.0 - yp_set_input_string@Base 3.3.0 - yp_str_to_bin@Base 3.3.0 - yp_str_to_txt@Base 3.3.0 diff --git a/distro/pkg/deb/libknot15.install b/distro/pkg/deb/libknot15.install new file mode 100644 index 0000000..f9b9f93 --- /dev/null +++ b/distro/pkg/deb/libknot15.install @@ -0,0 +1 @@ +usr/lib/*/libknot.so.* diff --git a/distro/pkg/deb/libknot15.symbols b/distro/pkg/deb/libknot15.symbols new file mode 100644 index 0000000..77dd5b0 --- /dev/null +++ b/distro/pkg/deb/libknot15.symbols @@ -0,0 +1,290 @@ +libknot.so.15 libknot15 #MINVER# +* Build-Depends-Package: libknot-dev + KNOT_DB_LMDB_DUPSORT@Base 3.4.0 + KNOT_DB_LMDB_INTEGERKEY@Base 3.4.0 + KNOT_DB_LMDB_MAPASYNC@Base 3.4.0 + KNOT_DB_LMDB_NOSYNC@Base 3.4.0 + KNOT_DB_LMDB_NOTLS@Base 3.4.0 + KNOT_DB_LMDB_RDONLY@Base 3.4.0 + KNOT_DB_LMDB_WRITEMAP@Base 3.4.0 + KNOT_DUMP_STYLE_DEFAULT@Base 3.4.0 + knot_creds_cert@Base 3.4.0 + knot_creds_free@Base 3.4.0 + knot_creds_init@Base 3.4.0 + knot_creds_init_peer@Base 3.4.0 + knot_creds_update@Base 3.4.0 + knot_ctl_accept@Base 3.4.0 + knot_ctl_alloc@Base 3.4.0 + knot_ctl_bind@Base 3.4.0 + knot_ctl_clone@Base 3.4.0 + knot_ctl_close@Base 3.4.0 + knot_ctl_connect@Base 3.4.0 + knot_ctl_free@Base 3.4.0 + knot_ctl_receive@Base 3.4.0 + knot_ctl_send@Base 3.4.0 + knot_ctl_set_timeout@Base 3.4.0 + knot_ctl_unbind@Base 3.4.0 + knot_db_lmdb_api@Base 3.4.0 + knot_db_lmdb_del_exact@Base 3.4.0 + knot_db_lmdb_get_mapsize@Base 3.4.0 + knot_db_lmdb_get_path@Base 3.4.0 + knot_db_lmdb_get_usage@Base 3.4.0 + knot_db_lmdb_iter_del@Base 3.4.0 + knot_db_lmdb_txn_begin@Base 3.4.0 + knot_db_trie_api@Base 3.4.0 + knot_dname_cmp@Base 3.4.0 + knot_dname_copy@Base 3.4.0 + knot_dname_copy_lower@Base 3.4.0 + knot_dname_free@Base 3.4.0 + knot_dname_from_str@Base 3.4.0 + knot_dname_in_bailiwick@Base 3.4.0 + knot_dname_is_case_equal@Base 3.4.0 + knot_dname_is_equal@Base 3.4.0 + knot_dname_labels@Base 3.4.0 + knot_dname_lf@Base 3.4.0 + knot_dname_matched_labels@Base 3.4.0 + knot_dname_prefixlen@Base 3.4.0 + knot_dname_realsize@Base 3.4.0 + knot_dname_replace_suffix@Base 3.4.0 + knot_dname_size@Base 3.4.0 + knot_dname_store@Base 3.4.0 + knot_dname_to_lower@Base 3.4.0 + knot_dname_to_str@Base 3.4.0 + knot_dname_to_wire@Base 3.4.0 + knot_dname_unpack@Base 3.4.0 + knot_dname_wire_check@Base 3.4.0 + knot_dnssec_alg_names@Base 3.4.0 + knot_edns_add_option@Base 3.4.0 + knot_edns_alignment_size@Base 3.4.0 + knot_edns_chain_parse@Base 3.4.0 + knot_edns_chain_size@Base 3.4.0 + knot_edns_chain_write@Base 3.4.0 + knot_edns_client_subnet_get_addr@Base 3.4.0 + knot_edns_client_subnet_parse@Base 3.4.0 + knot_edns_client_subnet_set_addr@Base 3.4.0 + knot_edns_client_subnet_size@Base 3.4.0 + knot_edns_client_subnet_write@Base 3.4.0 + knot_edns_cookie_client_check@Base 3.4.0 + knot_edns_cookie_client_generate@Base 3.4.0 + knot_edns_cookie_parse@Base 3.4.0 + knot_edns_cookie_server_check@Base 3.4.0 + knot_edns_cookie_server_generate@Base 3.4.0 + knot_edns_cookie_size@Base 3.4.0 + knot_edns_cookie_write@Base 3.4.0 + knot_edns_ede_names@Base 3.4.0 + knot_edns_get_ext_rcode@Base 3.4.0 + knot_edns_get_option@Base 3.4.0 + knot_edns_get_options@Base 3.4.0 + knot_edns_get_version@Base 3.4.0 + knot_edns_init@Base 3.4.0 + knot_edns_keepalive_parse@Base 3.4.0 + knot_edns_keepalive_size@Base 3.4.0 + knot_edns_keepalive_write@Base 3.4.0 + knot_edns_opt_names@Base 3.4.0 + knot_edns_reserve_option@Base 3.4.0 + knot_edns_set_ext_rcode@Base 3.4.0 + knot_edns_set_version@Base 3.4.0 + knot_error_from_libdnssec@Base 3.4.0 + knot_eth_mtu@Base 3.4.0 + knot_eth_name_from_addr@Base 3.4.0 + knot_eth_queues@Base 3.4.0 + knot_eth_rss@Base 3.4.0 + knot_eth_vlans@Base 3.4.0 + knot_eth_xdp_mode@Base 3.4.0 + knot_get_obsolete_rdata_descriptor@Base 3.4.0 + knot_get_rdata_descriptor@Base 3.4.0 + knot_naptr_header_size@Base 3.4.0 + knot_opcode_names@Base 3.4.0 + knot_opt_code_to_string@Base 3.4.0 + knot_pkt_begin@Base 3.4.0 + knot_pkt_clear@Base 3.4.0 + knot_pkt_copy@Base 3.4.0 + knot_pkt_ext_rcode@Base 3.4.0 + knot_pkt_ext_rcode_name@Base 3.4.0 + knot_pkt_free@Base 3.4.0 + knot_pkt_init_response@Base 3.4.0 + knot_pkt_new@Base 3.4.0 + knot_pkt_parse@Base 3.4.0 + knot_pkt_parse_question@Base 3.4.0 + knot_pkt_put_question@Base 3.4.0 + knot_pkt_put_rotate@Base 3.4.0 + knot_pkt_reclaim@Base 3.4.0 + knot_pkt_reserve@Base 3.4.0 + knot_probe_alloc@Base 3.4.0 + knot_probe_consume@Base 3.4.0 + knot_probe_data_set@Base 3.4.0 + knot_probe_fd@Base 3.4.0 + knot_probe_free@Base 3.4.0 + knot_probe_produce@Base 3.4.0 + knot_probe_set_consumer@Base 3.4.0 + knot_probe_set_producer@Base 3.4.0 + knot_probe_tcp_rtt@Base 3.4.0 + knot_quic_cleanup@Base 3.4.0 + knot_quic_client@Base 3.4.0 + knot_quic_conn_block@Base 3.4.0 + knot_quic_conn_get_stream@Base 3.4.0 + knot_quic_conn_local_port@Base 3.4.0 + knot_quic_conn_new_stream@Base 3.4.0 + knot_quic_conn_next_timeout@Base 3.4.0 + knot_quic_conn_rtt@Base 3.4.0 + knot_quic_conn_stream_free@Base 3.4.0 + knot_quic_handle@Base 3.4.0 + knot_quic_hanle_expiry@Base 3.4.0 + knot_quic_send@Base 3.4.0 + knot_quic_session_available@Base 3.4.0 + knot_quic_session_load@Base 3.4.0 + knot_quic_session_save@Base 3.4.0 + knot_quic_stream_add_data@Base 3.4.0 + knot_quic_stream_get_process@Base 3.4.0 + knot_quic_table_free@Base 3.4.0 + knot_quic_table_new@Base 3.4.0 + knot_quic_table_rem@Base 3.4.0 + knot_quic_table_sweep@Base 3.4.0 + knot_rcode_names@Base 3.4.0 + knot_rdataset_add@Base 3.4.0 + knot_rdataset_at@Base 3.4.0 + knot_rdataset_clear@Base 3.4.0 + knot_rdataset_copy@Base 3.4.0 + knot_rdataset_eq@Base 3.4.0 + knot_rdataset_intersect@Base 3.4.0 + knot_rdataset_intersect2@Base 3.4.0 + knot_rdataset_member@Base 3.4.0 + knot_rdataset_merge@Base 3.4.0 + knot_rdataset_subset@Base 3.4.0 + knot_rdataset_subtract@Base 3.4.0 + knot_rrclass_from_string@Base 3.4.0 + knot_rrclass_to_string@Base 3.4.0 + knot_rrset_add_rdata@Base 3.4.0 + knot_rrset_clear@Base 3.4.0 + knot_rrset_copy@Base 3.4.0 + knot_rrset_equal@Base 3.4.0 + knot_rrset_free@Base 3.4.0 + knot_rrset_is_nsec3rel@Base 3.4.0 + knot_rrset_new@Base 3.4.0 + knot_rrset_rr_from_wire@Base 3.4.0 + knot_rrset_rr_to_canonical@Base 3.4.0 + knot_rrset_size@Base 3.4.0 + knot_rrset_to_wire_extra@Base 3.4.0 + knot_rrset_txt_dump@Base 3.4.0 + knot_rrset_txt_dump_data@Base 3.4.0 + knot_rrset_txt_dump_edns@Base 3.4.0 + knot_rrset_txt_dump_header@Base 3.4.0 + knot_rrtype_additional_needed@Base 3.4.0 + knot_rrtype_from_string@Base 3.4.0 + knot_rrtype_is_dnssec@Base 3.4.0 + knot_rrtype_is_metatype@Base 3.4.0 + knot_rrtype_should_be_lowercased@Base 3.4.0 + knot_rrtype_to_string@Base 3.4.0 + knot_strerror@Base 3.4.0 + knot_svcb_param_names@Base 3.4.0 + knot_tcp_cleanup@Base 3.4.0 + knot_tcp_inbufs_upd@Base 3.4.0 + knot_tcp_outbufs_ack@Base 3.4.0 + knot_tcp_outbufs_add@Base 3.4.0 + knot_tcp_outbufs_can_send@Base 3.4.0 + knot_tcp_outbufs_usage@Base 3.4.0 + knot_tcp_recv@Base 3.4.0 + knot_tcp_reply_data@Base 3.4.0 + knot_tcp_send@Base 3.4.0 + knot_tcp_sweep@Base 3.4.0 + knot_tcp_table_free@Base 3.4.0 + knot_tcp_table_new@Base 3.4.0 + knot_tls_conn_block@Base 3.4.0 + knot_tls_conn_del@Base 3.4.0 + knot_tls_conn_new@Base 3.4.0 + knot_tls_ctx_free@Base 3.4.0 + knot_tls_ctx_new@Base 3.4.0 + knot_tls_handshake@Base 3.4.0 + knot_tls_pin@Base 3.4.0 + knot_tls_pin_check@Base 3.4.0 + knot_tls_recv_dns@Base 3.4.0 + knot_tls_send_dns@Base 3.4.0 + knot_tls_session@Base 3.4.0 + knot_tsig_add@Base 3.4.0 + knot_tsig_append@Base 3.4.0 + knot_tsig_client_check@Base 3.4.0 + knot_tsig_client_check_next@Base 3.4.0 + knot_tsig_create_rdata@Base 3.4.0 + knot_tsig_key_copy@Base 3.4.0 + knot_tsig_key_deinit@Base 3.4.0 + knot_tsig_key_init@Base 3.4.0 + knot_tsig_key_init_file@Base 3.4.0 + knot_tsig_key_init_str@Base 3.4.0 + knot_tsig_rcode_names@Base 3.4.0 + knot_tsig_rdata_alg@Base 3.4.0 + knot_tsig_rdata_alg_name@Base 3.4.0 + knot_tsig_rdata_error@Base 3.4.0 + knot_tsig_rdata_fudge@Base 3.4.0 + knot_tsig_rdata_is_ok@Base 3.4.0 + knot_tsig_rdata_mac@Base 3.4.0 + knot_tsig_rdata_mac_length@Base 3.4.0 + knot_tsig_rdata_orig_id@Base 3.4.0 + knot_tsig_rdata_other_data@Base 3.4.0 + knot_tsig_rdata_other_data_length@Base 3.4.0 + knot_tsig_rdata_set_fudge@Base 3.4.0 + knot_tsig_rdata_set_mac@Base 3.4.0 + knot_tsig_rdata_set_orig_id@Base 3.4.0 + knot_tsig_rdata_set_other_data@Base 3.4.0 + knot_tsig_rdata_set_time_signed@Base 3.4.0 + knot_tsig_rdata_time_signed@Base 3.4.0 + knot_tsig_rdata_tsig_timers_length@Base 3.4.0 + knot_tsig_rdata_tsig_variables_length@Base 3.4.0 + knot_tsig_server_check@Base 3.4.0 + knot_tsig_sign@Base 3.4.0 + knot_tsig_sign_next@Base 3.4.0 + knot_tsig_wire_maxsize@Base 3.4.0 + knot_tsig_wire_size@Base 3.4.0 + knot_xdp_deinit@Base 3.4.0 + knot_xdp_init@Base 3.4.0 + knot_xdp_recv@Base 3.4.0 + knot_xdp_recv_finish@Base 3.4.0 + knot_xdp_reply_alloc@Base 3.4.0 + knot_xdp_send@Base 3.4.0 + knot_xdp_send_alloc@Base 3.4.0 + knot_xdp_send_finish@Base 3.4.0 + knot_xdp_send_free@Base 3.4.0 + knot_xdp_send_prepare@Base 3.4.0 + knot_xdp_socket_info@Base 3.4.0 + knot_xdp_socket_stats@Base 3.4.0 + knot_xdp_socket_fd@Base 3.4.0 + yp_addr@Base 3.4.0 + yp_addr_noport@Base 3.4.0 + yp_addr_noport_to_bin@Base 3.4.0 + yp_addr_noport_to_txt@Base 3.4.0 + yp_addr_range_to_bin@Base 3.4.0 + yp_addr_range_to_txt@Base 3.4.0 + yp_addr_to_bin@Base 3.4.0 + yp_addr_to_txt@Base 3.4.0 + yp_base64_to_bin@Base 3.4.0 + yp_base64_to_txt@Base 3.4.0 + yp_bool_to_bin@Base 3.4.0 + yp_bool_to_txt@Base 3.4.0 + yp_deinit@Base 3.4.0 + yp_dname_to_bin@Base 3.4.0 + yp_dname_to_txt@Base 3.4.0 + yp_format_id@Base 3.4.0 + yp_format_key0@Base 3.4.0 + yp_format_key1@Base 3.4.0 + yp_hex_to_bin@Base 3.4.0 + yp_hex_to_txt@Base 3.4.0 + yp_init@Base 3.4.0 + yp_int_to_bin@Base 3.4.0 + yp_int_to_txt@Base 3.4.0 + yp_item_to_bin@Base 3.4.0 + yp_item_to_txt@Base 3.4.0 + yp_option_to_bin@Base 3.4.0 + yp_option_to_txt@Base 3.4.0 + yp_parse@Base 3.4.0 + yp_schema_check_deinit@Base 3.4.0 + yp_schema_check_init@Base 3.4.0 + yp_schema_check_parser@Base 3.4.0 + yp_schema_check_str@Base 3.4.0 + yp_schema_copy@Base 3.4.0 + yp_schema_find@Base 3.4.0 + yp_schema_free@Base 3.4.0 + yp_schema_merge@Base 3.4.0 + yp_schema_purge_dynamic@Base 3.4.0 + yp_set_input_file@Base 3.4.0 + yp_set_input_string@Base 3.4.0 + yp_str_to_bin@Base 3.4.0 + yp_str_to_txt@Base 3.4.0 diff --git a/distro/pkg/deb/rules b/distro/pkg/deb/rules index 82cc34b..c5c81d0 100755 --- a/distro/pkg/deb/rules +++ b/distro/pkg/deb/rules @@ -36,11 +36,9 @@ BASE_VERSION := $(shell echo $(DEB_VERSION) | sed 's/^\([^.]\+\.[^.]\+\).*/\1/') # invocation due to bug in dh-python's plugin_pyproject.py wheel unpack export PYBUILD_SYSTEM = distutils - %: dh $@ \ - --exclude=.la --exclude=example.com.zone \ - --with python3 + --with python3 override_dh_auto_configure: dh_auto_configure -- \ @@ -95,7 +93,7 @@ ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) endif override_dh_missing: - dh_missing --fail-missing + dh_missing --exclude=.la --fail-missing override_dh_installchangelogs: dh_installchangelogs NEWS diff --git a/distro/pkg/deb/ufw/knot b/distro/pkg/deb/ufw/knot deleted file mode 100644 index ee36916..0000000 --- a/distro/pkg/deb/ufw/knot +++ /dev/null @@ -1,4 +0,0 @@ -[Knot] -title=Internet Domain Name Server -description=The Knot DNS implements an Internet domain name server. -ports=53 diff --git a/distro/pkg/el-7/01-revert-AC_PROG_CC.patch b/distro/pkg/el-7/01-revert-AC_PROG_CC.patch deleted file mode 100644 index fb49c00..0000000 --- a/distro/pkg/el-7/01-revert-AC_PROG_CC.patch +++ /dev/null @@ -1,18 +0,0 @@ -From: Daniel Salzman -Date: Sun, 20 Feb 2022 20:38:35 +0100 -Subject: [PATCH] Revert "configure: upgrade from AC_PROG_CC_C99 to AC_PROG_CC" - -diff --git a/configure.ac b/configure.ac -index 6506197ed..c7df7f815 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -38,7 +38,8 @@ release_date=$($SED -n 's/^Knot DNS .* (\(.*\))/\1/p;q;' ${srcdir}/NEWS) - AC_SUBST([RELEASE_DATE], $release_date) - - # Set compiler compatibility flags --AC_PROG_CC -+AC_PROG_CC_C99 # AC_PROG_CC not supported by CentOS 7 -+AM_PROG_CC_C_O # Needed by CentOS 7 - AC_PROG_CPP_WERROR - - # Set default CFLAGS diff --git a/distro/pkg/el-7/02-fix-compilation-by-using-SHA-1.patch b/distro/pkg/el-7/02-fix-compilation-by-using-SHA-1.patch deleted file mode 100644 index cbc5aa2..0000000 --- a/distro/pkg/el-7/02-fix-compilation-by-using-SHA-1.patch +++ /dev/null @@ -1,67 +0,0 @@ -From: Daniel Salzman -Date: Mon, 20 Mar 2023 14:57:54 +0100 -Subject: [PATCH] distro/el-7: fix compilation by using SHA-1 for PIN computation - -diff --git a/src/libknot/quic/quic.c b/src/libknot/quic/quic.c -index 5610865f6..555c495d9 100644 ---- a/src/libknot/quic/quic.c -+++ b/src/libknot/quic/quic.c -@@ -460,7 +460,7 @@ void knot_quic_conn_pin(knot_quic_conn_t *conn, uint8_t *pin, size_t *pin_size, - goto error; - } - -- ret = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, pin, pin_size); -+ ret = gnutls_x509_crt_get_key_id(cert, 0, pin, pin_size); - if (ret != GNUTLS_E_SUCCESS) { - gnutls_x509_crt_deinit(cert); - goto error; -diff --git a/src/utils/common/tls.c b/src/utils/common/tls.c -index 245dd3f96..6a2e7a986 100644 ---- a/src/utils/common/tls.c -+++ b/src/utils/common/tls.c -@@ -328,7 +328,7 @@ static int check_certificates(gnutls_session_t session, const list_t *pins) - - uint8_t cert_pin[CERT_PIN_LEN] = { 0 }; - size_t cert_pin_size = sizeof(cert_pin); -- ret = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, -+ ret = gnutls_x509_crt_get_key_id(cert, 0, - cert_pin, &cert_pin_size); - if (ret != 0) { - gnutls_x509_crt_deinit(cert); -@@ -336,18 +336,18 @@ static int check_certificates(gnutls_session_t session, const list_t *pins) - } - - // Check if correspond to a specified PIN. -- bool match = check_pin(cert_pin, sizeof(cert_pin), pins); -+ bool match = check_pin(cert_pin, cert_pin_size, pins); - if (match) { - matches++; - } - - uint8_t *txt_pin; -- ret = knot_base64_encode_alloc(cert_pin, sizeof(cert_pin), &txt_pin); -+ ret = knot_base64_encode_alloc(cert_pin, cert_pin_size, &txt_pin); - if (ret < 0) { - gnutls_x509_crt_deinit(cert); - return ret; - } -- DBG(" SHA-256 PIN: %.*s%s", ret, txt_pin, match ? ", MATCH" : ""); -+ DBG(" SHA-1 PIN: %.*s%s", ret, txt_pin, match ? ", MATCH" : ""); - free(txt_pin); - - gnutls_x509_crt_deinit(cert); -diff --git a/src/utils/kdig/kdig_params.c b/src/utils/kdig/kdig_params.c -index 359b8b596..8fd33b011 100644 ---- a/src/utils/kdig/kdig_params.c -+++ b/src/utils/kdig/kdig_params.c -@@ -707,8 +707,8 @@ static int opt_tls_pin(const char *arg, void *query) - if (ret < 0) { - ERR("invalid +tls-pin=%s", arg); - return ret; -- } else if (ret != CERT_PIN_LEN) { // Check for 256-bit value. -- ERR("invalid sha256 hash length +tls-pin=%s", arg); -+ } else if (ret != 20) { // Check for 256-bit value. -+ ERR("invalid sha1 hash length +tls-pin=%s", arg); - return KNOT_EINVAL; - } - diff --git a/distro/pkg/el-7/03-doc-don-t-try-to-import-sphinx_panels.patch b/distro/pkg/el-7/03-doc-don-t-try-to-import-sphinx_panels.patch deleted file mode 100644 index 8ef7e7e..0000000 --- a/distro/pkg/el-7/03-doc-don-t-try-to-import-sphinx_panels.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c05abb0401d3343b96ced4a6cdd724ee04adfe1b Mon Sep 17 00:00:00 2001 -From: Daniel Salzman -Date: Mon, 21 Aug 2023 16:54:46 +0200 -Subject: [PATCH] doc: don't try to import sphinx_panels on CentOS 7 - - - 1 file changed, 3 deletions(-) - -diff --git a/doc/conf.py b/doc/conf.py -index fc2e94d96..515241051 100644 ---- a/doc/conf.py -+++ b/doc/conf.py -@@ -27,9 +27,6 @@ sys.path.insert(0, os.path.abspath('ext')) - - # Add any Sphinx extension module names here, as strings. They can be extensions - # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. --import importlib.util --if importlib.util.find_spec("sphinx_panels"): -- extensions = [ 'sphinx_panels' ] - - # Add any paths that contain templates here, relative to this directory. - templates_path = ['_templates'] --- -2.25.1 - diff --git a/distro/pkg/el-7/04-revert-don-t-share-PKCS-11-private-keys.patch b/distro/pkg/el-7/04-revert-don-t-share-PKCS-11-private-keys.patch deleted file mode 100644 index d360433..0000000 --- a/distro/pkg/el-7/04-revert-don-t-share-PKCS-11-private-keys.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 1bad8f831a9fd506516549ac7461f97c689a0c46 Mon Sep 17 00:00:00 2001 -From: Daniel Salzman -Date: Mon, 11 Dec 2023 17:08:23 +0100 -Subject: [PATCH] Revert "zone-sign: don't share PKCS 11 private keys by - multiple signing threads" - -This reverts commit 7d63e8e0825e03b8e0608e87b86968c452755c93. ---- - src/knot/dnssec/zone-keys.c | 38 +++---------------------------------- - src/libdnssec/key.h | 4 ++-- - src/libdnssec/key/key.c | 24 +---------------------- - tests/libdnssec/test_key.c | 4 ++-- - 4 files changed, 8 insertions(+), 62 deletions(-) - -diff --git a/src/knot/dnssec/zone-keys.c b/src/knot/dnssec/zone-keys.c -index cd6bf0bb3..d5cccc759 100644 ---- a/src/knot/dnssec/zone-keys.c -+++ b/src/knot/dnssec/zone-keys.c -@@ -642,21 +642,6 @@ int zone_key_calculate_ds(zone_key_t *for_key, dnssec_key_digest_t digesttype, - return ret; - } - --static int dup_zone_key(const zone_key_t *src, zone_key_t *dst) --{ -- assert(src); -- assert(dst); -- -- *dst = *src; -- -- dst->key = dnssec_key_dup(src->key); -- if (dst->key == NULL) { -- return KNOT_ENOMEM; -- } -- -- return KNOT_EOK; --} -- - zone_sign_ctx_t *zone_sign_ctx(const zone_keyset_t *keyset, const kdnssec_ctx_t *dnssec_ctx) - { - zone_sign_ctx_t *ctx = calloc(1, sizeof(*ctx) + keyset->count * sizeof(*ctx->sign_ctxs)); -@@ -665,24 +650,11 @@ zone_sign_ctx_t *zone_sign_ctx(const zone_keyset_t *keyset, const kdnssec_ctx_t - } - - ctx->sign_ctxs = (dnssec_sign_ctx_t **)(ctx + 1); -- -- ctx->keys = calloc(keyset->count, sizeof(*ctx->keys)); -- if (ctx->keys == NULL) { -- zone_sign_ctx_free(ctx); -- return NULL; -- } - ctx->count = keyset->count; -- -+ ctx->keys = keyset->keys; - ctx->dnssec_ctx = dnssec_ctx; - for (size_t i = 0; i < ctx->count; i++) { -- // Clone the key to avoid thread contention on the key mutex. -- int ret = dup_zone_key(&keyset->keys[i], &ctx->keys[i]); -- if (ret != KNOT_EOK) { -- zone_sign_ctx_free(ctx); -- return NULL; -- } -- -- ret = dnssec_sign_new(&ctx->sign_ctxs[i], ctx->keys[i].key); -+ int ret = dnssec_sign_new(&ctx->sign_ctxs[i], ctx->keys[i].key); - if (ret != DNSSEC_EOK) { - zone_sign_ctx_free(ctx); - return NULL; -@@ -719,12 +691,8 @@ void zone_sign_ctx_free(zone_sign_ctx_t *ctx) - { - if (ctx != NULL) { - for (size_t i = 0; i < ctx->count; i++) { -- if (ctx->keys != NULL) { -- dnssec_key_free(ctx->keys[i].key); -- } - dnssec_sign_free(ctx->sign_ctxs[i]); - } -- free(ctx->keys); - free(ctx); - } - } -diff --git a/src/libdnssec/key.h b/src/libdnssec/key.h -index aa8002b4a..2a69d377f 100644 ---- a/src/libdnssec/key.h -+++ b/src/libdnssec/key.h -@@ -1,4 +1,4 @@ --/* Copyright (C) 2023 CZ.NIC, z.s.p.o. -+/* Copyright (C) 2022 CZ.NIC, z.s.p.o. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by -@@ -134,7 +134,7 @@ void dnssec_key_free(dnssec_key_t *key); - /*! - * Create a copy of a DNSSEC key. - * -- * Public key isn't duplicated. -+ * Only a public part of the key is copied. - */ - dnssec_key_t *dnssec_key_dup(const dnssec_key_t *key); - -diff --git a/src/libdnssec/key/key.c b/src/libdnssec/key/key.c -index 4574bbefb..f36316712 100644 ---- a/src/libdnssec/key/key.c -+++ b/src/libdnssec/key/key.c -@@ -1,4 +1,4 @@ --/* Copyright (C) 2023 CZ.NIC, z.s.p.o. -+/* Copyright (C) 2019 CZ.NIC, z.s.p.o. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by -@@ -141,28 +141,6 @@ dnssec_key_t *dnssec_key_dup(const dnssec_key_t *key) - return NULL; - } - -- if (key->private_key != NULL) { -- gnutls_privkey_init(&dup->private_key); -- -- gnutls_privkey_type_t type = gnutls_privkey_get_type(key->private_key); -- if (type == GNUTLS_PRIVKEY_PKCS11) { --#ifdef ENABLE_PKCS11 -- gnutls_pkcs11_privkey_t tmp; -- gnutls_privkey_export_pkcs11(key->private_key, &tmp); -- gnutls_privkey_import_pkcs11(dup->private_key, tmp, -- GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE); --#else -- assert(0); --#endif // ENABLE_PKCS11 -- } else { -- assert(type == GNUTLS_PRIVKEY_X509); -- gnutls_x509_privkey_t tmp; -- gnutls_privkey_export_x509(key->private_key, &tmp); -- gnutls_privkey_import_x509(dup->private_key, tmp, -- GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE); -- } -- } -- - return dup; - } - -diff --git a/tests/libdnssec/test_key.c b/tests/libdnssec/test_key.c -index c3643f08c..cd0aaee0e 100644 ---- a/tests/libdnssec/test_key.c -+++ b/tests/libdnssec/test_key.c -@@ -1,4 +1,4 @@ --/* Copyright (C) 2023 CZ.NIC, z.s.p.o. -+/* Copyright (C) 2021 CZ.NIC, z.s.p.o. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by -@@ -148,7 +148,7 @@ static void test_private_key(const key_parameters_t *params) - - check_key_tag(copy, params); - check_key_size(copy, params); -- check_usage(copy, true, true); -+ check_usage(copy, true, false); - - dnssec_key_free(copy); - dnssec_key_free(key); --- -2.34.1 - diff --git a/distro/pkg/el-7/05-revert-mod-dnstap-TCP-sink.patch b/distro/pkg/el-7/05-revert-mod-dnstap-TCP-sink.patch deleted file mode 100644 index dae0fac..0000000 --- a/distro/pkg/el-7/05-revert-mod-dnstap-TCP-sink.patch +++ /dev/null @@ -1,160 +0,0 @@ -From d236d2b7fcd5fa607f7bfd38044eb6f510fac7ce Mon Sep 17 00:00:00 2001 -From: Daniel Salzman -Date: Wed, 12 Jun 2024 11:18:31 +0200 -Subject: [PATCH] Revert "mod-dnstap: add sink for TCP connection" - -This reverts commit 2ffd7dfa58ddcd1b860f0c9980fd082c3852d3e6. ---- - src/knot/modules/dnstap/dnstap.c | 74 +++++------------------------- - src/knot/modules/dnstap/dnstap.rst | 9 ++-- - 2 files changed, 15 insertions(+), 68 deletions(-) - -diff --git a/src/knot/modules/dnstap/dnstap.c b/src/knot/modules/dnstap/dnstap.c -index 612e48869..c8c82eaa4 100644 ---- a/src/knot/modules/dnstap/dnstap.c -+++ b/src/knot/modules/dnstap/dnstap.c -@@ -1,4 +1,4 @@ --/* Copyright (C) 2024 CZ.NIC, z.s.p.o. -+/* Copyright (C) 2023 CZ.NIC, z.s.p.o. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by -@@ -185,33 +185,6 @@ finish: - return writer; - } - --static struct fstrm_writer* dnstap_tcp_writer(const char *address, const char *port) --{ -- struct fstrm_tcp_writer_options *opt = NULL; -- struct fstrm_writer_options *wopt = NULL; -- struct fstrm_writer *writer = NULL; -- -- opt = fstrm_tcp_writer_options_init(); -- if (opt == NULL) { -- goto finish; -- } -- -- fstrm_tcp_writer_options_set_socket_address(opt, address); -- fstrm_tcp_writer_options_set_socket_port(opt, port); -- -- wopt = fstrm_writer_options_init(); -- if (wopt == NULL) { -- goto finish; -- } -- fstrm_writer_options_add_content_type(wopt, DNSTAP_CONTENT_TYPE, -- strlen(DNSTAP_CONTENT_TYPE)); -- writer = fstrm_tcp_writer_init(opt, wopt); --finish: -- fstrm_tcp_writer_options_destroy(&opt); -- fstrm_writer_options_destroy(&wopt); -- return writer; --} -- - /*! \brief Create a basic file writer sink. */ - static struct fstrm_writer* dnstap_file_writer(const char *path) - { -@@ -240,42 +213,17 @@ finish: - } - - /*! \brief Create a log sink according to the path string. */ --static struct fstrm_writer* dnstap_writer(knotd_mod_t *mod, const char *path) -+static struct fstrm_writer* dnstap_writer(const char *path) - { -- const char *unix_prefix = "unix:"; -- const size_t unix_prefix_len = strlen(unix_prefix); -- -- const char *tcp_prefix = "tcp:"; -- const size_t tcp_prefix_len = strlen(tcp_prefix); -- -- const size_t path_len = strlen(path); -+ const char *prefix = "unix:"; -+ const size_t prefix_len = strlen(prefix); - - /* UNIX socket prefix. */ -- if (path_len > unix_prefix_len && -- strncmp(path, unix_prefix, unix_prefix_len) == 0) { -- knotd_mod_log(mod, LOG_DEBUG, "using sink UNIX socket '%s'", path); -- return dnstap_unix_writer(path + unix_prefix_len); -- /* TCP socket prefix. */ -- } else if (path_len > tcp_prefix_len && -- strncmp(path, tcp_prefix, tcp_prefix_len) == 0) { -- char addr[INET6_ADDRSTRLEN] = { 0 }; -- const char *delimiter = strchr(path + tcp_prefix_len, '@'); -- if (delimiter == NULL) { -- return NULL; -- } -- size_t addr_len = delimiter - path - tcp_prefix_len; -- if (addr_len >= sizeof(addr)) { -- return NULL; -- } -- memcpy(addr, path + tcp_prefix_len, addr_len); -- knotd_mod_log(mod, LOG_DEBUG, "using sink TCP address '%s' port '%s'", -- addr, delimiter + 1); -- return dnstap_tcp_writer(addr, delimiter + 1); -- /* File path. */ -- } else { -- knotd_mod_log(mod, LOG_DEBUG, "using sink file '%s'", path); -- return dnstap_file_writer(path); -+ if (strlen(path) > prefix_len && strncmp(path, prefix, prefix_len) == 0) { -+ return dnstap_unix_writer(path + prefix_len); - } -+ -+ return dnstap_file_writer(path); - } - - int dnstap_load(knotd_mod_t *mod) -@@ -325,7 +273,7 @@ int dnstap_load(knotd_mod_t *mod) - const bool log_responses = conf.single.boolean; - - /* Initialize the writer and the options. */ -- struct fstrm_writer *writer = dnstap_writer(mod, sink); -+ struct fstrm_writer *writer = dnstap_writer(sink); - if (writer == NULL) { - goto fail; - } -@@ -359,13 +307,13 @@ int dnstap_load(knotd_mod_t *mod) - - return KNOT_EOK; - fail: -- knotd_mod_log(mod, LOG_ERR, "failed to initialize sink '%s'", sink); -+ knotd_mod_log(mod, LOG_ERR, "failed to init sink '%s'", sink); - - free(ctx->identity); - free(ctx->version); - free(ctx); - -- return KNOT_EINVAL; -+ return KNOT_ENOMEM; - } - - void dnstap_unload(knotd_mod_t *mod) -diff --git a/src/knot/modules/dnstap/dnstap.rst b/src/knot/modules/dnstap/dnstap.rst -index 05eac09ab..358977da0 100644 ---- a/src/knot/modules/dnstap/dnstap.rst -+++ b/src/knot/modules/dnstap/dnstap.rst -@@ -11,7 +11,7 @@ Example - ------- - - The configuration comprises only a :ref:`mod-dnstap_sink` path parameter, --which can be either a file, a UNIX socket, or a TCP address:: -+which can be either a file or a UNIX socket:: - - mod-dnstap: - - id: capture_all -@@ -60,10 +60,9 @@ A module identifier. - sink - .... - --A sink path, which can be either a file, a UNIX socket when prefixed with --``unix:``, or a TCP `address@port` when prefixed with ``tcp:``. The file may --be specified as an absolute path or a path relative to --the :doc:`knotd` startup directory. -+A sink path, which can be either a file or a UNIX socket when prefixed with -+``unix:``. The file may be specified as an absolute path or a path relative -+to the :doc:`knotd` startup directory. - - *Required* - --- -2.34.1 - diff --git a/distro/pkg/el-7/knot.service b/distro/pkg/el-7/knot.service deleted file mode 100644 index a872929..0000000 --- a/distro/pkg/el-7/knot.service +++ /dev/null @@ -1,25 +0,0 @@ -[Unit] -Description=Knot DNS server -Wants=network-online.target -After=network-online.target -Documentation=man:knotd(8) man:knot.conf(5) man:knotc(8) - -[Service] -Type=notify -User=knot -Group=knot -CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETPCAP -AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_SETPCAP -ExecStartPre=/usr/sbin/knotc conf-check -ExecStart=/usr/sbin/knotd -m "$KNOT_CONF_MAX_SIZE" -ExecReload=/bin/kill -HUP $MAINPID -Restart=on-abort -LimitNOFILE=1048576 -TimeoutStopSec=300 -# Extend the systemd startup timeout by this value (seconds) for each zone -Environment="KNOT_ZONE_LOAD_TIMEOUT_SEC=180" -# Maximum size (MiB) of a configuration database -Environment="KNOT_CONF_MAX_SIZE=512" - -[Install] -WantedBy=multi-user.target diff --git a/distro/pkg/el-7/knot.spec b/distro/pkg/el-7/knot.spec deleted file mode 100644 index 887f988..0000000 --- a/distro/pkg/el-7/knot.spec +++ /dev/null @@ -1,334 +0,0 @@ -%global _hardened_build 1 -%{!?_pkgdocdir: %global _pkgdocdir %{_docdir}/%{name}} - -%define GPG_CHECK 0 -%define BASE_VERSION %(echo "%{version}" | sed 's/^\\([^.]\\+\\.[^.]\\+\\).*/\\1/') -%define repodir %{_builddir}/%{name}-%{version} - -Summary: High-performance authoritative DNS server -Name: knot -Version: {{ version }} -Release: cznic.{{ release }}%{?dist} -License: GPL-3.0-or-later -URL: https://www.knot-dns.cz -Source0: %{name}-%{version}.tar.xz - -%if 0%{?GPG_CHECK} -Source1: https://secure.nic.cz/files/knot-dns/%{name}-%{version}.tar.xz.asc -# PGP keys used to sign upstream releases -# Export with --armor using command from https://fedoraproject.org/wiki/PackagingDrafts:GPGSignatures -# Don't forget to update %%prep section when adding/removing keys -Source100: gpgkey-742FA4E95829B6C5EAC6B85710BB7AF6FEBBD6AB.gpg.asc -BuildRequires: gnupg2 -%endif - -Patch1: 01-revert-AC_PROG_CC.patch -Patch2: 02-fix-compilation-by-using-SHA-1.patch -Patch3: 03-doc-don-t-try-to-import-sphinx_panels.patch -Patch4: 04-revert-don-t-share-PKCS-11-private-keys.patch -Patch5: 05-revert-mod-dnstap-TCP-sink.patch - -# Required dependencies -BuildRequires: autoconf -BuildRequires: automake -BuildRequires: libtool -BuildRequires: devtoolset-11-make -BuildRequires: devtoolset-11-gcc -BuildRequires: pkgconfig(liburcu) -BuildRequires: pkgconfig(gnutls) >= 3.3 -BuildRequires: pkgconfig(libedit) - -# Optional dependencies -BuildRequires: pkgconfig(libcap-ng) -BuildRequires: pkgconfig(libidn2) -BuildRequires: pkgconfig(libmnl) -BuildRequires: pkgconfig(libnghttp2) -BuildRequires: pkgconfig(libsystemd) -BuildRequires: pkgconfig(systemd) -# dnstap dependencies -BuildRequires: pkgconfig(libfstrm) -BuildRequires: pkgconfig(libprotobuf-c) -# geoip dependencies -BuildRequires: pkgconfig(libmaxminddb) - -# Distro-dependent dependencies -%if 0%{?suse_version} -BuildRequires: python3-Sphinx -BuildRequires: lmdb-devel -BuildRequires: protobuf-c -Requires(pre): pwdutils -%endif -%if 0%{?rhel} && 0%{?rhel} <= 7 -BuildRequires: python-sphinx -BuildRequires: lmdb-devel -%endif -%if 0%{?fedora} || 0%{?rhel} > 7 -BuildRequires: python3-sphinx -BuildRequires: pkgconfig(lmdb) -%endif - -# disable XDP on old EL -%define configure_xdp --enable-xdp=no - -Requires(post): systemd %{_sbindir}/runuser -Requires(preun): systemd -Requires(postun): systemd - -Conflicts: knot-resolver < 5.7.0 - -Requires: %{name}-libs%{?_isa} = %{version}-%{release} - -%description -Knot DNS is a high-performance authoritative DNS server implementation. - -%package libs -Summary: Libraries used by the Knot DNS server and client applications - -%description libs -The package contains shared libraries used by the Knot DNS server and -utilities. - -%package devel -Summary: Development header files for the Knot DNS libraries -Requires: %{name}-libs%{?_isa} = %{version}-%{release} - -%description devel -The package contains development header files for the Knot DNS libraries -included in knot-libs package. - -%package utils -Summary: DNS client utilities shipped with the Knot DNS server -Requires: %{name}-libs%{?_isa} = %{version}-%{release} -# Debian package compat -Provides: %{name}-dnsutils = %{version}-%{release} - -%description utils -The package contains DNS client utilities shipped with the Knot DNS server. - -%package dnssecutils -Summary: DNSSEC tools shipped with the Knot DNS server -Requires: %{name}-libs%{?_isa} = %{version}-%{release} - -%description dnssecutils -The package contains DNSSEC tools shipped with the Knot DNS server. - -%package module-dnstap -Summary: dnstap module for Knot DNS -Requires: %{name} = %{version}-%{release} - -%description module-dnstap -The package contains dnstap Knot DNS module for logging DNS traffic. - -%package module-geoip -Summary: geoip module for Knot DNS -Requires: %{name} = %{version}-%{release} - -%description module-geoip -The package contains geoip Knot DNS module for geography-based responses. - -%package doc -Summary: Documentation for the Knot DNS server -BuildArch: noarch -Provides: bundled(jquery) - -%description doc -The package contains documentation for the Knot DNS server. -On-line version is available on https://www.knot-dns.cz/documentation/ - -%prep -%if 0%{?GPG_CHECK} -export GNUPGHOME=./gpg-keyring -[ -d ${GNUPGHOME} ] && rm -r ${GNUPGHOME} -mkdir --mode=700 ${GNUPGHOME} -gpg2 --import %{SOURCE100} -gpg2 --verify %{SOURCE1} %{SOURCE0} -%endif -%autosetup -p1 - -%build -# disable debug code (causes unused warnings) -CFLAGS="%{optflags} -DNDEBUG -Wno-unused" - -%ifarch armv7hl i686 -# 32-bit architectures sometimes do not have sufficient amount of -# contiguous address space to handle default values -%define configure_db_sizes --with-conf-mapsize=64 -%endif - -autoreconf -if - -export CC="/opt/rh/devtoolset-11/root/usr/bin/gcc" -%configure \ - --sysconfdir=/etc \ - --localstatedir=/var/lib \ - --libexecdir=/usr/lib/knot \ - --with-rundir=/run/knot \ - --with-moduledir=%{_libdir}/knot/modules-%{BASE_VERSION} \ - --with-storage=/var/lib/knot \ - %{?configure_db_sizes} \ - %{?configure_xdp} \ - --disable-static \ - --enable-dnstap=yes \ - --with-module-dnstap=shared \ - --with-module-geoip=shared -make %{?_smp_mflags} -make html - -%install -make install DESTDIR=%{buildroot} - -# install documentation -install -d -m 0755 %{buildroot}%{_pkgdocdir}/samples -install -p -m 0644 -t %{buildroot}%{_pkgdocdir}/samples samples/*.zone* -install -p -m 0644 NEWS README.md %{buildroot}%{_pkgdocdir} -cp -av doc/_build/html %{buildroot}%{_pkgdocdir} -[ -r %{buildroot}%{_pkgdocdir}/html/index.html ] || exit 1 -rm -f %{buildroot}%{_pkgdocdir}/html/.buildinfo - -# install daemon and dbus configuration files -rm %{buildroot}%{_sysconfdir}/%{name}/* -install -p -m 0644 -D %{repodir}/samples/%{name}.sample.conf %{buildroot}%{_sysconfdir}/%{name}/%{name}.conf -%if 0%{?fedora} || 0%{?rhel} > 7 -install -p -m 0644 -D %{repodir}/distro/common/cz.nic.knotd.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/cz.nic.knotd.conf -%endif - -# install systemd files -install -p -m 0644 -D %{repodir}/distro/pkg/el-7/%{name}.service %{buildroot}%{_unitdir}/%{name}.service -install -p -m 0644 -D %{repodir}/distro/pkg/el-7/%{name}.tmpfiles %{buildroot}%{_tmpfilesdir}/%{name}.conf -%if 0%{?suse_version} -ln -s service %{buildroot}/%{_sbindir}/rcknot -%endif - -# create storage dir -install -d %{buildroot}%{_sharedstatedir} -install -d -m 0770 -D %{buildroot}%{_sharedstatedir}/knot - -# remove libarchive files -find %{buildroot} -type f -name "*.la" -delete -print - -%check -V=1 make check - -%pre -getent group knot >/dev/null || groupadd -r knot -getent passwd knot >/dev/null || \ - useradd -r -g knot -d %{_sharedstatedir}/knot -s /sbin/nologin \ - -c "Knot DNS server" knot -%if 0%{?suse_version} -%service_add_pre knot.service -%endif - -%post -systemd-tmpfiles --create %{_tmpfilesdir}/knot.conf &>/dev/null || : -%if 0%{?suse_version} -%service_add_post knot.service -%else -%systemd_post knot.service -%endif - -%preun -%if 0%{?suse_version} -%service_del_preun knot.service -%else -%systemd_preun knot.service -%endif - -%postun -%if 0%{?suse_version} -%service_del_postun knot.service -%else -%systemd_postun_with_restart knot.service -%endif - -%if 0%{?fedora} || 0%{?rhel} > 7 -# https://fedoraproject.org/wiki/Changes/Removing_ldconfig_scriptlets -%else -%post libs -p /sbin/ldconfig -%postun libs -p /sbin/ldconfig -%endif - -%files -%license COPYING -%doc %{_pkgdocdir} -%exclude %{_pkgdocdir}/html -%attr(770,root,knot) %dir %{_sysconfdir}/knot -%config(noreplace) %attr(640,root,knot) %{_sysconfdir}/knot/knot.conf -%if 0%{?fedora} || 0%{?rhel} > 7 -%config(noreplace) %attr(644,root,root) %{_sysconfdir}/dbus-1/system.d/cz.nic.knotd.conf -%endif -%attr(770,root,knot) %dir %{_sharedstatedir}/knot -%dir %{_libdir}/knot -%dir %{_libdir}/knot/modules-* -%{_unitdir}/knot.service -%{_tmpfilesdir}/knot.conf -%{_sbindir}/kcatalogprint -%{_sbindir}/kjournalprint -%{_sbindir}/keymgr -%{_sbindir}/knotc -%{_sbindir}/knotd -%if 0%{?suse_version} -%{_sbindir}/rcknot -%endif -%{_mandir}/man5/knot.conf.* -%{_mandir}/man8/kcatalogprint.* -%{_mandir}/man8/kjournalprint.* -%{_mandir}/man8/keymgr.* -%{_mandir}/man8/knotc.* -%{_mandir}/man8/knotd.* -%ghost %attr(770,root,knot) %dir %{_rundir}/knot - -%files utils -%{_bindir}/kdig -%{_bindir}/khost -%{_bindir}/knsupdate -%if 0%{?use_xdp} -%{_sbindir}/kxdpgun -%{_mandir}/man8/kxdpgun.* -%endif -%{_mandir}/man1/kdig.* -%{_mandir}/man1/khost.* -%{_mandir}/man1/knsupdate.* - -%files dnssecutils -%{_bindir}/knsec3hash -%{_bindir}/kzonecheck -%{_bindir}/kzonesign -%{_mandir}/man1/knsec3hash.* -%{_mandir}/man1/kzonecheck.* -%{_mandir}/man1/kzonesign.* - -%files module-dnstap -%{_libdir}/knot/modules-*/dnstap.so - -%files module-geoip -%{_libdir}/knot/modules-*/geoip.so - -%files libs -%license COPYING -%doc NEWS -%doc README.md -%{_libdir}/libdnssec.so.* -%{_libdir}/libknot.so.* -%{_libdir}/libzscanner.so.* - -%files devel -%{_includedir}/libdnssec -%{_includedir}/knot -%{_includedir}/libknot -%{_includedir}/libzscanner -%{_libdir}/libdnssec.so -%{_libdir}/libknot.so -%{_libdir}/libzscanner.so -%{_libdir}/pkgconfig/knotd.pc -%{_libdir}/pkgconfig/libdnssec.pc -%{_libdir}/pkgconfig/libknot.pc -%{_libdir}/pkgconfig/libzscanner.pc - -%files doc -%dir %{_pkgdocdir} -%doc %{_pkgdocdir}/html - -%changelog -* {{ now }} Jakub Ružička - {{ version }}-{{ release }} -- upstream package -- see https://www.knot-dns.cz diff --git a/distro/pkg/el-7/knot.tmpfiles b/distro/pkg/el-7/knot.tmpfiles deleted file mode 100644 index edec729..0000000 --- a/distro/pkg/el-7/knot.tmpfiles +++ /dev/null @@ -1,3 +0,0 @@ -# tmpfiles.d(5) runtime directory for knot -#Type Path Mode UID GID Age Argument - d /run/knot 0755 knot knot - - diff --git a/distro/pkg/rpm/knot.spec b/distro/pkg/rpm/knot.spec index 3a7d89e..c99ea55 100644 --- a/distro/pkg/rpm/knot.spec +++ b/distro/pkg/rpm/knot.spec @@ -84,7 +84,7 @@ Knot DNS is a high-performance authoritative DNS server implementation. %package libs Summary: Libraries used by the Knot DNS server and client applications -Conflicts: knot-resolver < 5.7.0 +Conflicts: knot-resolver < 5.7.3 %description libs The package contains shared libraries used by the Knot DNS server and diff --git a/doc/Makefile.am b/doc/Makefile.am index b26e298..71d561c 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,18 +1,3 @@ -MANPAGES_IN = \ - man/knot.conf.5in \ - man/knotc.8in \ - man/knotd.8in \ - man/kcatalogprint.8in \ - man/keymgr.8in \ - man/kjournalprint.8in \ - man/kdig.1in \ - man/khost.1in \ - man/knsupdate.1in \ - man/knsec3hash.1in \ - man/kzonecheck.1in \ - man/kzonesign.1in \ - man/kxdpgun.8in - MANPAGES_RST = \ reference.rst \ man_knotc.rst \ @@ -44,7 +29,6 @@ EXTRA_DIST = \ troubleshooting.rst \ utilities.rst \ \ - $(MANPAGES_IN) \ $(MANPAGES_RST) \ \ logo.pdf \ @@ -66,27 +50,26 @@ SPHINXBUILDDIR = $(builddir)/_build _SPHINXOPTS = -c $(srcdir) \ -a \ - $(SPHINX_V) - -ALLSPHINXOPTS = $(_SPHINXOPTS) \ + $(SPHINX_V) \ -D version="$(VERSION)" \ -D today="$(RELEASE_DATE)" \ - -D release="$(VERSION)" \ + -D release="$(VERSION)" + +ALLSPHINXOPTS = $(_SPHINXOPTS) \ $(SPHINXOPTS) \ $(srcdir) man_SPHINXOPTS = $(_SPHINXOPTS) \ - -D version="@""VERSION@" \ - -D today="@""RELEASE_DATE@" \ - -D release="@""VERSION@" \ -D extensions="ignore_panels" \ $(SPHINXOPTS) \ $(srcdir) -.PHONY: html-local singlehtml pdf-local info-local epub man install-html-local install-singlehtml install-pdf-local install-info-local install-epub +.PHONY: html-local singlehtml pdf-local epub man install-html-local install-singlehtml install-pdf-local install-epub man_MANS = +if HAVE_DOCS + if HAVE_DAEMON man_MANS += \ man/knot.conf.5 \ @@ -115,43 +98,8 @@ man_MANS += man/kxdpgun.8 endif # ENABLE_XDP endif # HAVE_UTILS -man/knot.conf.5: man/knot.conf.5in -man/knotc.8: man/knotc.8in -man/knotd.8: man/knotd.8in -man/kcatalogprint.8: man/kcatalogprint.8in -man/keymgr.8: man/keymgr.8in -man/kjournalprint.8: man/kjournalprint.8in -man/kdig.1: man/kdig.1in -man/khost.1: man/khost.1in -man/knsupdate.1: man/knsupdate.1in -man/knsec3hash.1: man/knsec3hash.1in -man/kzonecheck.1: man/kzonecheck.1in -man/kzonesign.1: man/kzonesign.1in -man/kxdpgun.8: man/kxdpgun.8in - -man_SUBST = $(AM_V_GEN)mkdir -p man; \ - sed -e 's,[@]VERSION@,$(VERSION),' \ - -e 's,[@]RELEASE_DATE@,$(RELEASE_DATE),' \ - -e 's,[@]config_dir@,$(config_dir),' \ - -e 's,[@]storage_dir@,$(storage_dir),' \ - -e 's,[@]run_dir@,$(run_dir),' \ - -e 's,[@]conf_mapsize@,$(conf_mapsize),' \ - $< > $@ - -.1in.1: - $(man_SUBST) - -.5in.5: - $(man_SUBST) - -.8in.8: - $(man_SUBST) - -if HAVE_DOCS - -if HAVE_SPHINXBUILD html-local: - $(AM_V_SPHINX)$(SPHINXBUILD) -b html -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/html + $(AM_V_SPHINX)$(SPHINXBUILD) -b html -d $(SPHINXBUILDDIR)/doctrees/html $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/html @echo "The HTML documentation has been built in $(SPHINXBUILDDIR)/html/" install-html-local: @@ -161,7 +109,7 @@ install-html-local: $(INSTALL_DATA) $(SPHINXBUILDDIR)/html/_static/* $(DESTDIR)/$(docdir)/_static/ singlehtml: - $(AM_V_SPHINX)$(SPHINXBUILD) -b singlehtml -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/singlehtml + $(AM_V_SPHINX)$(SPHINXBUILD) -b singlehtml -d $(SPHINXBUILDDIR)/doctrees/singlehtml $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/singlehtml @echo "The single HTML documentation has been built in $(SPHINXBUILDDIR)/singlehtml/" install-singlehtml: singlehtml @@ -170,7 +118,7 @@ install-singlehtml: singlehtml $(INSTALL_DATA) $(SPHINXBUILDDIR)/singlehtml/_static/* $(DESTDIR)/$(docdir)/_static/ epub: - $(AM_V_SPHINX)$(SPHINXBUILD) -b epub -A today=$(RELEASE_DATE) -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/epub + $(AM_V_SPHINX)$(SPHINXBUILD) -b epub -A today=$(RELEASE_DATE) -d $(SPHINXBUILDDIR)/doctrees/epub $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/epub @echo "The EPUB documentation has been built in $(SPHINXBUILDDIR)/epub/" install-epub: @@ -179,7 +127,7 @@ install-epub: if HAVE_PDFLATEX pdf-local: - $(AM_V_SPHINX)$(SPHINXBUILD) -b latex -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/latex + $(AM_V_SPHINX)$(SPHINXBUILD) -b latex -d $(SPHINXBUILDDIR)/doctrees/latex $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/latex $(MAKE) -C $(SPHINXBUILDDIR)/latex all-pdf @echo "The PDF documentation has been built in $(SPHINXBUILDDIR)/latex/" @@ -192,37 +140,26 @@ pdf-local install-pdf-local: @echo "Install 'pdflatex' and re-run configure to be able to generate PDF documentation!" endif # HAVE_PDFLATEX -if HAVE_MAKEINFO -info-local: - $(AM_V_SPHINX)$(SPHINXBUILD) -b texinfo -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/texinfo - $(MAKE) -C $(SPHINXBUILDDIR)/texinfo info - @echo "The Info pages have been built in $(SPHINXBUILDDIR)/texinfo/" - -install-info-local: - $(INSTALL) -d $(DESTDIR)/$(infodir) - $(INSTALL_DATA) $(SPHINXBUILDDIR)/texinfo/knot.info $(DESTDIR)/$(infodir)/ - -else -info-local install-info-local: - @echo "Install 'texinfo' and re-run configure to be able to generate Info pages!" -endif # HAVE_MAKEINFO - -.NOTPARALLEL: man man: $(man_MANS) -$(MANPAGES_IN): $(MANPAGES_RST) - $(AM_V_SPHINX)$(SPHINXBUILD) -b man -d $(SPHINXBUILDDIR)/doctrees $(man_SPHINXOPTS) $(SPHINXBUILDDIR)/man - @mkdir -p $(srcdir)/man +$(man_MANS)&: $(MANPAGES_RST) + $(AM_V_SPHINX)$(SPHINXBUILD) -b man -d $(SPHINXBUILDDIR)/doctrees/man $(man_SPHINXOPTS) $(SPHINXBUILDDIR)/man + @mkdir -p man @for f in $(SPHINXBUILDDIR)/man/*; do \ - sed -e '/^\.TP$$/ {' -e 'n' -e 's/^\.B //' -e '}' "$$f" > "$(srcdir)/man/$$(basename $$f)in"; \ + sed -e 's,[@]config_dir@,$(config_dir),' \ + -e 's,[@]storage_dir@,$(storage_dir),' \ + -e 's,[@]run_dir@,$(run_dir),' \ + -e 's,[@]conf_mapsize@,$(conf_mapsize),' "$$f" > "man/$$(basename $$f)"; \ done else -html-local singlehtml pdf-local info-local epub man install-html-local install-singlehtml install-pdf-local install-info-local install-epub: +html-local singlehtml pdf-local epub man install-html-local install-singlehtml install-pdf-local install-epub: @echo "Install 'sphinx-build' and re-run configure to be able to generate documentation!" -endif # HAVE_SPHINXBUILD endif # HAVE_DOCS +EXTRA_DIST += \ + $(man_MANS) + clean-local: -rm -rf $(SPHINXBUILDDIR) - -rm -f man/*.1 man/*.5 man/*.8 + -rm -rf man diff --git a/doc/Makefile.in b/doc/Makefile.in index 5642629..a7bacd9 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -87,25 +87,25 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -@HAVE_DAEMON_TRUE@am__append_1 = \ -@HAVE_DAEMON_TRUE@ man/knot.conf.5 \ -@HAVE_DAEMON_TRUE@ man/knotc.8 \ -@HAVE_DAEMON_TRUE@ man/knotd.8 - -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@am__append_2 = \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ man/kcatalogprint.8 \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ man/keymgr.8 \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ man/kjournalprint.8 \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ man/kzonecheck.1 \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ man/kzonesign.1 - -@HAVE_UTILS_TRUE@am__append_3 = \ -@HAVE_UTILS_TRUE@ man/kdig.1 \ -@HAVE_UTILS_TRUE@ man/khost.1 \ -@HAVE_UTILS_TRUE@ man/knsupdate.1 \ -@HAVE_UTILS_TRUE@ man/knsec3hash.1 - -@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@am__append_4 = man/kxdpgun.8 +@HAVE_DAEMON_TRUE@@HAVE_DOCS_TRUE@am__append_1 = \ +@HAVE_DAEMON_TRUE@@HAVE_DOCS_TRUE@ man/knot.conf.5 \ +@HAVE_DAEMON_TRUE@@HAVE_DOCS_TRUE@ man/knotc.8 \ +@HAVE_DAEMON_TRUE@@HAVE_DOCS_TRUE@ man/knotd.8 + +@HAVE_DAEMON_TRUE@@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@am__append_2 = \ +@HAVE_DAEMON_TRUE@@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@ man/kcatalogprint.8 \ +@HAVE_DAEMON_TRUE@@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@ man/keymgr.8 \ +@HAVE_DAEMON_TRUE@@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@ man/kjournalprint.8 \ +@HAVE_DAEMON_TRUE@@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@ man/kzonecheck.1 \ +@HAVE_DAEMON_TRUE@@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@ man/kzonesign.1 + +@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@am__append_3 = \ +@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@ man/kdig.1 \ +@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@ man/khost.1 \ +@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@ man/knsupdate.1 \ +@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@ man/knsec3hash.1 + +@ENABLE_XDP_TRUE@@HAVE_DOCS_TRUE@@HAVE_UTILS_TRUE@am__append_4 = man/kxdpgun.8 subdir = doc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ @@ -312,6 +312,8 @@ infodir = @infodir@ install_sh = @install_sh@ libbpf_CFLAGS = @libbpf_CFLAGS@ libbpf_LIBS = @libbpf_LIBS@ +libdbus_CFLAGS = @libdbus_CFLAGS@ +libdbus_LIBS = @libdbus_LIBS@ libdir = @libdir@ libdnssec_SONAME = @libdnssec_SONAME@ libdnssec_SOVERSION = @libdnssec_SOVERSION@ @@ -323,8 +325,6 @@ libfstrm_CFLAGS = @libfstrm_CFLAGS@ libfstrm_LIBS = @libfstrm_LIBS@ libidn2_CFLAGS = @libidn2_CFLAGS@ libidn2_LIBS = @libidn2_LIBS@ -libidn_CFLAGS = @libidn_CFLAGS@ -libidn_LIBS = @libidn_LIBS@ libknot_SONAME = @libknot_SONAME@ libknot_SOVERSION = @libknot_SOVERSION@ libknot_VERSION_INFO = @libknot_VERSION_INFO@ @@ -342,7 +342,6 @@ libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@ libprotobuf_c_LIBS = @libprotobuf_c_LIBS@ liburcu_CFLAGS = @liburcu_CFLAGS@ liburcu_LIBS = @liburcu_LIBS@ -liburcu_PKGCONFIG = @liburcu_PKGCONFIG@ libxdp_CFLAGS = @libxdp_CFLAGS@ libxdp_LIBS = @libxdp_LIBS@ libzscanner_SONAME = @libzscanner_SONAME@ @@ -378,21 +377,6 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -MANPAGES_IN = \ - man/knot.conf.5in \ - man/knotc.8in \ - man/knotd.8in \ - man/kcatalogprint.8in \ - man/keymgr.8in \ - man/kjournalprint.8in \ - man/kdig.1in \ - man/khost.1in \ - man/knsupdate.1in \ - man/knsec3hash.1in \ - man/kzonecheck.1in \ - man/kzonesign.1in \ - man/kxdpgun.8in - MANPAGES_RST = \ reference.rst \ man_knotc.rst \ @@ -408,31 +392,11 @@ MANPAGES_RST = \ man_kzonesign.rst \ man_kxdpgun.rst -EXTRA_DIST = \ - conf.py \ - \ - appendices.rst \ - configuration.rst \ - index.rst \ - installation.rst \ - introduction.rst \ - migration.rst \ - modules.rst.in \ - operation.rst \ - reference.rst \ - requirements.rst \ - troubleshooting.rst \ - utilities.rst \ - \ - $(MANPAGES_IN) \ - $(MANPAGES_RST) \ - \ - logo.pdf \ - logo.svg \ - \ - ext/ignore_panels.py \ - theme_html - +EXTRA_DIST = conf.py appendices.rst configuration.rst index.rst \ + installation.rst introduction.rst migration.rst modules.rst.in \ + operation.rst reference.rst requirements.rst \ + troubleshooting.rst utilities.rst $(MANPAGES_RST) logo.pdf \ + logo.svg ext/ignore_panels.py theme_html $(man_MANS) SPHINX_V = $(SPHINX_V_@AM_V@) SPHINX_V_ = $(SPHINX_V_@AM_DEFAULT_V@) SPHINX_V_0 = -q @@ -443,38 +407,25 @@ AM_V_SPHINX_0 = @echo " SPHINX $@"; SPHINXBUILDDIR = $(builddir)/_build _SPHINXOPTS = -c $(srcdir) \ -a \ - $(SPHINX_V) - -ALLSPHINXOPTS = $(_SPHINXOPTS) \ + $(SPHINX_V) \ -D version="$(VERSION)" \ -D today="$(RELEASE_DATE)" \ - -D release="$(VERSION)" \ + -D release="$(VERSION)" + +ALLSPHINXOPTS = $(_SPHINXOPTS) \ $(SPHINXOPTS) \ $(srcdir) man_SPHINXOPTS = $(_SPHINXOPTS) \ - -D version="@""VERSION@" \ - -D today="@""RELEASE_DATE@" \ - -D release="@""VERSION@" \ -D extensions="ignore_panels" \ $(SPHINXOPTS) \ $(srcdir) man_MANS = $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) -man_SUBST = $(AM_V_GEN)mkdir -p man; \ - sed -e 's,[@]VERSION@,$(VERSION),' \ - -e 's,[@]RELEASE_DATE@,$(RELEASE_DATE),' \ - -e 's,[@]config_dir@,$(config_dir),' \ - -e 's,[@]storage_dir@,$(storage_dir),' \ - -e 's,[@]run_dir@,$(run_dir),' \ - -e 's,[@]conf_mapsize@,$(conf_mapsize),' \ - $< > $@ - all: all-am .SUFFIXES: -.SUFFIXES: .1 .1in .5 .5in .8 .8in $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -718,21 +669,11 @@ maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @HAVE_DOCS_FALSE@html-local: -@HAVE_SPHINXBUILD_FALSE@html-local: -@HAVE_DOCS_FALSE@info-local: -@HAVE_MAKEINFO_FALSE@info-local: -@HAVE_SPHINXBUILD_FALSE@info-local: @HAVE_DOCS_FALSE@install-html-local: -@HAVE_SPHINXBUILD_FALSE@install-html-local: -@HAVE_DOCS_FALSE@install-info-local: -@HAVE_MAKEINFO_FALSE@install-info-local: -@HAVE_SPHINXBUILD_FALSE@install-info-local: @HAVE_DOCS_FALSE@install-pdf-local: @HAVE_PDFLATEX_FALSE@install-pdf-local: -@HAVE_SPHINXBUILD_FALSE@install-pdf-local: @HAVE_DOCS_FALSE@pdf-local: @HAVE_PDFLATEX_FALSE@pdf-local: -@HAVE_SPHINXBUILD_FALSE@pdf-local: clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am @@ -751,7 +692,7 @@ html-am: html-local info: info-am -info-am: info-local +info-am: install-data-am: install-man @@ -767,7 +708,7 @@ install-html-am: install-html-local install-info: install-info-am -install-info-am: install-info-local +install-info-am: install-man: install-man1 install-man5 install-man8 @@ -806,11 +747,10 @@ uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8 .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am html-local \ - info info-am info-local install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am \ - install-html-local install-info install-info-am \ - install-info-local install-man install-man1 install-man5 \ + info info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-html-local install-info \ + install-info-am install-man install-man1 install-man5 \ install-man8 install-pdf install-pdf-am install-pdf-local \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ @@ -822,97 +762,64 @@ uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8 .PRECIOUS: Makefile -.PHONY: html-local singlehtml pdf-local info-local epub man install-html-local install-singlehtml install-pdf-local install-info-local install-epub - -man/knot.conf.5: man/knot.conf.5in -man/knotc.8: man/knotc.8in -man/knotd.8: man/knotd.8in -man/kcatalogprint.8: man/kcatalogprint.8in -man/keymgr.8: man/keymgr.8in -man/kjournalprint.8: man/kjournalprint.8in -man/kdig.1: man/kdig.1in -man/khost.1: man/khost.1in -man/knsupdate.1: man/knsupdate.1in -man/knsec3hash.1: man/knsec3hash.1in -man/kzonecheck.1: man/kzonecheck.1in -man/kzonesign.1: man/kzonesign.1in -man/kxdpgun.8: man/kxdpgun.8in - -.1in.1: - $(man_SUBST) - -.5in.5: - $(man_SUBST) - -.8in.8: - $(man_SUBST) - -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@html-local: -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b html -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/html -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ @echo "The HTML documentation has been built in $(SPHINXBUILDDIR)/html/" - -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@install-html-local: -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir) $(DESTDIR)/$(docdir)/_static $(DESTDIR)/$(docdir)/_sources -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -D $(SPHINXBUILDDIR)/html/*.html $(DESTDIR)/$(docdir)/ -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/html/_sources/* $(DESTDIR)/$(docdir)/_sources/ -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/html/_static/* $(DESTDIR)/$(docdir)/_static/ - -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@singlehtml: -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b singlehtml -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/singlehtml -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ @echo "The single HTML documentation has been built in $(SPHINXBUILDDIR)/singlehtml/" - -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@install-singlehtml: singlehtml -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir) $(DESTDIR)/$(docdir)/_static -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/singlehtml/*.html $(DESTDIR)/$(docdir)/ -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/singlehtml/_static/* $(DESTDIR)/$(docdir)/_static/ - -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@epub: -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b epub -A today=$(RELEASE_DATE) -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/epub -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ @echo "The EPUB documentation has been built in $(SPHINXBUILDDIR)/epub/" - -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@install-epub: -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir) -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/epub/KnotDNS.epub $(DESTDIR)/$(docdir)/ - -@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@pdf-local: -@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b latex -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/latex -@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(MAKE) -C $(SPHINXBUILDDIR)/latex all-pdf -@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@ @echo "The PDF documentation has been built in $(SPHINXBUILDDIR)/latex/" - -@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@install-pdf-local: -@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir) -@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/latex/KnotDNS.pdf $(DESTDIR)/$(docdir)/ - -@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_FALSE@@HAVE_SPHINXBUILD_TRUE@pdf-local install-pdf-local: -@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_FALSE@@HAVE_SPHINXBUILD_TRUE@ @echo "Install 'pdflatex' and re-run configure to be able to generate PDF documentation!" - -@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@info-local: -@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b texinfo -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/texinfo -@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(MAKE) -C $(SPHINXBUILDDIR)/texinfo info -@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@ @echo "The Info pages have been built in $(SPHINXBUILDDIR)/texinfo/" - -@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@install-info-local: -@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -d $(DESTDIR)/$(infodir) -@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/texinfo/knot.info $(DESTDIR)/$(infodir)/ - -@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_FALSE@@HAVE_SPHINXBUILD_TRUE@info-local install-info-local: -@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_FALSE@@HAVE_SPHINXBUILD_TRUE@ @echo "Install 'texinfo' and re-run configure to be able to generate Info pages!" - -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@.NOTPARALLEL: man -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@man: $(man_MANS) -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@$(MANPAGES_IN): $(MANPAGES_RST) -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b man -d $(SPHINXBUILDDIR)/doctrees $(man_SPHINXOPTS) $(SPHINXBUILDDIR)/man -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ @mkdir -p $(srcdir)/man -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ @for f in $(SPHINXBUILDDIR)/man/*; do \ -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ sed -e '/^\.TP$$/ {' -e 'n' -e 's/^\.B //' -e '}' "$$f" > "$(srcdir)/man/$$(basename $$f)in"; \ -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ done - -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_FALSE@html-local singlehtml pdf-local info-local epub man install-html-local install-singlehtml install-pdf-local install-info-local install-epub: -@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_FALSE@ @echo "Install 'sphinx-build' and re-run configure to be able to generate documentation!" +.PHONY: html-local singlehtml pdf-local epub man install-html-local install-singlehtml install-pdf-local install-epub + +@HAVE_DOCS_TRUE@html-local: +@HAVE_DOCS_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b html -d $(SPHINXBUILDDIR)/doctrees/html $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/html +@HAVE_DOCS_TRUE@ @echo "The HTML documentation has been built in $(SPHINXBUILDDIR)/html/" + +@HAVE_DOCS_TRUE@install-html-local: +@HAVE_DOCS_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir) $(DESTDIR)/$(docdir)/_static $(DESTDIR)/$(docdir)/_sources +@HAVE_DOCS_TRUE@ $(INSTALL) -D $(SPHINXBUILDDIR)/html/*.html $(DESTDIR)/$(docdir)/ +@HAVE_DOCS_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/html/_sources/* $(DESTDIR)/$(docdir)/_sources/ +@HAVE_DOCS_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/html/_static/* $(DESTDIR)/$(docdir)/_static/ + +@HAVE_DOCS_TRUE@singlehtml: +@HAVE_DOCS_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b singlehtml -d $(SPHINXBUILDDIR)/doctrees/singlehtml $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/singlehtml +@HAVE_DOCS_TRUE@ @echo "The single HTML documentation has been built in $(SPHINXBUILDDIR)/singlehtml/" + +@HAVE_DOCS_TRUE@install-singlehtml: singlehtml +@HAVE_DOCS_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir) $(DESTDIR)/$(docdir)/_static +@HAVE_DOCS_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/singlehtml/*.html $(DESTDIR)/$(docdir)/ +@HAVE_DOCS_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/singlehtml/_static/* $(DESTDIR)/$(docdir)/_static/ + +@HAVE_DOCS_TRUE@epub: +@HAVE_DOCS_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b epub -A today=$(RELEASE_DATE) -d $(SPHINXBUILDDIR)/doctrees/epub $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/epub +@HAVE_DOCS_TRUE@ @echo "The EPUB documentation has been built in $(SPHINXBUILDDIR)/epub/" + +@HAVE_DOCS_TRUE@install-epub: +@HAVE_DOCS_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir) +@HAVE_DOCS_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/epub/KnotDNS.epub $(DESTDIR)/$(docdir)/ + +@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@pdf-local: +@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b latex -d $(SPHINXBUILDDIR)/doctrees/latex $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/latex +@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@ $(MAKE) -C $(SPHINXBUILDDIR)/latex all-pdf +@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@ @echo "The PDF documentation has been built in $(SPHINXBUILDDIR)/latex/" + +@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@install-pdf-local: +@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir) +@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/latex/KnotDNS.pdf $(DESTDIR)/$(docdir)/ + +@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_FALSE@pdf-local install-pdf-local: +@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_FALSE@ @echo "Install 'pdflatex' and re-run configure to be able to generate PDF documentation!" + +@HAVE_DOCS_TRUE@man: $(man_MANS) +@HAVE_DOCS_TRUE@$(man_MANS)&: $(MANPAGES_RST) +@HAVE_DOCS_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b man -d $(SPHINXBUILDDIR)/doctrees/man $(man_SPHINXOPTS) $(SPHINXBUILDDIR)/man +@HAVE_DOCS_TRUE@ @mkdir -p man +@HAVE_DOCS_TRUE@ @for f in $(SPHINXBUILDDIR)/man/*; do \ +@HAVE_DOCS_TRUE@ sed -e 's,[@]config_dir@,$(config_dir),' \ +@HAVE_DOCS_TRUE@ -e 's,[@]storage_dir@,$(storage_dir),' \ +@HAVE_DOCS_TRUE@ -e 's,[@]run_dir@,$(run_dir),' \ +@HAVE_DOCS_TRUE@ -e 's,[@]conf_mapsize@,$(conf_mapsize),' "$$f" > "man/$$(basename $$f)"; \ +@HAVE_DOCS_TRUE@ done + +@HAVE_DOCS_FALSE@html-local singlehtml pdf-local epub man install-html-local install-singlehtml install-pdf-local install-epub: +@HAVE_DOCS_FALSE@ @echo "Install 'sphinx-build' and re-run configure to be able to generate documentation!" clean-local: -rm -rf $(SPHINXBUILDDIR) - -rm -f man/*.1 man/*.5 man/*.8 + -rm -rf man # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/doc/appendices.rst b/doc/appendices.rst index 309bb20..1012623 100644 --- a/doc/appendices.rst +++ b/doc/appendices.rst @@ -103,24 +103,3 @@ support. A command similar to the following may be used to verify what algorithms are supported: ``$ pkcs11-tool --modul /usr/lib64/pkcs11/libsofthsm2.so -M``. .. [#fn-utimaco] Requires setting the number of background workers to 1! - -The following table summarizes supported DNSSEC algorithm numbers and minimal -GnuTLS library version required. Any algorithm may work with older library, -however the supported operations may be limited (e.g. private key import). - -.. list-table:: - :header-rows: 1 - :stub-columns: 1 - - * - - - `Numbers `_ - - GnuTLS version - * - ED25519 - - 15 - - 3.6.0 or newer - * - ECDSA - - 13, 14 - - 3.4.8 or newer - * - RSA - - 5, 7, 8, 10 - - 3.4.6 or newer diff --git a/doc/conf.py b/doc/conf.py index ec821d6..4b1c8e9 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -248,10 +248,7 @@ man_pages = [ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) -texinfo_documents = [ - ('index', 'knot', 'Knot DNS Documentation', author, - 'KnotDNS', 'Knot Authoritative DNS Server', 'Miscellaneous') -] +#texinfo_documents = [] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] diff --git a/doc/configuration.rst b/doc/configuration.rst index a29521b..982031b 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -377,6 +377,19 @@ which must be used for the transaction security:: - domain: example.net. acl: owner_rule3_net +.. _Handling CNAME and DNAME-related updates: + +Handling CNAME and DNAME-related updates +---------------------------------------- + +In general, no RR must exist beside a CNAME or below a DNAME. Whenever +such a CNAME or DNAME-related semantic rule is vialoated by an RR addition +in DDNS (this means addition of a CNAME beside an existing record, addition of +another record beside a CNAME, addition of a DNAME above an existing record, +addition of another record below a DNAME), such an RR addition is silently ignored. +However, other RRs from the same DDNS update are processed normally. This is slightly +non-compliant with RFC 6672 (in particular, no RR occlusion takes place). + .. _dnssec: Automatic DNSSEC signing @@ -826,7 +839,7 @@ of the used certificate: .. code-block:: console ... info: binding to QUIC interface ::1@853 - ... info: QUIC, certificate public key 0xtdayWpnJh4Py8goi8cei/gXGD4kJQ+HEqcxS++DBw= + ... info: QUIC/TLS, certificate public key 0xtdayWpnJh4Py8goi8cei/gXGD4kJQ+HEqcxS++DBw= .. TIP:: @@ -861,10 +874,10 @@ Using :doc:`kdig` we can verify that the server responds over QUIC: ;; version.server. CH TXT ;; ANSWER SECTION: - version.server. 0 CH TXT "Knot DNS 3.3.0" + version.server. 0 CH TXT "Knot DNS 3.4.0" ;; Received 468 B - ;; Time 2023-08-15 15:04:36 CEST + ;; Time 2024-06-21 08:30:12 CEST ;; From ::1@853(QUIC) in 1.1 ms In this case, :rfc:`opportunistic authentication<9103#section-9.3.1>` was @@ -1074,6 +1087,62 @@ This mode is recommended if possible. Knot DNS uses certificate public key pinning. This approach has much lower overhead and in most cases simplifies configuration and certificate management. +.. _DNS_over_TLS: + +DNS over TLS +============ + +TLS is an encrypted internet transport protocol. +Knot DNS supports DNS over TLS (DoT) (:rfc:`7858`), including zone transfers (XoT). +By default, the TCP port `853` is used for DNS over TLS. + +There are the same requirements for TLS key and certificate as for :ref:`DNS_over_QUIC`. + +In order to listen for incoming requests over TLS, :ref:`interface` +must be configured. + +An example of configuration of listening for DNS over TLS on the loopback interface: + +.. code-block:: console + + server: + listen-tls: ::1 + +When the server is started, it logs some interface details and public key pin +of the used certificate: + +.. code-block:: console + + ... info: binding to TLS interface ::1@853 + ... info: QUIC/TLS, certificate public key 0xtdayWpnJh4Py8goi8cei/gXGD4kJQ+HEqcxS++DBw= + +Using :doc:`kdig` we can verify that the server responds over TLS: + +.. code-block:: console + + $ kdig @::1 ch txt version.server +tls + ;; TLS session (TLS1.3)-(ECDHE-X25519)-(EdDSA-Ed25519)-(AES-256-GCM) + ;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 0 + ;; Flags: qr rd; QUERY: 1; ANSWER: 1; AUTHORITY: 0; ADDITIONAL: 1 + + ;; EDNS PSEUDOSECTION: + ;; Version: 0; flags: ; UDP size: 1232 B; ext-rcode: NOERROR + ;; PADDING: 370 B + + ;; QUESTION SECTION: + ;; version.server. CH TXT + + ;; ANSWER SECTION: + version.server. 0 CH TXT "Knot DNS 3.4.0" + + ;; Received 468 B + ;; Time 2024-06-21 08:31:13 CEST + ;; From ::1@853(TLS) in 9.1 ms + +Zone transfer configuration and authentication profiles are almost identical +to :ref:`DNS_over_QUIC`, with the only difference being the enabling of +:ref:`remote_tls` for the corresponding remotes. + .. _query-modules: Query modules diff --git a/doc/installation.rst b/doc/installation.rst index f89f439..8eebaa3 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -34,10 +34,7 @@ The build process relies on these standard tools: * autoconf >= 2.65 * python-sphinx (optional, for documentation building) -GCC >= 4.1 is mandatory for atomic built-ins, but the latest -available version is recommended. Another requirement is ``_GNU_SOURCE`` -and C99 support, otherwise it adapts to the available compiler features. -LLVM clang compiler since version 2.9 can be used as well. +A GCC or LLVM Clang compiler with C11 support. Getting the source code ----------------------- diff --git a/doc/introduction.rst b/doc/introduction.rst index 398d0d4..f472b85 100644 --- a/doc/introduction.rst +++ b/doc/introduction.rst @@ -29,7 +29,7 @@ DNS features: * Primary and secondary server operation * Internet (IN) and Chaos (CH) classes * DNS extension (EDNS0, EDE, EXPIRE) -* UDP, TCP, and QUIC protocols +* UDP, TCP, TLS 1.3, and QUIC protocols * Zone catalog generation and interpretation * Minimal responses * Dynamic zone updates @@ -73,7 +73,7 @@ Remarkable module extensions: Remarkable supported networking features: * TCP Fast Open (client and server) -* Opportunistic, strict, and mutual authentication profiles over QUIC +* Opportunistic, strict, and mutual authentication profiles over TLS 1.3 or QUIC * High-performance UDP, TCP, and QUIC through AF_XDP processing (on Linux 4.18+) * SO_REUSEPORT (on Linux) or SO_REUSEPORT_LB (on FreeBSD 12.0+) on UDP and by choice on TCP * Binding to non-local addresses (IP_FREEBIND on Linux, IP_BINDANY/IPV6_BINDANY on FreeBSD) diff --git a/doc/man/kcatalogprint.8 b/doc/man/kcatalogprint.8 new file mode 100644 index 0000000..f9d9fc9 --- /dev/null +++ b/doc/man/kcatalogprint.8 @@ -0,0 +1,81 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KCATALOGPRINT" "8" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +kcatalogprint \- Knot DNS catalog print utility +.SH SYNOPSIS +.sp +\fBkcatalogprint\fP [\fIconfig_option\fP] [\fIoptions\fP] +.SH DESCRIPTION +.sp +The program prints zone catalog stored in a catalog database. +.SS Config options +.INDENT 0.0 +.TP +\fB\-c\fP, \fB\-\-config\fP \fIfile\fP +Use a textual configuration file (default is \fB/usr/local/etc/knot/knot.conf\fP). +.TP +\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP +Use a binary configuration database directory (default is \fB/usr/local/var/lib/knot/confdb\fP). +The default configuration database, if exists, has a preference to the default +configuration file. +.TP +\fB\-D\fP, \fB\-\-dir\fP \fIpath\fP +Use specified catalog database path and default configuration. +.UNINDENT +.SS Options +.INDENT 0.0 +.TP +\fB\-a\fP, \fB\-\-catalog\fP +Filter the output by catalog zone name. +.TP +\fB\-m\fP, \fB\-\-member\fP +Filter the output by member zone name. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.UNINDENT +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH SEE ALSO +.sp +\fBknotd(8)\fP, \fBknot.conf(5)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/kcatalogprint.8in b/doc/man/kcatalogprint.8in deleted file mode 100644 index da964d8..0000000 --- a/doc/man/kcatalogprint.8in +++ /dev/null @@ -1,80 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KCATALOGPRINT" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -kcatalogprint \- Knot DNS catalog print utility -.SH SYNOPSIS -.sp -\fBkcatalogprint\fP [\fIconfig_option\fP] [\fIoptions\fP] -.SH DESCRIPTION -.sp -The program prints zone catalog stored in a catalog database. -.SS Config options -.INDENT 0.0 -.TP -\fB\-c\fP, \fB\-\-config\fP \fIfile\fP -Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP). -.TP -\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP -Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP). -The default configuration database, if exists, has a preference to the default -configuration file. -.TP -\fB\-D\fP, \fB\-\-dir\fP \fIpath\fP -Use specified catalog database path and default configuration. -.UNINDENT -.SS Options -.INDENT 0.0 -.TP -\fB\-a\fP, \fB\-\-catalog\fP -Filter the output by catalog zone name. -.TP -\fB\-m\fP, \fB\-\-member\fP -Filter the output by member zone name. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print the program help. -.TP -\fB\-V\fP, \fB\-\-version\fP -Print the program version. -.UNINDENT -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH SEE ALSO -.sp -\fBknotd(8)\fP, \fBknot.conf(5)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/kdig.1 b/doc/man/kdig.1 new file mode 100644 index 0000000..207c8c8 --- /dev/null +++ b/doc/man/kdig.1 @@ -0,0 +1,465 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KDIG" "1" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +kdig \- Advanced DNS lookup utility +.SH SYNOPSIS +.sp +\fBkdig\fP [\fIcommon\-settings\fP] [\fIquery\fP [\fIsettings\fP]]... +.sp +\fBkdig\fP \fB\-h\fP +.SH DESCRIPTION +.sp +This utility sends one or more DNS queries to a nameserver. Each query can have +individual \fIsettings\fP, or it can be specified globally via \fIcommon\-settings\fP, +which must precede \fIquery\fP specification. +.SS Parameters +.INDENT 0.0 +.TP +.B \fIquery\fP +\fIname\fP | \fB\-q\fP \fIname\fP | \fB\-x\fP \fIaddress\fP | \fB\-G\fP \fItapfile\fP +.TP +.B \fIcommon\-settings\fP, \fIsettings\fP +[\fIquery_class\fP] [\fIquery_type\fP] [\fB@\fP\fIserver\fP]... [\fIoptions\fP] +.TP +.B \fIname\fP +Is a domain name that is to be looked up. +.TP +.B \fIserver\fP +Is a domain name or an IPv4 or IPv6 address of the nameserver to send a query +to. An additional port can be specified using address:port ([address]:port +for IPv6 address), address@port, or address#port notation. A value which begins +with \(aq/\(aq character is considered an absolute UNIX socket path. If no server is +specified, the servers from \fB/etc/resolv.conf\fP are used. +.UNINDENT +.sp +If no arguments are provided, \fBkdig\fP sends NS query for the root +zone. +.SS Query classes +.sp +A \fIquery_class\fP can be either a DNS class name (IN, CH) or generic class +specification \fBCLASS\fP\fIXXXXX\fP where \fIXXXXX\fP is a corresponding decimal +class number. The default query class is IN. +.SS Query types +.sp +A \fIquery_type\fP can be either a DNS resource record type +(A, AAAA, NS, SOA, DNSKEY, ANY, etc.) or one of the following: +.INDENT 0.0 +.TP +\fBTYPE\fP\fIXXXXX\fP +Generic query type specification where \fIXXXXX\fP is a corresponding decimal +type number. +.TP +\fBAXFR\fP +Full zone transfer request. +.TP +\fBIXFR=\fP\fIserial\fP +Incremental zone transfer request for specified SOA serial number +(i.e. all zone updates since the specified zone version are to be returned). +.TP +\fBNOTIFY=\fP\fIserial\fP +Notify message with a SOA serial hint specified. +.TP +\fBNOTIFY\fP +Notify message with a SOA serial hint unspecified. +.UNINDENT +.sp +The default query type is A. +.SS Options +.INDENT 0.0 +.TP +\fB\-4\fP +Use the IPv4 protocol only. +.TP +\fB\-6\fP +Use the IPv6 protocol only. +.TP +\fB\-b\fP \fIaddress\fP +Set the source IP address of the query to \fIaddress\fP\&. The address must be a +valid address for local interface or :: or 0.0.0.0. An optional port +can be specified in the same format as the \fIserver\fP value. +.TP +\fB\-c\fP \fIclass\fP +An explicit \fIquery_class\fP specification. See possible values above. +.TP +\fB\-d\fP +Enable debug messages. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-k\fP \fIkeyfile\fP +Use the TSIG key stored in a file \fIkeyfile\fP to authenticate the request. The +file must contain the key in the same format as accepted by the +\fB\-y\fP option. +.TP +\fB\-p\fP \fIport\fP +Set the nameserver port number or service name to send a query to. The default +port is 53. +.TP +\fB\-q\fP \fIname\fP +Set the query name. An explicit variant of \fIname\fP specification. If no \fIname\fP +is provided, empty question section is set. +.TP +\fB\-t\fP \fItype\fP +An explicit \fIquery_type\fP specification. See possible values above. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.TP +\fB\-x\fP \fIaddress\fP +Send a reverse (PTR) query for IPv4 or IPv6 \fIaddress\fP\&. The correct name, class +and type is set automatically. +.TP +\fB\-y\fP [\fIalg\fP:]\fIname\fP:\fIkey\fP +Use the TSIG key named \fIname\fP to authenticate the request. The \fIalg\fP +part specifies the algorithm (the default is hmac\-sha256) and \fIkey\fP specifies +the shared secret encoded in Base64. +.TP +\fB\-E\fP \fItapfile\fP +Export a dnstap trace of the query and response messages received to the +file \fItapfile\fP\&. +.TP +\fB\-G\fP \fItapfile\fP +Generate message output from a previously saved dnstap file \fItapfile\fP\&. +.TP +\fB+\fP[\fBno\fP]\fBmultiline\fP +Wrap long records to more lines and improve human readability. +.TP +\fB+\fP[\fBno\fP]\fBshort\fP +Show record data only. +.TP +\fB+\fP[\fBno\fP]\fBgeneric\fP +Use the generic representation format when printing resource record types +and data. +.TP +\fB+\fP[\fBno\fP]\fBcrypto\fP +Display the DNSSEC keys and signatures values in base64, instead of omitting them. +.TP +\fB+\fP[\fBno\fP]\fBaaflag\fP +Set the AA flag. +.TP +\fB+\fP[\fBno\fP]\fBtcflag\fP +Set the TC flag. +.TP +\fB+\fP[\fBno\fP]\fBrdflag\fP +Set the RD flag. +.TP +\fB+\fP[\fBno\fP]\fBrecurse\fP +Same as \fB+\fP[\fBno\fP]\fBrdflag\fP +.TP +\fB+\fP[\fBno\fP]\fBraflag\fP +Set the RA flag. +.TP +\fB+\fP[\fBno\fP]\fBzflag\fP +Set the zero flag bit. +.TP +\fB+\fP[\fBno\fP]\fBadflag\fP +Set the AD flag. +.TP +\fB+\fP[\fBno\fP]\fBcdflag\fP +Set the CD flag. +.TP +\fB+\fP[\fBno\fP]\fBdnssec\fP +Set the DO flag. +.TP +\fB+\fP[\fBno\fP]\fBall\fP +Show all packet sections. +.TP +\fB+\fP[\fBno\fP]\fBqr\fP +Show the query packet. +.TP +\fB+\fP[\fBno\fP]\fBheader\fP +Show the packet header. +.TP +\fB+\fP[\fBno\fP]\fBcomments\fP +Show commented section names. +.TP +\fB+\fP[\fBno\fP]\fBopt\fP +Show the EDNS pseudosection. +.TP +\fB+\fP[\fBno\fP]\fBopttext\fP +Try to show unknown EDNS options as text. +.TP +\fB+\fP[\fBno\fP]\fBoptpresent\fP +Show EDNS in presentation format according to the specification in version +\fI\%draft\-peltan\-edns\-presentation\-format\-01\fP\&. +.TP +\fB+\fP[\fBno\fP]\fBquestion\fP +Show the question section. +.TP +\fB+\fP[\fBno\fP]\fBanswer\fP +Show the answer section. +.TP +\fB+\fP[\fBno\fP]\fBauthority\fP +Show the authority section. +.TP +\fB+\fP[\fBno\fP]\fBadditional\fP +Show the additional section. +.TP +\fB+\fP[\fBno\fP]\fBtsig\fP +Show the TSIG pseudosection. +.TP +\fB+\fP[\fBno\fP]\fBstats\fP +Show trailing packet statistics. +.TP +\fB+\fP[\fBno\fP]\fBclass\fP +Show the DNS class. +.TP +\fB+\fP[\fBno\fP]\fBttl\fP +Show the TTL value. +.TP +\fB+\fP[\fBno\fP]\fBtcp\fP +Use the TCP protocol (default is UDP for standard query and TCP for AXFR/IXFR). +.TP +\fB+\fP[\fBno\fP]\fBfastopen\fP +Use TCP Fast Open. +.TP +\fB+\fP[\fBno\fP]\fBignore\fP +Don\(aqt use TCP automatically if a truncated reply is received. +.TP +\fB+\fP[\fBno\fP]\fBkeepopen\fP +Keep TCP connection open for the following query if it has the same connection +configuration. This applies to +tcp, +tls, and +https operations. The connection +is considered in the context of a single kdig call only. +.TP +\fB+\fP[\fBno\fP]\fBtls\fP +Use TLS with the Opportunistic privacy profile (\fI\%RFC 7858#section\-4.1\fP). +.TP +\fB+\fP[\fBno\fP]\fBtls\-ca\fP[=\fIFILE\fP] +Use TLS with a certificate validation. Certification authority certificates +are loaded from the specified PEM file (default is system certificate storage +if no argument is provided). +Can be specified multiple times. If the +tls\-hostname option is not provided, +the name of the target server (if specified) is used for strict authentication. +.TP +\fB+\fP[\fBno\fP]\fBtls\-pin\fP=\fIBASE64\fP +Use TLS with the Out\-of\-Band key\-pinned privacy profile (\fI\%RFC 7858#section\-4.2\fP). +The PIN must be a Base64 encoded SHA\-256 hash of the X.509 SubjectPublicKeyInfo. +Can be specified multiple times. +.TP +\fB+\fP[\fBno\fP]\fBtls\-hostname\fP=\fISTR\fP +Use TLS with a remote server hostname check. +.TP +\fB+\fP[\fBno\fP]\fBtls\-sni\fP=\fISTR\fP +Use TLS with a Server Name Indication. +.TP +\fB+\fP[\fBno\fP]\fBtls\-keyfile\fP=\fIFILE\fP +Use TLS with a client keyfile. +.TP +\fB+\fP[\fBno\fP]\fBtls\-certfile\fP=\fIFILE\fP +Use TLS with a client certfile. +.TP +\fB+\fP[\fBno\fP]\fBtls\-ocsp\-stapling\fP[=\fIH\fP] +Use TLS with a valid stapled OCSP response for the server certificate +(%u or specify hours). OCSP responses older than the specified period are +considered invalid. +.TP +\fB+\fP[\fBno\fP]\fBhttps\fP[=\fIURL\fP] +Use HTTPS (DNS\-over\-HTTPS) in wire format (\fI\%RFC 1035#section\-4.2.1\fP). +It is also possible to specify URL=[authority][/path] where request +will be sent to. Any leading scheme and authority indicator (i.e. //) are ignored. +Authority might also be specified as the \fIserver\fP (using the parameter \fI@\fP). +If \fIpath\fP is specified and \fIauthority\fP is missing, then the \fIserver\fP +is used as authority together with the specified \fIpath\fP\&. +Library \fIlibnghttp2\fP is required. +.TP +\fB+\fP[\fBno\fP]\fBhttps\-get\fP +Use HTTPS with HTTP/GET method instead of the default HTTP/POST method. +Library \fIlibnghttp2\fP is required. +.TP +\fB+\fP[\fBno\fP]\fBquic\fP +Use QUIC (DNS\-over\-QUIC). +.TP +\fB+\fP[\fBno\fP]\fBnsid\fP +Request the nameserver identifier (NSID). +.TP +\fB+\fP[\fBno\fP]\fBbufsize\fP=\fIB\fP +Set EDNS buffer size in bytes (default is 1232 bytes). +.TP +\fB+\fP[\fBno\fP]\fBpadding\fP[=\fIB\fP] +Use EDNS(0) padding option to pad queries, optionally to a specific +size. The default is to pad queries with a sensible amount when using ++tls, and not to pad at all when queries are sent without TLS. With +no argument (i.e., just +padding) pad every query with a sensible +amount regardless of the use of TLS. With +nopadding, never pad. +.TP +\fB+\fP[\fBno\fP]\fBalignment\fP[=\fIB\fP] +Align the query to B\-byte\-block message using the EDNS(0) padding option +(default is no or 128 if no argument is specified). +.TP +\fB+\fP[\fBno\fP]\fBsubnet\fP=\fISUBN\fP +Set EDNS(0) client subnet SUBN=addr/prefix. +.TP +\fB+\fP[\fBno\fP]\fBedns\fP[=\fIN\fP] +Use EDNS version (default is 0). EDNS(0) is enabled by default. +.TP +\fB+\fP[\fBno\fP]\fBtimeout\fP=\fIT\fP +Set the wait\-for\-reply interval in seconds (default is 5 seconds). This timeout +applies to each query attempt. Zero value or \fInotimeout\fP is interpreted as +infinity. +.TP +\fB+\fP[\fBno\fP]\fBretry\fP=\fIN\fP +Set the number (>=0) of UDP retries (default is 2). This doesn\(aqt apply to +AXFR/IXFR. +.TP +\fB+\fP[\fBno\fP]\fBexpire\fP +Sets the EXPIRE EDNS option. +.TP +\fB+\fP[\fBno\fP]\fBcookie\fP[=\fIHEX\fP] +Attach EDNS(0) cookie to the query. +.TP +\fB+\fP[\fBno\fP]\fBbadcookie\fP +Repeat a query with the correct cookie. +.TP +\fB+\fP[\fBno\fP]\fBednsopt\fP[=\fICODE\fP[:\fIHEX\fP]] +Send custom EDNS option. The \fICODE\fP is EDNS option code in decimal, \fIHEX\fP +is an optional hex encoded string to use as EDNS option value. This argument +can be used multiple times. +noednsopt clears all EDNS options specified by ++ednsopt. +.TP +\fB+\fP[\fBno\fP]\fBproxy\fP=\fISRC_ADDR\fP[#\fISRC_PORT\fP]\-\fIDST_ADDR\fP[#\fIDST_PORT\fP] +Add PROXYv2 header with the specified source and destination addresses to the query. +The default source port is 0 and destination port 53. +.TP +\fB+\fP[\fBno\fP]\fBjson\fP +Use JSON for output encoding (RFC 8427). +.TP +\fB+noidn\fP +Disable the IDN transformation to ASCII and vice versa. IDN support depends +on libidn2 availability during project building! If used in \fIcommon\-settings\fP, +all IDN transformations are disabled. If used in the individual query \fIsettings\fP, +transformation from ASCII is disabled on output for the particular query. Note +that IDN transformation does not preserve domain name letter case. +.UNINDENT +.SH NOTES +.sp +Options \fB\-k\fP and \fB\-y\fP can not be used simultaneously. +.sp +Dnssec\-keygen keyfile format is not supported. Use \fBkeymgr(8)\fP instead. +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH EXAMPLES +.INDENT 0.0 +.IP 1. 3 +Get A records for example.com: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ kdig example.com A +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 2. 3 +Perform AXFR for zone example.com from the server 192.0.2.1: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ kdig example.com \-t AXFR @192.0.2.1 +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 3. 3 +Get A records for example.com from 192.0.2.1 and reverse lookup for address +2001:DB8::1 from 192.0.2.2. Both using the TCP protocol: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ kdig +tcp example.com \-t A @192.0.2.1 \-x 2001:DB8::1 @192.0.2.2 +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 4. 3 +Get SOA record for example.com, use TLS, use system certificates, check +for specified hostname, check for certificate pin, and print additional +debug info: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ kdig \-d @185.49.141.38 +tls\-ca +tls\-host=getdnsapi.net \e + +tls\-pin=foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9S= soa example.com +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 5. 3 +DNS over HTTPS examples (various DoH implementations): +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ kdig @1.1.1.1 +https example.com. +$ kdig @193.17.47.1 +https=/doh example.com. +$ kdig @8.8.4.4 +https +https\-get example.com. +$ kdig @8.8.8.8 +https +tls\-hostname=dns.google +fastopen example.com. +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 6. 3 +More queries share one DoT connection: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ kdig @1.1.1.1 +tls +keepopen abc.example.com A mail.example.com AAAA +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.SH FILES +.sp +\fB/etc/resolv.conf\fP +.SH SEE ALSO +.sp +\fBkhost(1)\fP, \fBknsupdate(1)\fP, \fBkeymgr(8)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/kdig.1in b/doc/man/kdig.1in deleted file mode 100644 index 99745c9..0000000 --- a/doc/man/kdig.1in +++ /dev/null @@ -1,464 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KDIG" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -kdig \- Advanced DNS lookup utility -.SH SYNOPSIS -.sp -\fBkdig\fP [\fIcommon\-settings\fP] [\fIquery\fP [\fIsettings\fP]]... -.sp -\fBkdig\fP \fB\-h\fP -.SH DESCRIPTION -.sp -This utility sends one or more DNS queries to a nameserver. Each query can have -individual \fIsettings\fP, or it can be specified globally via \fIcommon\-settings\fP, -which must precede \fIquery\fP specification. -.SS Parameters -.INDENT 0.0 -.TP -\fIquery\fP -\fIname\fP | \fB\-q\fP \fIname\fP | \fB\-x\fP \fIaddress\fP | \fB\-G\fP \fItapfile\fP -.TP -\fIcommon\-settings\fP, \fIsettings\fP -[\fIquery_class\fP] [\fIquery_type\fP] [\fB@\fP\fIserver\fP]... [\fIoptions\fP] -.TP -\fIname\fP -Is a domain name that is to be looked up. -.TP -\fIserver\fP -Is a domain name or an IPv4 or IPv6 address of the nameserver to send a query -to. An additional port can be specified using address:port ([address]:port -for IPv6 address), address@port, or address#port notation. A value which begins -with \(aq/\(aq character is considered an absolute UNIX socket path. If no server is -specified, the servers from \fB/etc/resolv.conf\fP are used. -.UNINDENT -.sp -If no arguments are provided, \fBkdig\fP sends NS query for the root -zone. -.SS Query classes -.sp -A \fIquery_class\fP can be either a DNS class name (IN, CH) or generic class -specification \fBCLASS\fP\fIXXXXX\fP where \fIXXXXX\fP is a corresponding decimal -class number. The default query class is IN. -.SS Query types -.sp -A \fIquery_type\fP can be either a DNS resource record type -(A, AAAA, NS, SOA, DNSKEY, ANY, etc.) or one of the following: -.INDENT 0.0 -.TP -\fBTYPE\fP\fIXXXXX\fP -Generic query type specification where \fIXXXXX\fP is a corresponding decimal -type number. -.TP -\fBAXFR\fP -Full zone transfer request. -.TP -\fBIXFR=\fP\fIserial\fP -Incremental zone transfer request for specified SOA serial number -(i.e. all zone updates since the specified zone version are to be returned). -.TP -\fBNOTIFY=\fP\fIserial\fP -Notify message with a SOA serial hint specified. -.TP -\fBNOTIFY\fP -Notify message with a SOA serial hint unspecified. -.UNINDENT -.sp -The default query type is A. -.SS Options -.INDENT 0.0 -.TP -\fB\-4\fP -Use the IPv4 protocol only. -.TP -\fB\-6\fP -Use the IPv6 protocol only. -.TP -\fB\-b\fP \fIaddress\fP -Set the source IP address of the query to \fIaddress\fP\&. The address must be a -valid address for local interface or :: or 0.0.0.0. An optional port -can be specified in the same format as the \fIserver\fP value. -.TP -\fB\-c\fP \fIclass\fP -An explicit \fIquery_class\fP specification. See possible values above. -.TP -\fB\-d\fP -Enable debug messages. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print the program help. -.TP -\fB\-k\fP \fIkeyfile\fP -Use the TSIG key stored in a file \fIkeyfile\fP to authenticate the request. The -file must contain the key in the same format as accepted by the -\fB\-y\fP option. -.TP -\fB\-p\fP \fIport\fP -Set the nameserver port number or service name to send a query to. The default -port is 53. -.TP -\fB\-q\fP \fIname\fP -Set the query name. An explicit variant of \fIname\fP specification. If no \fIname\fP -is provided, empty question section is set. -.TP -\fB\-t\fP \fItype\fP -An explicit \fIquery_type\fP specification. See possible values above. -.TP -\fB\-V\fP, \fB\-\-version\fP -Print the program version. -.TP -\fB\-x\fP \fIaddress\fP -Send a reverse (PTR) query for IPv4 or IPv6 \fIaddress\fP\&. The correct name, class -and type is set automatically. -.TP -\fB\-y\fP [\fIalg\fP:]\fIname\fP:\fIkey\fP -Use the TSIG key named \fIname\fP to authenticate the request. The \fIalg\fP -part specifies the algorithm (the default is hmac\-sha256) and \fIkey\fP specifies -the shared secret encoded in Base64. -.TP -\fB\-E\fP \fItapfile\fP -Export a dnstap trace of the query and response messages received to the -file \fItapfile\fP\&. -.TP -\fB\-G\fP \fItapfile\fP -Generate message output from a previously saved dnstap file \fItapfile\fP\&. -.TP -\fB+\fP[\fBno\fP]\fBmultiline\fP -Wrap long records to more lines and improve human readability. -.TP -\fB+\fP[\fBno\fP]\fBshort\fP -Show record data only. -.TP -\fB+\fP[\fBno\fP]\fBgeneric\fP -Use the generic representation format when printing resource record types -and data. -.TP -\fB+\fP[\fBno\fP]\fBcrypto\fP -Display the DNSSEC keys and signatures values in base64, instead of omitting them. -.TP -\fB+\fP[\fBno\fP]\fBaaflag\fP -Set the AA flag. -.TP -\fB+\fP[\fBno\fP]\fBtcflag\fP -Set the TC flag. -.TP -\fB+\fP[\fBno\fP]\fBrdflag\fP -Set the RD flag. -.TP -\fB+\fP[\fBno\fP]\fBrecurse\fP -Same as \fB+\fP[\fBno\fP]\fBrdflag\fP -.TP -\fB+\fP[\fBno\fP]\fBraflag\fP -Set the RA flag. -.TP -\fB+\fP[\fBno\fP]\fBzflag\fP -Set the zero flag bit. -.TP -\fB+\fP[\fBno\fP]\fBadflag\fP -Set the AD flag. -.TP -\fB+\fP[\fBno\fP]\fBcdflag\fP -Set the CD flag. -.TP -\fB+\fP[\fBno\fP]\fBdnssec\fP -Set the DO flag. -.TP -\fB+\fP[\fBno\fP]\fBall\fP -Show all packet sections. -.TP -\fB+\fP[\fBno\fP]\fBqr\fP -Show the query packet. -.TP -\fB+\fP[\fBno\fP]\fBheader\fP -Show the packet header. -.TP -\fB+\fP[\fBno\fP]\fBcomments\fP -Show commented section names. -.TP -\fB+\fP[\fBno\fP]\fBopt\fP -Show the EDNS pseudosection. -.TP -\fB+\fP[\fBno\fP]\fBopttext\fP -Try to show unknown EDNS options as text. -.TP -\fB+\fP[\fBno\fP]\fBoptpresent\fP -Show EDNS in presentation format according to the specification in version -\fI\%draft\-peltan\-edns\-presentation\-format\-01\fP\&. -.TP -\fB+\fP[\fBno\fP]\fBquestion\fP -Show the question section. -.TP -\fB+\fP[\fBno\fP]\fBanswer\fP -Show the answer section. -.TP -\fB+\fP[\fBno\fP]\fBauthority\fP -Show the authority section. -.TP -\fB+\fP[\fBno\fP]\fBadditional\fP -Show the additional section. -.TP -\fB+\fP[\fBno\fP]\fBtsig\fP -Show the TSIG pseudosection. -.TP -\fB+\fP[\fBno\fP]\fBstats\fP -Show trailing packet statistics. -.TP -\fB+\fP[\fBno\fP]\fBclass\fP -Show the DNS class. -.TP -\fB+\fP[\fBno\fP]\fBttl\fP -Show the TTL value. -.TP -\fB+\fP[\fBno\fP]\fBtcp\fP -Use the TCP protocol (default is UDP for standard query and TCP for AXFR/IXFR). -.TP -\fB+\fP[\fBno\fP]\fBfastopen\fP -Use TCP Fast Open. -.TP -\fB+\fP[\fBno\fP]\fBignore\fP -Don\(aqt use TCP automatically if a truncated reply is received. -.TP -\fB+\fP[\fBno\fP]\fBkeepopen\fP -Keep TCP connection open for the following query if it has the same connection -configuration. This applies to +tcp, +tls, and +https operations. The connection -is considered in the context of a single kdig call only. -.TP -\fB+\fP[\fBno\fP]\fBtls\fP -Use TLS with the Opportunistic privacy profile (\fI\%RFC 7858#section\-4.1\fP). -.TP -\fB+\fP[\fBno\fP]\fBtls\-ca\fP[=\fIFILE\fP] -Use TLS with a certificate validation. Certification authority certificates -are loaded from the specified PEM file (default is system certificate storage -if no argument is provided). -Can be specified multiple times. If the +tls\-hostname option is not provided, -the name of the target server (if specified) is used for strict authentication. -.TP -\fB+\fP[\fBno\fP]\fBtls\-pin\fP=\fIBASE64\fP -Use TLS with the Out\-of\-Band key\-pinned privacy profile (\fI\%RFC 7858#section\-4.2\fP). -The PIN must be a Base64 encoded SHA\-256 hash of the X.509 SubjectPublicKeyInfo. -Can be specified multiple times. -.TP -\fB+\fP[\fBno\fP]\fBtls\-hostname\fP=\fISTR\fP -Use TLS with a remote server hostname check. -.TP -\fB+\fP[\fBno\fP]\fBtls\-sni\fP=\fISTR\fP -Use TLS with a Server Name Indication. -.TP -\fB+\fP[\fBno\fP]\fBtls\-keyfile\fP=\fIFILE\fP -Use TLS with a client keyfile. -.TP -\fB+\fP[\fBno\fP]\fBtls\-certfile\fP=\fIFILE\fP -Use TLS with a client certfile. -.TP -\fB+\fP[\fBno\fP]\fBtls\-ocsp\-stapling\fP[=\fIH\fP] -Use TLS with a valid stapled OCSP response for the server certificate -(%u or specify hours). OCSP responses older than the specified period are -considered invalid. -.TP -\fB+\fP[\fBno\fP]\fBhttps\fP[=\fIURL\fP] -Use HTTPS (DNS\-over\-HTTPS) in wire format (\fI\%RFC 1035#section\-4.2.1\fP). -It is also possible to specify URL=[authority][/path] where request -will be sent to. Any leading scheme and authority indicator (i.e. //) are ignored. -Authority might also be specified as the \fIserver\fP (using the parameter \fI@\fP). -If \fIpath\fP is specified and \fIauthority\fP is missing, then the \fIserver\fP -is used as authority together with the specified \fIpath\fP\&. -Library \fIlibnghttp2\fP is required. -.TP -\fB+\fP[\fBno\fP]\fBhttps\-get\fP -Use HTTPS with HTTP/GET method instead of the default HTTP/POST method. -Library \fIlibnghttp2\fP is required. -.TP -\fB+\fP[\fBno\fP]\fBquic\fP -Use QUIC (DNS\-over\-QUIC). -.TP -\fB+\fP[\fBno\fP]\fBnsid\fP -Request the nameserver identifier (NSID). -.TP -\fB+\fP[\fBno\fP]\fBbufsize\fP=\fIB\fP -Set EDNS buffer size in bytes (default is 4096 bytes). -.TP -\fB+\fP[\fBno\fP]\fBpadding\fP[=\fIB\fP] -Use EDNS(0) padding option to pad queries, optionally to a specific -size. The default is to pad queries with a sensible amount when using -+tls, and not to pad at all when queries are sent without TLS. With -no argument (i.e., just +padding) pad every query with a sensible -amount regardless of the use of TLS. With +nopadding, never pad. -.TP -\fB+\fP[\fBno\fP]\fBalignment\fP[=\fIB\fP] -Align the query to B\-byte\-block message using the EDNS(0) padding option -(default is no or 128 if no argument is specified). -.TP -\fB+\fP[\fBno\fP]\fBsubnet\fP=\fISUBN\fP -Set EDNS(0) client subnet SUBN=addr/prefix. -.TP -\fB+\fP[\fBno\fP]\fBedns\fP[=\fIN\fP] -Use EDNS version (default is 0). -.TP -\fB+\fP[\fBno\fP]\fBtimeout\fP=\fIT\fP -Set the wait\-for\-reply interval in seconds (default is 5 seconds). This timeout -applies to each query attempt. Zero value or \fInotimeout\fP is interpreted as -infinity. -.TP -\fB+\fP[\fBno\fP]\fBretry\fP=\fIN\fP -Set the number (>=0) of UDP retries (default is 2). This doesn\(aqt apply to -AXFR/IXFR. -.TP -\fB+\fP[\fBno\fP]\fBexpire\fP -Sets the EXPIRE EDNS option. -.TP -\fB+\fP[\fBno\fP]\fBcookie\fP[=\fIHEX\fP] -Attach EDNS(0) cookie to the query. -.TP -\fB+\fP[\fBno\fP]\fBbadcookie\fP -Repeat a query with the correct cookie. -.TP -\fB+\fP[\fBno\fP]\fBednsopt\fP[=\fICODE\fP[:\fIHEX\fP]] -Send custom EDNS option. The \fICODE\fP is EDNS option code in decimal, \fIHEX\fP -is an optional hex encoded string to use as EDNS option value. This argument -can be used multiple times. +noednsopt clears all EDNS options specified by -+ednsopt. -.TP -\fB+\fP[\fBno\fP]\fBproxy\fP=\fISRC_ADDR\fP[#\fISRC_PORT\fP]\-\fIDST_ADDR\fP[#\fIDST_PORT\fP] -Add PROXYv2 header with the specified source and destination addresses to the query. -The default source port is 0 and destination port 53. -.TP -\fB+\fP[\fBno\fP]\fBjson\fP -Use JSON for output encoding (RFC 8427). -.TP -\fB+noidn\fP -Disable the IDN transformation to ASCII and vice versa. IDN support depends -on libidn availability during project building! If used in \fIcommon\-settings\fP, -all IDN transformations are disabled. If used in the individual query \fIsettings\fP, -transformation from ASCII is disabled on output for the particular query. Note -that IDN transformation does not preserve domain name letter case. -.UNINDENT -.SH NOTES -.sp -Options \fB\-k\fP and \fB\-y\fP can not be used simultaneously. -.sp -Dnssec\-keygen keyfile format is not supported. Use \fBkeymgr(8)\fP instead. -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH EXAMPLES -.INDENT 0.0 -.IP 1. 3 -Get A records for example.com: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ kdig example.com A -.ft P -.fi -.UNINDENT -.UNINDENT -.IP 2. 3 -Perform AXFR for zone example.com from the server 192.0.2.1: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ kdig example.com \-t AXFR @192.0.2.1 -.ft P -.fi -.UNINDENT -.UNINDENT -.IP 3. 3 -Get A records for example.com from 192.0.2.1 and reverse lookup for address -2001:DB8::1 from 192.0.2.2. Both using the TCP protocol: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ kdig +tcp example.com \-t A @192.0.2.1 \-x 2001:DB8::1 @192.0.2.2 -.ft P -.fi -.UNINDENT -.UNINDENT -.IP 4. 3 -Get SOA record for example.com, use TLS, use system certificates, check -for specified hostname, check for certificate pin, and print additional -debug info: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ kdig \-d @185.49.141.38 +tls\-ca +tls\-host=getdnsapi.net \e - +tls\-pin=foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9S= soa example.com -.ft P -.fi -.UNINDENT -.UNINDENT -.IP 5. 3 -DNS over HTTPS examples (various DoH implementations): -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ kdig @1.1.1.1 +https example.com. -$ kdig @193.17.47.1 +https=/doh example.com. -$ kdig @8.8.4.4 +https +https\-get example.com. -$ kdig @8.8.8.8 +https +tls\-hostname=dns.google +fastopen example.com. -.ft P -.fi -.UNINDENT -.UNINDENT -.IP 6. 3 -More queries share one DoT connection: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ kdig @1.1.1.1 +tls +keepopen abc.example.com A mail.example.com AAAA -.ft P -.fi -.UNINDENT -.UNINDENT -.UNINDENT -.SH FILES -.sp -\fB/etc/resolv.conf\fP -.SH SEE ALSO -.sp -\fBkhost(1)\fP, \fBknsupdate(1)\fP, \fBkeymgr(8)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/keymgr.8 b/doc/man/keymgr.8 new file mode 100644 index 0000000..a963df3 --- /dev/null +++ b/doc/man/keymgr.8 @@ -0,0 +1,390 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KEYMGR" "8" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +keymgr \- Knot DNS key management utility +.SH SYNOPSIS +.sp +\fBkeymgr\fP [\fIconfig_option\fP] [\fIoptions\fP] \fIzone_name\fP \fIcommand\fP +.sp +\fBkeymgr\fP [\fIconfig_option\fP] [\fIoptions\fP] \fIkeystore_id\fP \fIcommand\fP +.sp +\fBkeymgr\fP [\fIconfig_option\fP] [\-j] \fB\-l\fP +.sp +\fBkeymgr\fP \fB\-t\fP \fIparameter\fP\&... +.SH DESCRIPTION +.sp +The \fBkeymgr\fP utility serves for manual key management in Knot DNS server. +.sp +Functions for DNSSEC keys and KASP (Key And Signature Policy) +management are provided. +.sp +The DNSSEC and KASP configuration is stored in a so called KASP database. +The database is backed by LMDB. +.SS Parameters +.INDENT 0.0 +.TP +.B \fIzone_name\fP +Name of the zone the command is executed for. +.UNINDENT +.SS Config options +.INDENT 0.0 +.TP +\fB\-c\fP, \fB\-\-config\fP \fIfile\fP +Use a textual configuration file (default is \fB/usr/local/etc/knot/knot.conf\fP). +.TP +\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP +Use a binary configuration database directory (default is \fB/usr/local/var/lib/knot/confdb\fP). +The default configuration database, if exists, has a preference to the default +configuration file. +.TP +\fB\-D\fP, \fB\-\-dir\fP \fIpath\fP +Use specified KASP database path and default configuration. +.UNINDENT +.SS Options +.INDENT 0.0 +.TP +\fB\-t\fP, \fB\-\-tsig\fP \fItsig_name\fP [\fItsig_algorithm\fP [\fItsig_bits\fP]] +Generates a TSIG key for the given name. Optionally the key algorithm can +be specified by its \fI\%name\fP (default: hmac\-sha256) and +a bit length of the key (default: optimal length given by algorithm). +The generated TSIG key is only displayed on \fIstdout\fP: +the command does not create a file, nor include the key in a keystore. +.TP +\fB\-e\fP, \fB\-\-extended\fP +Extended output (listing of keys with full description). +.TP +\fB\-j\fP, \fB\-\-json\fP +Print the zones or keys in JSON format. +.TP +\fB\-l\fP, \fB\-\-list\fP +Print the list of zones that have at least one key stored in the configured KASP +database. +.TP +\fB\-x\fP, \fB\-\-mono\fP +Don\(aqt generate colorized output. +.TP +\fB\-X\fP, \fB\-\-color\fP +Force colorized output in the normal mode. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Keymgr runs with the same user privileges as configured for \fI\%knotd\fP\&. +For example, if keymgr is run as \fBroot\fP, but the configured \fI\%user\fP +is \fBknot\fP, it won\(aqt be able to read files (PEM files, KASP database, ...) readable +only by \fBroot\fP\&. +.UNINDENT +.UNINDENT +.SS Commands +.INDENT 0.0 +.TP +\fBlist\fP [\fItimestamp_format\fP] +Prints the list of key IDs and parameters of keys belonging to the zone. +.TP +\fBgenerate\fP [\fIarguments\fP\&...] +Generates new DNSSEC key and stores it in KASP database. Prints the key ID. +This action takes some number of arguments (see below). Values for unspecified arguments are taken +from corresponding policy (if \fI\-c\fP or \fI\-C\fP options used) or from Knot policy defaults. +.TP +\fBimport\-bind\fP \fIBIND_key_file\fP +Imports a BIND\-style key into KASP database (converting it to PEM format). +Takes one argument: path to BIND key file (private or public, but both MUST exist). +.TP +\fBimport\-pub\fP \fIBIND_pubkey_file\fP +Imports a public key into KASP database. This key won\(aqt be rolled over nor used for signing. +Takes one argument: path to BIND public key file. +.TP +\fBimport\-pem\fP \fIPEM_file\fP [\fIarguments\fP\&...] +Imports a DNSSEC key from PEM file. The key parameters (same as for the generate action) need to be +specified (mainly algorithm, timers...) because they are not contained in the PEM format. +.TP +\fBimport\-pkcs11\fP \fIkey_id\fP [\fIarguments\fP\&...] +Imports a DNSSEC key from PKCS #11 storage. The key parameters (same as for the generate action) need to be +specified (mainly algorithm, timers...) because they are not available. In fact, no key +data is imported, only KASP database metadata is created. +.TP +\fBnsec3\-salt\fP [\fInew_salt\fP] +Prints the current NSEC3 salt used for signing. If \fInew_salt\fP is specified, the salt is overwritten. +The salt is printed and expected in hexadecimal, or dash if empty. +.TP +\fBlocal\-serial\fP [\fInew_serial\fP] +Print SOA serial stored in KASP database when using on\-secondary DNSSEC signing. +If \fInew_serial\fP is specified, the serial is overwritten. After updating the serial, expire the zone +(\fBzone\-purge +expire +zonefile +journal\fP) if the server is running, or remove corresponding zone file +and journal contents if the server is stopped. +.TP +\fBmaster\-serial\fP [\fInew_serial\fP] +Print SOA serial of the remote master stored in KASP database when using on\-secondary DNSSEC signing. +If \fInew_serial\fP is specified, the serial is overwritten (not recommended). +.TP +\fBset\fP \fIkey_spec\fP [\fIarguments\fP\&...] +Changes a timing argument (or ksk/zsk) of an existing key to a new value. \fIKey_spec\fP is either the +key tag or a prefix of the key ID, with an optional \fI[id=|keytag=]\fP prefix; \fIarguments\fP +are like for \fBgenerate\fP, but just the related ones. +.TP +\fBds\fP [\fIkey_spec\fP] +Generate DS record (all digest algorithms together) for specified key. \fIKey_spec\fP +is like for \fBset\fP, if unspecified, all KSKs are used. +.TP +\fBdnskey\fP [\fIkey_spec\fP] +Generate DNSKEY record for specified key. \fIKey_spec\fP +is like for \fBds\fP, if unspecified, all KSKs are used. +.TP +\fBdelete\fP \fIkey_spec\fP +Remove the specified key from zone. If the key was not shared, it is also deleted from keystore. +.TP +\fBshare\fP \fIkey_ID\fP \fIzone_from\fP +Import a key (specified by full key ID) from another zone as shared. After this, the key is +owned by both zones equally. +.UNINDENT +.SS Keystore commands +.INDENT 0.0 +.TP +\fBkeystore\-test\fP +Conduct some tests on the specified keystore. For each algorithm, key generation, +import, removal, and use (signing and verification) are tested. +Use a configured \fIkeystore_id\fP or \fB\-\fP for the default. +.TP +\fBkeystore\-bench\fP [\fInum_threads\fP] +Conduct a signing benchmark on the specified keystore. +Random blocks of data are signed by the selected number of threads +(default is 1) in a loop, and the average number of signing operations per +second for each algorithm is returned. +Use a configured \fIkeystore_id\fP or \fB\-\fP for the default. +.UNINDENT +.SS Commands related to Offline KSK feature +.INDENT 0.0 +.TP +\fBpregenerate\fP [\fItimestamp\-from\fP] \fItimestamp\-to\fP +Pre\-generate ZSKs for use with offline KSK, for the specified period starting from now or specified time. +This function also applies to non\-offline KSK keys. +.TP +\fBshow\-offline\fP [\fItimestamp\-from\fP] [\fItimestamp\-to\fP] +Print pre\-generated offline key\-related records for specified time interval. If \fItimestamp_to\fP +is omitted, it will be to infinity. If \fItimestamp\-from\fP is omitted, it will start from the +beginning. +.TP +\fBdel\-offline\fP \fItimestamp\-from\fP \fItimestamp\-to\fP +Delete pre\-generated offline key\-related records in specified time interval. +.TP +\fBdel\-all\-old\fP +Delete old keys that are in state \(aqremoved\(aq. This function also applies to +non\-offline KSK keys. +.TP +\fBgenerate\-ksr\fP [\fItimestamp\-from\fP] \fItimestamp\-to\fP +Print to stdout KeySigningRequest based on pre\-generated ZSKs for specified time period. +If \fItimestamp\-from\fP is omitted, timestamp of the last offline records set is used +or now if no records available. +.TP +\fBsign\-ksr\fP \fIksr_file\fP +Read KeySigningRequest from a text file, sign it using local keyset and print SignedKeyResponse to stdout. +.TP +\fBvalidate\-skr\fP \fIskr_file\fP +Read SignedKeyResponse from a text file and validate the RRSIGs in it if not corrupt. +.TP +\fBimport\-skr\fP \fIskr_file\fP +Read SignedKeyResponse from a text file and import the signatures for later use in zone. If some +signatures have already been imported, they will be deleted for the period from beginning of the SKR +to infinity. +.UNINDENT +.SS Generate arguments +.sp +Arguments are separated by space, each of them is in format \(aqname=value\(aq. +.INDENT 0.0 +.TP +\fBalgorithm\fP +Either an algorithm number (e.g. 14) or \fI\%algorithm name\fP +without dashes (e.g. ECDSAP384SHA384). +.TP +\fBsize\fP +Key length in bits. +.TP +\fBksk\fP +If set to \fByes\fP, the key will be used for signing DNSKEY rrset. The generated key will also +have the Secure Entry Point flag set to 1. +.TP +\fBzsk\fP +If set to \fByes\fP, the key will be used for signing zone (except DNSKEY rrset). This flag can +be set concurrently with the \fBksk\fP flag. +.TP +\fBsep\fP +Overrides the standard setting of the Secure Entry Point flag. +.UNINDENT +.sp +The following arguments are timestamps of key lifetime (see \fI\%DNSSEC key states\fP): +.INDENT 0.0 +.TP +\fBpre_active\fP +Key started to be used for signing, not published (only for algorithm rollover). +.TP +\fBpublish\fP +Key published. +.TP +\fBready\fP +Key is waiting for submission (only for KSK). +.TP +\fBactive\fP +Key used for signing. +.TP +\fBretire_active\fP +Key still used for signing, but another key is active (only for KSK or algorithm rollover). +.TP +\fBretire\fP +Key still published, but no longer used for signing. +.TP +\fBpost_active\fP +Key no longer published, but still used for signing (only for algorithm rollover). +.TP +\fBrevoke\fP +Key revoked according to \fI\%RFC 5011\fP trust anchor roll\-over. +.TP +\fBremove\fP +Key deleted. +.UNINDENT +.SS Timestamps +.INDENT 0.0 +.TP +.B 0 +Zero timestamp means infinite future. +.TP +.B \fIUNIX_time\fP +Positive number of seconds since 1970 UTC. +.TP +.B \fIYYYYMMDDHHMMSS\fP +Date and time in this format without any punctuation. +.TP +.B \fIrelative_timestamp\fP +A sign character (\fB+\fP, \fB\-\fP), a number, and an optional time unit +(\fBy\fP, \fBmo\fP, \fBd\fP, \fBh\fP, \fBmi\fP, \fBs\fP). The default unit is one second. +E.g. +1mi, \-2mo. +.UNINDENT +.SS Output timestamp formats +.INDENT 0.0 +.TP +.B (none) +The timestamps are printed as UNIX timestamp. +.TP +\fBhuman\fP +The timestamps are printed relatively to now using time units (e.g. \-2y5mo, +1h13s). +.TP +\fBiso\fP +The timestamps are printed in the ISO8601 format (e.g. 2016\-12\-31T23:59:00). +.UNINDENT +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH EXAMPLES +.INDENT 0.0 +.IP 1. 3 +Generate new TSIG key: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ keymgr \-t my_name hmac\-sha384 +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 2. 3 +Generate new DNSSEC key: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ keymgr example.com. generate algorithm=ECDSAP256SHA256 size=256 \e + ksk=true created=1488034625 publish=20170223205611 retire=+10mo remove=+1y +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 3. 3 +Import a DNSSEC key from BIND: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ keymgr example.com. import\-bind ~/bind/Kharbinge4d5.+007+63089.key +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 4. 3 +Configure key timing: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ keymgr example.com. set 4208 active=+2mi retire=+4mi remove=+5mi +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 5. 3 +Share a KSK from another zone: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ keymgr example.com. share e687cf927029e9db7184d2ece6d663f5d1e5b0e9 another\-zone.com. +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.SH SEE ALSO +.sp +\fI\%RFC 6781\fP \- DNSSEC Operational Practices. +\fI\%RFC 7583\fP \- DNSSEC Key Rollover Timing Considerations. +.sp +\fBknot.conf(5)\fP, +\fBknotc(8)\fP, +\fBknotd(8)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/keymgr.8in b/doc/man/keymgr.8in deleted file mode 100644 index 020d854..0000000 --- a/doc/man/keymgr.8in +++ /dev/null @@ -1,389 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KEYMGR" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -keymgr \- Knot DNS key management utility -.SH SYNOPSIS -.sp -\fBkeymgr\fP [\fIconfig_option\fP] [\fIoptions\fP] \fIzone_name\fP \fIcommand\fP -.sp -\fBkeymgr\fP [\fIconfig_option\fP] [\fIoptions\fP] \fIkeystore_id\fP \fIcommand\fP -.sp -\fBkeymgr\fP [\fIconfig_option\fP] [\-j] \fB\-l\fP -.sp -\fBkeymgr\fP \fB\-t\fP \fIparameter\fP\&... -.SH DESCRIPTION -.sp -The \fBkeymgr\fP utility serves for manual key management in Knot DNS server. -.sp -Functions for DNSSEC keys and KASP (Key And Signature Policy) -management are provided. -.sp -The DNSSEC and KASP configuration is stored in a so called KASP database. -The database is backed by LMDB. -.SS Parameters -.INDENT 0.0 -.TP -\fIzone_name\fP -Name of the zone the command is executed for. -.UNINDENT -.SS Config options -.INDENT 0.0 -.TP -\fB\-c\fP, \fB\-\-config\fP \fIfile\fP -Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP). -.TP -\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP -Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP). -The default configuration database, if exists, has a preference to the default -configuration file. -.TP -\fB\-D\fP, \fB\-\-dir\fP \fIpath\fP -Use specified KASP database path and default configuration. -.UNINDENT -.SS Options -.INDENT 0.0 -.TP -\fB\-t\fP, \fB\-\-tsig\fP \fItsig_name\fP [\fItsig_algorithm\fP [\fItsig_bits\fP]] -Generates a TSIG key for the given name. Optionally the key algorithm can -be specified by its \fI\%name\fP (default: hmac\-sha256) and -a bit length of the key (default: optimal length given by algorithm). -The generated TSIG key is only displayed on \fIstdout\fP: -the command does not create a file, nor include the key in a keystore. -.TP -\fB\-e\fP, \fB\-\-extended\fP -Extended output (listing of keys with full description). -.TP -\fB\-j\fP, \fB\-\-json\fP -Print the zones or keys in JSON format. -.TP -\fB\-l\fP, \fB\-\-list\fP -Print the list of zones that have at least one key stored in the configured KASP -database. -.TP -\fB\-x\fP, \fB\-\-mono\fP -Don\(aqt generate colorized output. -.TP -\fB\-X\fP, \fB\-\-color\fP -Force colorized output in the normal mode. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print the program help. -.TP -\fB\-V\fP, \fB\-\-version\fP -Print the program version. -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Keymgr runs with the same user privileges as configured for \fI\%knotd\fP\&. -For example, if keymgr is run as \fBroot\fP, but the configured \fI\%user\fP -is \fBknot\fP, it won\(aqt be able to read files (PEM files, KASP database, ...) readable -only by \fBroot\fP\&. -.UNINDENT -.UNINDENT -.SS Commands -.INDENT 0.0 -.TP -\fBlist\fP [\fItimestamp_format\fP] -Prints the list of key IDs and parameters of keys belonging to the zone. -.TP -\fBgenerate\fP [\fIarguments\fP\&...] -Generates new DNSSEC key and stores it in KASP database. Prints the key ID. -This action takes some number of arguments (see below). Values for unspecified arguments are taken -from corresponding policy (if \fI\-c\fP or \fI\-C\fP options used) or from Knot policy defaults. -.TP -\fBimport\-bind\fP \fIBIND_key_file\fP -Imports a BIND\-style key into KASP database (converting it to PEM format). -Takes one argument: path to BIND key file (private or public, but both MUST exist). -.TP -\fBimport\-pub\fP \fIBIND_pubkey_file\fP -Imports a public key into KASP database. This key won\(aqt be rolled over nor used for signing. -Takes one argument: path to BIND public key file. -.TP -\fBimport\-pem\fP \fIPEM_file\fP [\fIarguments\fP\&...] -Imports a DNSSEC key from PEM file. The key parameters (same as for the generate action) need to be -specified (mainly algorithm, timers...) because they are not contained in the PEM format. -.TP -\fBimport\-pkcs11\fP \fIkey_id\fP [\fIarguments\fP\&...] -Imports a DNSSEC key from PKCS #11 storage. The key parameters (same as for the generate action) need to be -specified (mainly algorithm, timers...) because they are not available. In fact, no key -data is imported, only KASP database metadata is created. -.TP -\fBnsec3\-salt\fP [\fInew_salt\fP] -Prints the current NSEC3 salt used for signing. If \fInew_salt\fP is specified, the salt is overwritten. -The salt is printed and expected in hexadecimal, or dash if empty. -.TP -\fBlocal\-serial\fP [\fInew_serial\fP] -Print SOA serial stored in KASP database when using on\-secondary DNSSEC signing. -If \fInew_serial\fP is specified, the serial is overwritten. After updating the serial, expire the zone -(\fBzone\-purge +expire +zonefile +journal\fP) if the server is running, or remove corresponding zone file -and journal contents if the server is stopped. -.TP -\fBmaster\-serial\fP [\fInew_serial\fP] -Print SOA serial of the remote master stored in KASP database when using on\-secondary DNSSEC signing. -If \fInew_serial\fP is specified, the serial is overwritten (not recommended). -.TP -\fBset\fP \fIkey_spec\fP [\fIarguments\fP\&...] -Changes a timing argument (or ksk/zsk) of an existing key to a new value. \fIKey_spec\fP is either the -key tag or a prefix of the key ID, with an optional \fI[id=|keytag=]\fP prefix; \fIarguments\fP -are like for \fBgenerate\fP, but just the related ones. -.TP -\fBds\fP [\fIkey_spec\fP] -Generate DS record (all digest algorithms together) for specified key. \fIKey_spec\fP -is like for \fBset\fP, if unspecified, all KSKs are used. -.TP -\fBdnskey\fP [\fIkey_spec\fP] -Generate DNSKEY record for specified key. \fIKey_spec\fP -is like for \fBds\fP, if unspecified, all KSKs are used. -.TP -\fBdelete\fP \fIkey_spec\fP -Remove the specified key from zone. If the key was not shared, it is also deleted from keystore. -.TP -\fBshare\fP \fIkey_ID\fP \fIzone_from\fP -Import a key (specified by full key ID) from another zone as shared. After this, the key is -owned by both zones equally. -.UNINDENT -.SS Keystore commands -.INDENT 0.0 -.TP -\fBkeystore\-test\fP -Conduct some tests on the specified keystore. For each algorithm, key generation, -import, removal, and use (signing and verification) are tested. -Use a configured \fIkeystore_id\fP or \fB\-\fP for the default. -.TP -\fBkeystore\-bench\fP [\fInum_threads\fP] -Conduct a signing benchmark on the specified keystore. -Random blocks of data are signed by the selected number of threads -(default is 1) in a loop, and the average number of signing operations per -second for each algorithm is returned. -Use a configured \fIkeystore_id\fP or \fB\-\fP for the default. -.UNINDENT -.SS Commands related to Offline KSK feature -.INDENT 0.0 -.TP -\fBpregenerate\fP [\fItimestamp\-from\fP] \fItimestamp\-to\fP -Pre\-generate ZSKs for use with offline KSK, for the specified period starting from now or specified time. -This function also applies to non\-offline KSK keys. -.TP -\fBshow\-offline\fP [\fItimestamp\-from\fP] [\fItimestamp\-to\fP] -Print pre\-generated offline key\-related records for specified time interval. If \fItimestamp_to\fP -is omitted, it will be to infinity. If \fItimestamp\-from\fP is omitted, it will start from the -beginning. -.TP -\fBdel\-offline\fP \fItimestamp\-from\fP \fItimestamp\-to\fP -Delete pre\-generated offline key\-related records in specified time interval. -.TP -\fBdel\-all\-old\fP -Delete old keys that are in state \(aqremoved\(aq. This function also applies to -non\-offline KSK keys. -.TP -\fBgenerate\-ksr\fP [\fItimestamp\-from\fP] \fItimestamp\-to\fP -Print to stdout KeySigningRequest based on pre\-generated ZSKs for specified time period. -If \fItimestamp\-from\fP is omitted, timestamp of the last offline records set is used -or now if no records available. -.TP -\fBsign\-ksr\fP \fIksr_file\fP -Read KeySigningRequest from a text file, sign it using local keyset and print SignedKeyResponse to stdout. -.TP -\fBvalidate\-skr\fP \fIskr_file\fP -Read SignedKeyResponse from a text file and validate the RRSIGs in it if not corrupt. -.TP -\fBimport\-skr\fP \fIskr_file\fP -Read SignedKeyResponse from a text file and import the signatures for later use in zone. If some -signatures have already been imported, they will be deleted for the period from beginning of the SKR -to infinity. -.UNINDENT -.SS Generate arguments -.sp -Arguments are separated by space, each of them is in format \(aqname=value\(aq. -.INDENT 0.0 -.TP -\fBalgorithm\fP -Either an algorithm number (e.g. 14) or \fI\%algorithm name\fP -without dashes (e.g. ECDSAP384SHA384). -.TP -\fBsize\fP -Key length in bits. -.TP -\fBksk\fP -If set to \fByes\fP, the key will be used for signing DNSKEY rrset. The generated key will also -have the Secure Entry Point flag set to 1. -.TP -\fBzsk\fP -If set to \fByes\fP, the key will be used for signing zone (except DNSKEY rrset). This flag can -be set concurrently with the \fBksk\fP flag. -.TP -\fBsep\fP -Overrides the standard setting of the Secure Entry Point flag. -.UNINDENT -.sp -The following arguments are timestamps of key lifetime (see \fI\%DNSSEC key states\fP): -.INDENT 0.0 -.TP -\fBpre_active\fP -Key started to be used for signing, not published (only for algorithm rollover). -.TP -\fBpublish\fP -Key published. -.TP -\fBready\fP -Key is waiting for submission (only for KSK). -.TP -\fBactive\fP -Key used for signing. -.TP -\fBretire_active\fP -Key still used for signing, but another key is active (only for KSK or algorithm rollover). -.TP -\fBretire\fP -Key still published, but no longer used for signing. -.TP -\fBpost_active\fP -Key no longer published, but still used for signing (only for algorithm rollover). -.TP -\fBrevoke\fP -Key revoked according to \fI\%RFC 5011\fP trust anchor roll\-over. -.TP -\fBremove\fP -Key deleted. -.UNINDENT -.SS Timestamps -.INDENT 0.0 -.TP -0 -Zero timestamp means infinite future. -.TP -\fIUNIX_time\fP -Positive number of seconds since 1970 UTC. -.TP -\fIYYYYMMDDHHMMSS\fP -Date and time in this format without any punctuation. -.TP -\fIrelative_timestamp\fP -A sign character (\fB+\fP, \fB\-\fP), a number, and an optional time unit -(\fBy\fP, \fBmo\fP, \fBd\fP, \fBh\fP, \fBmi\fP, \fBs\fP). The default unit is one second. -E.g. +1mi, \-2mo. -.UNINDENT -.SS Output timestamp formats -.INDENT 0.0 -.TP -(none) -The timestamps are printed as UNIX timestamp. -.TP -\fBhuman\fP -The timestamps are printed relatively to now using time units (e.g. \-2y5mo, +1h13s). -.TP -\fBiso\fP -The timestamps are printed in the ISO8601 format (e.g. 2016\-12\-31T23:59:00). -.UNINDENT -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH EXAMPLES -.INDENT 0.0 -.IP 1. 3 -Generate new TSIG key: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ keymgr \-t my_name hmac\-sha384 -.ft P -.fi -.UNINDENT -.UNINDENT -.IP 2. 3 -Generate new DNSSEC key: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ keymgr example.com. generate algorithm=ECDSAP256SHA256 size=256 \e - ksk=true created=1488034625 publish=20170223205611 retire=+10mo remove=+1y -.ft P -.fi -.UNINDENT -.UNINDENT -.IP 3. 3 -Import a DNSSEC key from BIND: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ keymgr example.com. import\-bind ~/bind/Kharbinge4d5.+007+63089.key -.ft P -.fi -.UNINDENT -.UNINDENT -.IP 4. 3 -Configure key timing: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ keymgr example.com. set 4208 active=+2mi retire=+4mi remove=+5mi -.ft P -.fi -.UNINDENT -.UNINDENT -.IP 5. 3 -Share a KSK from another zone: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ keymgr example.com. share e687cf927029e9db7184d2ece6d663f5d1e5b0e9 another\-zone.com. -.ft P -.fi -.UNINDENT -.UNINDENT -.UNINDENT -.SH SEE ALSO -.sp -\fI\%RFC 6781\fP \- DNSSEC Operational Practices. -\fI\%RFC 7583\fP \- DNSSEC Key Rollover Timing Considerations. -.sp -\fBknot.conf(5)\fP, -\fBknotc(8)\fP, -\fBknotd(8)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/khost.1 b/doc/man/khost.1 new file mode 100644 index 0000000..4cae5e9 --- /dev/null +++ b/doc/man/khost.1 @@ -0,0 +1,157 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KHOST" "1" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +khost \- Simple DNS lookup utility +.SH SYNOPSIS +.sp +\fBkhost\fP [\fIoptions\fP] \fIname\fP [\fIserver\fP] +.SH DESCRIPTION +.sp +This utility sends a DNS query for the \fIname\fP to the \fIserver\fP and prints a reply +in more user\-readable form. For more advanced DNS queries use \fI\%kdig\fP +instead. +.SS Parameters +.INDENT 0.0 +.TP +.B \fIname\fP +Is a domain name that is to be looked up. If the \fIname\fP is IPv4 or IPv6 +address the PTR query type is used. +.TP +.B \fIserver\fP +Is a name or an address of the nameserver to send a query to. The address +can be specified using [address]:port notation. If no server is specified, +the servers from \fB/etc/resolv.conf\fP are used. +.UNINDENT +.sp +If no arguments are provided, \fBkhost\fP prints a short help. +.SS Options +.INDENT 0.0 +.TP +\fB\-4\fP +Use the IPv4 protocol only. +.TP +\fB\-6\fP +Use the IPv6 protocol only. +.TP +\fB\-a\fP +Send ANY query with verbose mode. +.TP +\fB\-d\fP +Enable debug messages. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-r\fP +Disable recursion. +.TP +\fB\-T\fP +Use the TCP protocol. +.TP +\fB\-v\fP +Enable verbose output. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.TP +\fB\-w\fP +Wait forever for the reply. +.TP +\fB\-c\fP \fIclass\fP +Set the query class (e.g. CH, CLASS4). The default class is IN. +.TP +\fB\-t\fP \fItype\fP +Set the query type (e.g. NS, IXFR=12345, TYPE65535). The default is to send 3 +queries (A, AAAA and MX). +.TP +\fB\-R\fP \fIretries\fP +The number (>=0) of UDP retries to query a nameserver. The default is 1. +.TP +\fB\-W\fP \fIwait\fP +The time to wait for a reply in seconds. This timeout applies to each query +try. The default is 2 seconds. +.UNINDENT +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH EXAMPLES +.INDENT 0.0 +.IP 1. 3 +Get the A, AAAA and MX records for example.com: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ khost example.com +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 2. 3 +Get the reverse record for address 192.0.2.1: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ khost 192.0.2.1 +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 3. 3 +Perform a verbose zone transfer for zone example.com: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ khost \-t AXFR \-v example.com +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.SH FILES +.sp +\fB/etc/resolv.conf\fP +.SH SEE ALSO +.sp +\fBkdig(1)\fP, \fBknsupdate(1)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/khost.1in b/doc/man/khost.1in deleted file mode 100644 index 292f080..0000000 --- a/doc/man/khost.1in +++ /dev/null @@ -1,156 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KHOST" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -khost \- Simple DNS lookup utility -.SH SYNOPSIS -.sp -\fBkhost\fP [\fIoptions\fP] \fIname\fP [\fIserver\fP] -.SH DESCRIPTION -.sp -This utility sends a DNS query for the \fIname\fP to the \fIserver\fP and prints a reply -in more user\-readable form. For more advanced DNS queries use \fI\%kdig\fP -instead. -.SS Parameters -.INDENT 0.0 -.TP -\fIname\fP -Is a domain name that is to be looked up. If the \fIname\fP is IPv4 or IPv6 -address the PTR query type is used. -.TP -\fIserver\fP -Is a name or an address of the nameserver to send a query to. The address -can be specified using [address]:port notation. If no server is specified, -the servers from \fB/etc/resolv.conf\fP are used. -.UNINDENT -.sp -If no arguments are provided, \fBkhost\fP prints a short help. -.SS Options -.INDENT 0.0 -.TP -\fB\-4\fP -Use the IPv4 protocol only. -.TP -\fB\-6\fP -Use the IPv6 protocol only. -.TP -\fB\-a\fP -Send ANY query with verbose mode. -.TP -\fB\-d\fP -Enable debug messages. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print the program help. -.TP -\fB\-r\fP -Disable recursion. -.TP -\fB\-T\fP -Use the TCP protocol. -.TP -\fB\-v\fP -Enable verbose output. -.TP -\fB\-V\fP, \fB\-\-version\fP -Print the program version. -.TP -\fB\-w\fP -Wait forever for the reply. -.TP -\fB\-c\fP \fIclass\fP -Set the query class (e.g. CH, CLASS4). The default class is IN. -.TP -\fB\-t\fP \fItype\fP -Set the query type (e.g. NS, IXFR=12345, TYPE65535). The default is to send 3 -queries (A, AAAA and MX). -.TP -\fB\-R\fP \fIretries\fP -The number (>=0) of UDP retries to query a nameserver. The default is 1. -.TP -\fB\-W\fP \fIwait\fP -The time to wait for a reply in seconds. This timeout applies to each query -try. The default is 2 seconds. -.UNINDENT -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH EXAMPLES -.INDENT 0.0 -.IP 1. 3 -Get the A, AAAA and MX records for example.com: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ khost example.com -.ft P -.fi -.UNINDENT -.UNINDENT -.IP 2. 3 -Get the reverse record for address 192.0.2.1: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ khost 192.0.2.1 -.ft P -.fi -.UNINDENT -.UNINDENT -.IP 3. 3 -Perform a verbose zone transfer for zone example.com: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ khost \-t AXFR \-v example.com -.ft P -.fi -.UNINDENT -.UNINDENT -.UNINDENT -.SH FILES -.sp -\fB/etc/resolv.conf\fP -.SH SEE ALSO -.sp -\fBkdig(1)\fP, \fBknsupdate(1)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/kjournalprint.8 b/doc/man/kjournalprint.8 new file mode 100644 index 0000000..4c17e36 --- /dev/null +++ b/doc/man/kjournalprint.8 @@ -0,0 +1,118 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KJOURNALPRINT" "8" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +kjournalprint \- Knot DNS journal print utility +.SH SYNOPSIS +.sp +\fBkjournalprint\fP [\fIconfig_option\fP] [\fIoptions\fP] \fIzone_name\fP +.sp +\fBkjournalprint\fP [\fIconfig_option\fP] \fB\-z\fP +.SH DESCRIPTION +.sp +The program prints zone history stored in a journal database. As default, +changes are colored for terminal. +.SS Parameters +.INDENT 0.0 +.TP +.B \fIzone_name\fP +A name of the zone to print the history for. +.UNINDENT +.SS Config options +.INDENT 0.0 +.TP +\fB\-c\fP, \fB\-\-config\fP \fIfile\fP +Use a textual configuration file (default is \fB/usr/local/etc/knot/knot.conf\fP). +.TP +\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP +Use a binary configuration database directory (default is \fB/usr/local/var/lib/knot/confdb\fP). +The default configuration database, if exists, has a preference to the default +configuration file. +.TP +\fB\-D\fP, \fB\-\-dir\fP \fIpath\fP +Use specified journal database path and default configuration. +.UNINDENT +.SS Options +.INDENT 0.0 +.TP +\fB\-z\fP, \fB\-\-zone\-list\fP +Instead of reading the journal, display the list of zones in the DB. +.TP +\fB\-l\fP, \fB\-\-limit\fP \fIlimit\fP +Limits the number of displayed changes. +.TP +\fB\-s\fP, \fB\-\-serial\fP \fIsoa\fP +Start at a specific SOA serial. +.TP +\fB\-H\fP, \fB\-\-check\fP +Enable additional journal semantic checks during printing. +.TP +\fB\-d\fP, \fB\-\-debug\fP +Debug mode brief output. +.TP +\fB\-x\fP, \fB\-\-mono\fP +Don\(aqt generate colorized output. +.TP +\fB\-X\fP, \fB\-\-color\fP +Force colorized output. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.UNINDENT +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH EXAMPLES +.sp +Last (most recent) 5 changes without colors: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ kjournalprint \-nl 5 /var/lib/knot/journal example.com. +.ft P +.fi +.UNINDENT +.UNINDENT +.SH SEE ALSO +.sp +\fBknotd(8)\fP, \fBknot.conf(5)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/kjournalprint.8in b/doc/man/kjournalprint.8in deleted file mode 100644 index 2a1303a..0000000 --- a/doc/man/kjournalprint.8in +++ /dev/null @@ -1,120 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KJOURNALPRINT" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -kjournalprint \- Knot DNS journal print utility -.SH SYNOPSIS -.sp -\fBkjournalprint\fP [\fIconfig_option\fP] [\fIoptions\fP] \fIzone_name\fP -.sp -\fBkjournalprint\fP [\fIconfig_option\fP] \fB\-z\fP -.SH DESCRIPTION -.sp -The program prints zone history stored in a journal database. As default, -changes are colored for terminal. -.SS Parameters -.INDENT 0.0 -.TP -\fIzone_name\fP -A name of the zone to print the history for. -.UNINDENT -.SS Config options -.INDENT 0.0 -.TP -\fB\-c\fP, \fB\-\-config\fP \fIfile\fP -Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP). -.TP -\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP -Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP). -The default configuration database, if exists, has a preference to the default -configuration file. -.TP -\fB\-D\fP, \fB\-\-dir\fP \fIpath\fP -Use specified journal database path and default configuration. -.UNINDENT -.SS Options -.INDENT 0.0 -.TP -\fB\-z\fP, \fB\-\-zone\-list\fP -Instead of reading the journal, display the list of zones in the DB. -.TP -\fB\-l\fP, \fB\-\-limit\fP \fIlimit\fP -Limits the number of displayed changes. -.TP -\fB\-s\fP, \fB\-\-serial\fP \fIsoa\fP -Start at a specific SOA serial. -.TP -\fB\-H\fP, \fB\-\-check\fP -Enable additional journal semantic checks during printing. -.TP -\fB\-d\fP, \fB\-\-debug\fP -Debug mode brief output. -.TP -\fB\-x\fP, \fB\-\-mono\fP -Don\(aqt generate colorized output. -.TP -\fB\-n\fP, \fB\-\-no\-color\fP -An alias for \fB\-x\fP\&. Use of this option is deprecated, it will be removed in the future. -.TP -\fB\-X\fP, \fB\-\-color\fP -Force colorized output. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print the program help. -.TP -\fB\-V\fP, \fB\-\-version\fP -Print the program version. -.UNINDENT -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH EXAMPLES -.sp -Last (most recent) 5 changes without colors: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ kjournalprint \-nl 5 /var/lib/knot/journal example.com. -.ft P -.fi -.UNINDENT -.UNINDENT -.SH SEE ALSO -.sp -\fBknotd(8)\fP, \fBknot.conf(5)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/knot.conf.5 b/doc/man/knot.conf.5 new file mode 100644 index 0000000..dc6fe4a --- /dev/null +++ b/doc/man/knot.conf.5 @@ -0,0 +1,2957 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KNOT.CONF" "5" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +knot.conf \- Knot DNS configuration file +.SH DESCRIPTION +.sp +Configuration files for Knot DNS use simplified YAML format. Simplified means +that not all of the features are supported. +.sp +For the description of configuration items, we have to declare a meaning of +the following symbols: +.INDENT 0.0 +.IP \(bu 2 +\fBINT\fP – Integer +.IP \(bu 2 +\fBSTR\fP – Textual string +.IP \(bu 2 +\fBHEXSTR\fP – Hexadecimal string (with \fB0x\fP prefix) +.IP \(bu 2 +\fBBOOL\fP – Boolean value (\fBon\fP/\fBoff\fP or \fBtrue\fP/\fBfalse\fP) +.IP \(bu 2 +\fBTIME\fP – Number of seconds, an integer with a possible time multiplier suffix +(\fBs\fP ~ 1, \fBm\fP ~ 60, \fBh\fP ~ 3600, \fBd\fP ~ 24 * 3600, \fBw\fP ~ 7 * 24 * 3600, +\fBM\fP ~ 30 * 24 * 3600, \fBy\fP ~ 365 * 24 * 3600) +.IP \(bu 2 +\fBSIZE\fP – Number of bytes, an integer with a possible size multiplier suffix +(\fBB\fP ~ 1, \fBK\fP ~ 1024, \fBM\fP ~ 1024^2 or \fBG\fP ~ 1024^3) +.IP \(bu 2 +\fBBASE64\fP – Base64 encoded string +.IP \(bu 2 +\fBADDR\fP – IPv4 or IPv6 address +.IP \(bu 2 +\fBDNAME\fP – Domain name +.IP \(bu 2 +\fB\&...\fP – Multi\-valued item, order of the values is preserved +.IP \(bu 2 +\fB[\fP \fB]\fP – Optional value +.IP \(bu 2 +\fB|\fP – Choice +.UNINDENT +.sp +The configuration consists of several fixed sections and optional module +sections. There are 17 fixed sections (\fBmodule\fP, \fBserver\fP, \fBxdp\fP, \fBcontrol\fP, +\fBlog\fP, \fBstatistics\fP, \fBdatabase\fP, \fBkeystore\fP, \fBkey\fP, \fBremote\fP, +\fBremotes\fP, \fBacl\fP, \fBsubmission\fP, \fBdnskey\-sync\fP, \fBpolicy\fP, \fBtemplate\fP, +\fBzone\fP). +Module sections are prefixed with the \fBmod\-\fP prefix (e.g. \fBmod\-stats\fP). +.sp +Most of the sections (e.g. \fBzone\fP) are sequences of settings blocks. Each +settings block begins with a unique identifier, which can be used as a reference +from other sections (such an identifier must be defined in advance). +.sp +A multi\-valued item can be specified either as a YAML sequence: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +address: [10.0.0.1, 10.0.0.2] +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +or as more single\-valued items each on an extra line: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +address: 10.0.0.1 +address: 10.0.0.2 +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +If an item value contains spaces or other special characters, it is necessary +to enclose such a value within double quotes \fB\(dq\fP \fB\(dq\fP\&. +.sp +If not specified otherwise, an item representing a file or a directory path may +be defined either as an absolute path (starting with \fB/\fP), or a path relative +to the same directory as the default value of the item. +.SH COMMENTS +.sp +A comment begins with a \fB#\fP character and is ignored during processing. +Also each configuration section or sequence block allows a permanent +comment using the \fBcomment\fP item which is stored in the server beside the +configuration. +.SH INCLUDING CONFIGURATION +.sp +Another configuration file or files, matching a pattern, can be included at +the top level in the current file. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +include: STR +.ft P +.fi +.UNINDENT +.UNINDENT +.SS include +.sp +A path or a matching pattern specifying one or more files that are included +at the place of the include option position in the configuration. +If the path is not absolute, then it is considered to be relative to the +current file. The pattern can be an arbitrary string meeting POSIX \fIglob\fP +requirements, e.g. dir/*.conf. Matching files are processed in sorted order. +.sp +\fIDefault:\fP not set +.SH CLEARING CONFIGURATION SECTIONS +.sp +It\(aqs possible to clear specified configuration sections at given phases +of the configuration parsing. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +clear: STR +.ft P +.fi +.UNINDENT +.UNINDENT +.SS clear +.sp +A matching pattern specifying configuration sections that are cleared when +this item is parsed. This allows overriding of existing configuration +in the configuration database when including a configuration file or +ensures that some configuration wasn\(aqt specified in previous includes. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +For the pattern matching the POSIX function +\fI\%fnmatch()\fP +is used. On Linux, the GNU extension +\fI\%FNM_EXTMATCH\fP +is enabled, which allows extended pattern matching. +Examples: +.INDENT 0.0 +.IP \(bu 2 +\fBclear: zone\fP – Clears the \fBzone\fP section. +.IP \(bu 2 +\fBclear: mod\-*\fP – Clears all module sections. +.IP \(bu 2 +\fBclear: \(dq[!z]*\(dq\fP – Clears all sections not beginning with letter \fBz\fP\&. +.IP \(bu 2 +\fBclear: !(zone)\fP – (GNU only) Clears all sections except the \fBzone\fP one. +.IP \(bu 2 +\fBclear: @(zone|template)\fP – (GNU only) Clears the \fBzone\fP and \fBtemplate\fP sections. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP not set +.SH MODULE SECTION +.sp +Dynamic modules loading configuration. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +If configured with non\-empty \fB\-\-with\-moduledir=path\fP parameter, all +shared modules in this directory will be automatically loaded. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +module: + \- id: STR + file: STR +.ft P +.fi +.UNINDENT +.UNINDENT +.SS id +.sp +A module identifier in the form of the \fBmod\-\fP prefix and module name suffix. +.SS file +.sp +A path to a shared library file with the module implementation. +.sp +\fBWARNING:\fP +.INDENT 0.0 +.INDENT 3.5 +If the path is not absolute, the library is searched in the set of +system directories. See \fBman dlopen\fP for more details. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB${libdir}/knot/modules\-${version}\fP/module_name.so +(or \fB${path}\fP/module_name.so if configured with \fB\-\-with\-moduledir=path\fP) +.SH SERVER SECTION +.sp +General options related to the server. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +server: + identity: [STR] + version: [STR] + nsid: [STR|HEXSTR] + rundir: STR + user: STR[:STR] + pidfile: STR + udp\-workers: INT + tcp\-workers: INT + background\-workers: INT + async\-start: BOOL + tcp\-idle\-timeout: TIME + tcp\-io\-timeout: INT + tcp\-remote\-io\-timeout: INT + tcp\-max\-clients: INT + tcp\-reuseport: BOOL + tcp\-fastopen: BOOL + quic\-max\-clients: INT + quic\-outbuf\-max\-size: SIZE + quic\-idle\-close\-timeout: TIME + remote\-pool\-limit: INT + remote\-pool\-timeout: TIME + remote\-retry\-delay: INT + socket\-affinity: BOOL + udp\-max\-payload: SIZE + udp\-max\-payload\-ipv4: SIZE + udp\-max\-payload\-ipv6: SIZE + key\-file: STR + cert\-file: STR + edns\-client\-subnet: BOOL + answer\-rotation: BOOL + automatic\-acl: BOOL + proxy\-allowlist: ADDR[/INT] | ADDR\-ADDR ... + dbus\-event: none | running | zone\-updated | ksk\-submission | dnssec\-invalid ... + dbus\-init\-delay: TIME + listen: ADDR[@INT] | STR ... + listen\-quic: ADDR[@INT] ... + listen\-tls: ADDR[@INT] ... +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBCAUTION:\fP +.INDENT 0.0 +.INDENT 3.5 +When you change configuration parameters dynamically or via configuration file +reload, some parameters in the Server section require restarting the Knot server +so that the changes take effect. See below for the details. +.UNINDENT +.UNINDENT +.SS identity +.sp +An identity of the server returned in the response to the query for TXT +record \fBid.server.\fP or \fBhostname.bind.\fP in the CHAOS class (\fI\%RFC 4892\fP). +Set to an empty value to disable. +.sp +\fIDefault:\fP FQDN hostname +.SS version +.sp +A version of the server software returned in the response to the query +for TXT record \fBversion.server.\fP or \fBversion.bind.\fP in the CHAOS +class (\fI\%RFC 4892\fP). Set to an empty value to disable. +.sp +\fIDefault:\fP server version +.SS nsid +.sp +A DNS name server identifier (\fI\%RFC 5001\fP). Set to an empty value to disable. +.sp +\fIDefault:\fP FQDN hostname at the moment of the daemon start +.SS rundir +.sp +A path for storing run\-time data (PID file, unix sockets, etc.). A non\-absolute +path is relative to the \fI\%knotd\fP startup directory. +.sp +Depending on the usage of this parameter, its change may require restart of the Knot +server to take effect. +.sp +\fIDefault:\fP \fB${localstatedir}/run/knot\fP (configured with \fB\-\-with\-rundir=path\fP) +.SS user +.sp +A system user with an optional system group (\fBuser:group\fP) under which the +server is run after starting and binding to interfaces. Linux capabilities +are employed if supported. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fBroot:root\fP +.SS pidfile +.sp +A PID file \fI\%location\fP\&. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fI\%rundir\fP\fB/knot.pid\fP +.SS udp\-workers +.sp +A number of UDP workers (threads) used to process incoming queries +over UDP. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP equal to the number of online CPUs +.SS tcp\-workers +.sp +A number of TCP workers (threads) used to process incoming queries +over TCP. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP equal to the number of online CPUs, default value is at least 10 +.SS background\-workers +.sp +A number of workers (threads) used to execute background operations (zone +loading, zone updates, etc.). +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP equal to the number of online CPUs, default value is at most 10 +.SS async\-start +.sp +If enabled, server doesn\(aqt wait for the zones to be loaded and starts +responding immediately with SERVFAIL answers until the zone loads. +.sp +\fIDefault:\fP \fBoff\fP +.SS tcp\-idle\-timeout +.sp +Maximum idle time (in seconds) between requests on an inbound TCP connection. +It means if there is no activity on an inbound TCP connection during this limit, +the connection is closed by the server. +.sp +\fIMinimum:\fP \fB1\fP +.sp +\fIDefault:\fP \fB10\fP +.SS tcp\-io\-timeout +.sp +Maximum time (in milliseconds) to receive or send one DNS message over an inbound +TCP connection. It means this limit applies to normal DNS queries and replies, +incoming DDNS, and \fBoutgoing zone transfers\fP\&. The timeout is measured since some +data is already available for processing. +Set to 0 for infinity. +.sp +\fIDefault:\fP \fB500\fP (milliseconds) +.sp +\fBCAUTION:\fP +.INDENT 0.0 +.INDENT 3.5 +In order to reduce the risk of Slow Loris attacks, it\(aqs recommended setting +this limit as low as possible on public servers. +.UNINDENT +.UNINDENT +.SS tcp\-remote\-io\-timeout +.sp +Maximum time (in milliseconds) to receive or send one DNS message over an outbound +TCP connection which has already been established to a configured remote server. +It means this limit applies to incoming zone transfers, sending NOTIFY, +DDNS forwarding, and DS check or push. This timeout includes the time needed +for a network round\-trip and for a query processing by the remote. +Set to 0 for infinity. +.sp +\fIDefault:\fP \fB5000\fP (milliseconds) +.SS tcp\-reuseport +.sp +If enabled, each TCP worker listens on its own socket and the OS kernel +socket load balancing is employed using SO_REUSEPORT (or SO_REUSEPORT_LB +on FreeBSD). Due to the lack of one shared socket, the server can offer +higher response rate processing over TCP. However, in the case of +time\-consuming requests (e.g. zone transfers of a TLD zone), enabled reuseport +may result in delayed or not being responded client requests. So it is +advisable to use this option on secondary servers. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fBoff\fP +.SS tcp\-fastopen +.sp +If enabled, use TCP Fast Open for outbound TCP communication (client side): +incoming zone transfers, sending NOTIFY, and DDNS forwarding. This mode simplifies +TCP handshake and can result in better networking performance. TCP Fast Open +for inbound TCP communication (server side) isn\(aqt affected by this +configuration as it\(aqs enabled automatically if supported by OS. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +The TCP Fast Open support must also be enabled on the OS level: +.INDENT 0.0 +.IP \(bu 2 +Linux/macOS: ensure kernel parameter \fBnet.ipv4.tcp_fastopen\fP is \fB2\fP or +\fB3\fP for server side, and \fB1\fP or \fB3\fP for client side. +.IP \(bu 2 +FreeBSD: ensure kernel parameter \fBnet.inet.tcp.fastopen.server_enable\fP +is \fB1\fP for server side, and \fBnet.inet.tcp.fastopen.client_enable\fP is +\fB1\fP for client side. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBoff\fP +.SS quic\-max\-clients +.sp +A maximum number of QUIC clients connected in parallel. +.sp +See also \fI\%quic\fP\&. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIMinimum:\fP \fB128\fP +.sp +\fIDefault:\fP \fB10000\fP (ten thousand) +.SS quic\-outbuf\-max\-size +.sp +Maximum cumulative size of memory used for buffers of unACKed +sent messages. This limit is per one UDP worker. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Set low if little memory is available (together with \fI\%quic\-max\-clients\fP +since QUIC connections are memory\-heavy). Set to high value if outgoing zone +transfers of big zone over QUIC are expected. +.UNINDENT +.UNINDENT +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIMinimum:\fP \fB1M\fP (1 MiB) +.sp +\fIDefault:\fP \fB100M\fP (100 MiB) +.SS quic\-idle\-close\-timeout +.sp +Time in seconds, after which any idle QUIC connection is gracefully closed. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIMinimum:\fP \fB1\fP +.sp +\fIDefault:\fP \fB4\fP +.SS remote\-pool\-limit +.sp +If nonzero, the server will keep up to this number of outgoing TCP connections +open for later use. This is an optimization to avoid frequent opening of +TCP connections to the same remote. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fB0\fP +.SS remote\-pool\-timeout +.sp +The timeout in seconds after which the unused kept\-open outgoing TCP connections +to remote servers are closed. +.sp +\fIDefault:\fP \fB5\fP +.SS remote\-retry\-delay +.sp +When a connection attempt times out to some remote address, this information will be +kept for this specified time (in milliseconds) and other connections to the same address won\(aqt +be attempted. This prevents repetitive waiting for timeout on an unreachable remote. +.sp +\fIDefault:\fP \fB0\fP +.SS socket\-affinity +.sp +If enabled and if SO_REUSEPORT is available on Linux, all configured network +sockets are bound to UDP and TCP workers in order to increase the networking performance. +This mode isn\(aqt recommended for setups where the number of network card queues +is lower than the number of UDP or TCP workers. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fBoff\fP +.SS tcp\-max\-clients +.sp +A maximum number of TCP clients connected in parallel, set this below the file +descriptor limit to avoid resource exhaustion. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +It is advisable to adjust the maximum number of open files per process in your +operating system configuration. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP one half of the file descriptor limit for the server process +.SS udp\-max\-payload +.sp +Maximum EDNS0 UDP payload size default for both IPv4 and IPv6. +.sp +\fIDefault:\fP \fB1232\fP +.SS udp\-max\-payload\-ipv4 +.sp +Maximum EDNS0 UDP payload size for IPv4. +.sp +\fIDefault:\fP \fB1232\fP +.SS udp\-max\-payload\-ipv6 +.sp +Maximum EDNS0 UDP payload size for IPv6. +.sp +\fIDefault:\fP \fB1232\fP +.SS key\-file +.sp +Path to a server key PEM file which is used for DNS over QUIC/TLS communication. +A non\-absolute path of a user specified key file is relative to the +\fB/usr/local/etc/knot\fP directory. +.sp +\fIDefault:\fP auto\-generated key +.SS cert\-file +.sp +Path to a server certificate PEM file which is used for DNS over QUIC/TLS communication. +A non\-absolute path is relative to the \fB/usr/local/etc/knot\fP directory. +.sp +\fIDefault:\fP one\-time in\-memory certificate +.SS edns\-client\-subnet +.sp +Enable or disable EDNS Client Subnet support. If enabled, responses to queries +containing the EDNS Client Subnet option +always contain a valid EDNS Client Subnet option according to \fI\%RFC 7871\fP\&. +.sp +\fIDefault:\fP \fBoff\fP +.SS answer\-rotation +.sp +Enable or disable sorted\-rrset rotation in the answer section of normal replies. +The rotation shift is simply determined by a query ID. +.sp +\fIDefault:\fP \fBoff\fP +.SS automatic\-acl +.sp +If enabled, \fI\%automatic ACL\fP setting of +configured remotes is considered when evaluating authorized operations. +.sp +\fIDefault:\fP \fBoff\fP +.SS proxy\-allowlist +.sp +An ordered list of IP addresses, network subnets, or network ranges +which are allowed as a source address of proxied DNS traffic over UDP. +The supported proxy protocol is +\fI\%haproxy PROXY v2\fP\&. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +TCP is not supported. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP not set +.SS dbus\-event +.sp +Specification of server or zone states which emit a D\-Bus signal on the system +bus. The bus name is \fBcz.nic.knotd\fP, the object path is \fB/cz/nic/knotd\fP, and +the interface name is \fBcz.nic.knotd.events\fP\&. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBnone\fP – No signal is emitted. +.IP \(bu 2 +\fBrunning\fP – There are two possible signals emitted: +.INDENT 2.0 +.IP \(bu 2 +\fBstarted\fP when the server is started and all configured zones (including +catalog zones and their members) are loaded or successfully bootstrapped. +.IP \(bu 2 +\fBstopped\fP when the server shutdown sequence is initiated. +.UNINDENT +.IP \(bu 2 +\fBzone\-updated\fP – The signal \fBzone_updated\fP is emitted when a zone has been updated; +the signal parameters are \fIzone name\fP and \fIzone SOA serial\fP\&. +.IP \(bu 2 +\fBkeys\-updated\fP \- The signal \fBkeys_updated\fP is emitted when a DNSSEC key set +is updated; the signal parameter is \fIzone name\fP\&. +.IP \(bu 2 +\fBksk\-submission\fP – The signal \fBzone_ksk_submission\fP is emitted if there is +a ready KSK present when the zone is signed; the signal parameters are +\fIzone name\fP, \fIKSK keytag\fP, and \fIKSK KASP id\fP\&. +.IP \(bu 2 +\fBdnssec\-invalid\fP – The signal \fBzone_dnssec_invalid\fP is emitted when DNSSEC +validation fails; the signal parameters are \fIzone name\fP, and \fIremaining seconds\fP +until an RRSIG expires. +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This function requires systemd version at least 221 or libdbus. +.UNINDENT +.UNINDENT +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fBnone\fP +.SS dbus\-init\-delay +.sp +Time in seconds which the server waits upon D\-Bus initialization to ensure +the D\-Bus client is ready to receive signals. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIMinimum:\fP \fB0\fP +.sp +\fIDefault:\fP \fB1\fP +.SS listen +.sp +One or more IP addresses where the server listens for incoming queries. +Optional port specification (default is 53) can be appended to each address +using \fB@\fP separator. Use \fB0.0.0.0\fP for all configured IPv4 addresses or +\fB::\fP for all configured IPv6 addresses. Filesystem path can be specified +for listening on local unix SOCK_STREAM socket. Non\-absolute path +(i.e. not starting with \fB/\fP) is relative to \fI\%rundir\fP\&. +Non\-local address binding is automatically enabled if supported by the operating system. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP not set +.SS listen\-quic +.sp +One or more IP addresses (and optionally ports) where the server listens +for incoming queries over QUIC protocol. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP not set +.SS listen\-tls +.sp +One or more IP addresses (and optionally ports) where the server listens +for incoming queries over TLS protocol (DoT). +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP not set +.SH XDP SECTION +.sp +Various options related to XDP listening, especially TCP. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +xdp: + listen: STR[@INT] | ADDR[@INT] ... + udp: BOOL + tcp: BOOL + quic: BOOL + quic\-port: INT + tcp\-max\-clients: INT + tcp\-inbuf\-max\-size: SIZE + tcp\-outbuf\-max\-size: SIZE + tcp\-idle\-close\-timeout: TIME + tcp\-idle\-reset\-timeout: TIME + tcp\-resend\-timeout: TIME + route\-check: BOOL + ring\-size: INT + busypoll\-budget: INT + busypoll\-timeout: INT +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBCAUTION:\fP +.INDENT 0.0 +.INDENT 3.5 +When you change configuration parameters dynamically or via configuration file +reload, some parameters in the XDP section require restarting the Knot server +so that the changes take effect. +.UNINDENT +.UNINDENT +.SS listen +.sp +One or more network device names (e.g. \fBens786f0\fP) on which the \fI\%Mode XDP\fP +is enabled. Alternatively, an IP address can be used instead of a device name, +but the server will still listen on all addresses belonging to the same interface! +Optional port specification (default is 53) can be appended to each device name +or address using \fB@\fP separator. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fBCAUTION:\fP +.INDENT 0.0 +.INDENT 3.5 +If XDP workers only process regular DNS traffic over UDP, it is strongly +recommended to also \fI\%listen\fP on the addresses which are +intended to offer the DNS service, at least to fulfil the DNS requirement for +working TCP. +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Incoming \fI\%DDNS\fP over XDP isn\(aqt supported. +The server always responds with SERVFAIL. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP not set +.SS udp +.sp +If enabled, DNS over UDP is processed with XDP workers. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fBon\fP +.SS tcp +.sp +If enabled, DNS over TCP traffic is processed with XDP workers. +.sp +The TCP stack limitations: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +Congestion control is not implemented. +.IP \(bu 2 +Lost packets that do not contain TCP payload may not be resend. +.IP \(bu 2 +Not optimized for transfers of non\-trivial zones. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fBoff\fP +.SS quic +.sp +If enabled, DNS over QUIC is processed with XDP workers. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fBoff\fP +.SS quic\-port +.sp +DNS over QUIC will listen on the interfaces configured by \fI\%listen\fP, +but on different port, configured by this option. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fB853\fP +.SS tcp\-max\-clients +.sp +A maximum number of TCP clients connected in parallel. +.sp +\fIMinimum:\fP \fB1024\fP +.sp +\fIDefault:\fP \fB1000000\fP (one million) +.SS tcp\-inbuf\-max\-size +.sp +Maximum cumulative size of memory used for buffers of incompletely +received messages. +.sp +\fIMinimum:\fP \fB1M\fP (1 MiB) +.sp +\fIDefault:\fP \fB100M\fP (100 MiB) +.SS tcp\-outbuf\-max\-size +.sp +Maximum cumulative size of memory used for buffers of unACKed +sent messages. +.sp +\fIMinimum:\fP \fB1M\fP (1 MiB) +.sp +\fIDefault:\fP \fB100M\fP (100 MiB) +.SS tcp\-idle\-close\-timeout +.sp +Time in seconds, after which any idle connection is gracefully closed. +.sp +\fIMinimum:\fP \fB1\fP +.sp +\fIDefault:\fP \fB10\fP +.SS tcp\-idle\-reset\-timeout +.sp +Time in seconds, after which any idle connection is forcibly closed. +.sp +\fIMinimum:\fP \fB1\fP +.sp +\fIDefault:\fP \fB20\fP +.SS tcp\-resend\-timeout +.sp +Resend outgoing data packets (with DNS response payload) if not ACKed +before this timeout (in seconds). +.sp +\fIMinimum:\fP \fB1\fP +.sp +\fIDefault:\fP \fB5\fP +.SS route\-check +.sp +If enabled, routing information from the operating system is considered +when processing every incoming DNS packet received over the XDP interface: +.INDENT 0.0 +.IP \(bu 2 +If the outgoing interface of the corresponding DNS response differs from +the incoming one, the packet is processed normally by UDP/TCP workers +(XDP isn\(aqt used). +.IP \(bu 2 +If the destination address is blackholed, unreachable, or prohibited, +the DNS packet is dropped without any response. +.IP \(bu 2 +The destination MAC address and possible VLAN tag for the response are taken +from the routing system. +.UNINDENT +.sp +If disabled, symmetrical routing is applied. It means that the query source +MAC address is used as a response destination MAC address. Possible VLAN tag +is preserved. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This mode requires forwarding enabled on the loopback interface +(\fBsysctl \-w net.ipv4.conf.lo.forwarding=1\fP and \fBsysctl \-w net.ipv6.conf.lo.forwarding=1\fP). +If forwarding is disabled, all incoming DNS packets are dropped! +.sp +Only VLAN 802.1Q is supported. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBoff\fP +.SS ring\-size +.sp +Size of RX, FQ, TX, and CQ rings. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This value should be at least as high as the configured RX size of the +network device in the XDP mode. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB2048\fP +.SS busypoll\-budget +.sp +If set to a positive value, preferred busy polling is enabled with the +specified budget. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Preferred busy polling also requires setting \fBnapi_defer_hard_irqs\fP and +\fBgro_flush_timeout\fP for the appropriate network interface. E.g.: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +echo 2 | sudo tee /sys/class/net//napi_defer_hard_irqs +echo 200000 | sudo tee /sys/class/net//gro_flush_timeout +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +A recommended value is between 8 and 64. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB0\fP (disabled) +.SS busypoll\-timeout +.sp +Timeout in microseconds of preferrred busy polling if enabled by +\fI\%busypoll\-budget\fP\&. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fB20\fP (20 microseconds) +.SH CONTROL SECTION +.sp +Configuration of the server control interface. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +control: + listen: STR + backlog: INT + timeout: TIME +.ft P +.fi +.UNINDENT +.UNINDENT +.SS listen +.sp +A UNIX socket \fI\%path\fP where the server listens for +control commands. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fI\%rundir\fP\fB/knot.sock\fP +.SS backlog +.sp +The control UNIX socket listen backlog size. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fB5\fP +.SS timeout +.sp +Maximum time (in seconds) the control socket operations can take. +Set to 0 for infinity. +.sp +\fIDefault:\fP \fB5\fP +.SH LOG SECTION +.sp +Server can be configured to log to the standard output, standard error +output, syslog (or systemd journal if systemd is enabled) or into an arbitrary +file. +.sp +There are 6 logging severity levels: +.INDENT 0.0 +.IP \(bu 2 +\fBcritical\fP – Non\-recoverable error resulting in server shutdown. +.IP \(bu 2 +\fBerror\fP – Recoverable error, action should be taken. +.IP \(bu 2 +\fBwarning\fP – Warning that might require user action. +.IP \(bu 2 +\fBnotice\fP – Server notice or hint. +.IP \(bu 2 +\fBinfo\fP – Informational message. +.IP \(bu 2 +\fBdebug\fP – Debug or detailed message. +.UNINDENT +.sp +In the case of a missing log section, \fBwarning\fP or more serious messages +will be logged to both standard error output and syslog. The \fBinfo\fP and +\fBnotice\fP messages will be logged to standard output. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +log: + \- target: stdout | stderr | syslog | STR + server: critical | error | warning | notice | info | debug + control: critical | error | warning | notice | info | debug + zone: critical | error | warning | notice | info | debug + quic: critical | error | warning | notice | info | debug + any: critical | error | warning | notice | info | debug +.ft P +.fi +.UNINDENT +.UNINDENT +.SS target +.sp +A logging output. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBstdout\fP – Standard output. +.IP \(bu 2 +\fBstderr\fP – Standard error output. +.IP \(bu 2 +\fBsyslog\fP – Syslog or systemd journal. +.IP \(bu 2 +\fIfile_name\fP – A specific file. +.UNINDENT +.sp +With \fBsyslog\fP target, syslog service is used. However, if Knot DNS has been compiled +with systemd support and operating system has been booted with systemd, systemd journal +is used for logging instead of syslog. +.sp +A \fIfile_name\fP may be specified as an absolute path or a path relative to the +\fI\%knotd\fP startup directory. +.SS server +.sp +Minimum severity level for messages related to general operation of the server to be +logged. +.sp +\fIDefault:\fP not set +.SS control +.sp +Minimum severity level for messages related to server control to be logged. +.sp +\fIDefault:\fP not set +.SS zone +.sp +Minimum severity level for messages related to zones to be logged. +.sp +\fIDefault:\fP not set +.SS quic +.sp +Minimum severity level for messages related to QUIC to be logged. +.sp +\fIDefault:\fP not set +.SS any +.sp +Minimum severity level for all message types, except \fBquic\fP, to be logged. +.sp +\fIDefault:\fP not set +.SH STATISTICS SECTION +.sp +Periodic server statistics dumping. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +statistics: + timer: TIME + file: STR + append: BOOL +.ft P +.fi +.UNINDENT +.UNINDENT +.SS timer +.sp +A period (in seconds) after which all available statistics metrics will by written to the +\fI\%file\fP\&. +.sp +\fIDefault:\fP not set +.SS file +.sp +A file \fI\%path\fP of statistics output in the YAML format. +.sp +\fIDefault:\fP \fI\%rundir\fP\fB/stats.yaml\fP +.SS append +.sp +If enabled, the output will be appended to the \fI\%file\fP +instead of file replacement. +.sp +\fIDefault:\fP \fBoff\fP +.SH DATABASE SECTION +.sp +Configuration of databases for zone contents, DNSSEC metadata, or event timers. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +database: + storage: STR + journal\-db: STR + journal\-db\-mode: robust | asynchronous + journal\-db\-max\-size: SIZE + kasp\-db: STR + kasp\-db\-max\-size: SIZE + timer\-db: STR + timer\-db\-max\-size: SIZE + catalog\-db: str + catalog\-db\-max\-size: SIZE +.ft P +.fi +.UNINDENT +.UNINDENT +.SS storage +.sp +A data directory for storing journal, KASP, and timer databases. A non\-absolute +path is relative to the \fI\%knotd\fP startup directory. +.sp +\fIDefault:\fP \fB${localstatedir}/lib/knot\fP (configured with \fB\-\-with\-storage=path\fP) +.SS journal\-db +.sp +An explicit \fI\%specification\fP of the persistent journal database +directory. +.sp +\fIDefault:\fP \fI\%storage\fP\fB/journal\fP +.SS journal\-db\-mode +.sp +Specifies journal LMDB backend configuration, which influences performance +and durability. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBrobust\fP – The journal database disk synchronization ensures database +durability but is generally slower. +.IP \(bu 2 +\fBasynchronous\fP – The journal database disk synchronization is optimized for +better performance at the expense of lower database durability in the case of +a crash. This mode is recommended on secondary servers with many zones. +.UNINDENT +.sp +\fIDefault:\fP \fBrobust\fP +.SS journal\-db\-max\-size +.sp +The hard limit for the journal database maximum size. There is no cleanup logic +in journal to recover from reaching this limit. Journal simply starts refusing +changes across all zones. Decreasing this value has no effect if it is lower +than the actual database file size. +.sp +It is recommended to limit \fI\%journal\-max\-usage\fP +per\-zone instead of \fI\%journal\-db\-max\-size\fP +in most cases. Please keep this value larger than the sum of all zones\(aq +journal usage limits. See more details regarding +\fI\%journal behaviour\fP\&. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This value also influences server\(aqs usage of virtual memory. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB20G\fP (20 GiB), or \fB512M\fP (512 MiB) for 32\-bit +.SS kasp\-db +.sp +An explicit \fI\%specification\fP of the KASP database directory. +.sp +\fIDefault:\fP \fI\%storage\fP\fB/keys\fP +.SS kasp\-db\-max\-size +.sp +The hard limit for the KASP database maximum size. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This value also influences server\(aqs usage of virtual memory. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB500M\fP (500 MiB) +.SS timer\-db +.sp +An explicit \fI\%specification\fP of the persistent timer +database directory. +.sp +\fIDefault:\fP \fI\%storage\fP\fB/timers\fP +.SS timer\-db\-max\-size +.sp +The hard limit for the timer database maximum size. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This value also influences server\(aqs usage of virtual memory. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB100M\fP (100 MiB) +.SS catalog\-db +.sp +An explicit \fI\%specification\fP of the zone catalog +database directory. Only useful if \fI\%Catalog zones\fP are enabled. +.sp +\fIDefault:\fP \fI\%storage\fP\fB/catalog\fP +.SS catalog\-db\-max\-size +.sp +The hard limit for the catalog database maximum size. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This value also influences server\(aqs usage of virtual memory. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB20G\fP (20 GiB), or \fB512M\fP (512 MiB) for 32\-bit +.SH KEYSTORE SECTION +.sp +DNSSEC keystore configuration. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +keystore: + \- id: STR + backend: pem | pkcs11 + config: STR + key\-label: BOOL +.ft P +.fi +.UNINDENT +.UNINDENT +.SS id +.sp +A keystore identifier. +.SS backend +.sp +A key storage backend type. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBpem\fP – PEM files. +.IP \(bu 2 +\fBpkcs11\fP – PKCS #11 storage. +.UNINDENT +.sp +\fIDefault:\fP \fBpem\fP +.SS config +.sp +A backend specific configuration. A directory with PEM files (the path can +be specified as a relative path to \fI\%kasp\-db\fP) or +a configuration string for PKCS #11 storage (\fI \fP). +The PKCS #11 URI Scheme is defined in \fI\%RFC 7512\fP\&. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Example configuration string for PKCS #11: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\(dqpkcs11:token=knot;pin\-value=1234 /usr/lib64/pkcs11/libsofthsm2.so\(dq +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fI\%kasp\-db\fP\fB/keys\fP +.SS key\-label +.sp +If enabled in combination with the PKCS #11 \fI\%backend\fP, generated keys +are labeled in the form \fB KSK|ZSK\fP\&. +.sp +\fIDefault:\fP \fBoff\fP +.SH KEY SECTION +.sp +Shared TSIG keys used to authenticate communication with the server. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +key: + \- id: DNAME + algorithm: hmac\-md5 | hmac\-sha1 | hmac\-sha224 | hmac\-sha256 | hmac\-sha384 | hmac\-sha512 + secret: BASE64 +.ft P +.fi +.UNINDENT +.UNINDENT +.SS id +.sp +A key name identifier. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This value MUST be exactly the same as the name of the TSIG key on the +opposite primary/secondary server(s). +.UNINDENT +.UNINDENT +.SS algorithm +.sp +A TSIG key algorithm. See +\fI\%TSIG Algorithm Numbers\fP\&. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBhmac\-md5\fP +.IP \(bu 2 +\fBhmac\-sha1\fP +.IP \(bu 2 +\fBhmac\-sha224\fP +.IP \(bu 2 +\fBhmac\-sha256\fP +.IP \(bu 2 +\fBhmac\-sha384\fP +.IP \(bu 2 +\fBhmac\-sha512\fP +.UNINDENT +.sp +\fIDefault:\fP not set +.SS secret +.sp +Shared key secret. +.sp +\fIDefault:\fP not set +.SH REMOTE SECTION +.sp +Definitions of remote servers for outgoing connections (source of a zone +transfer, target for a notification, etc.). +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +remote: + \- id: STR + address: ADDR[@INT] | STR ... + via: ADDR[@INT] ... + quic: BOOL + tls: BOOL + key: key_id + cert\-key: BASE64 ... + block\-notify\-after\-transfer: BOOL + no\-edns: BOOL + automatic\-acl: BOOL +.ft P +.fi +.UNINDENT +.UNINDENT +.SS id +.sp +A remote identifier. +.SS address +.sp +An ordered list of destination IP addresses or UNIX socket paths which are +used for communication with the remote server. Non\-absolute path +(i.e. not starting with \fB/\fP) is relative to \fI\%rundir\fP\&. +Optional destination port (default is 53 for UDP/TCP and 853 for QUIC) +can be appended to the address using \fB@\fP separator. +The addresses are tried in sequence until the +remote is reached. +.sp +\fIDefault:\fP not set +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +If the remote is contacted and it refuses to perform requested action, +no more addresses will be tried for this remote. +.UNINDENT +.UNINDENT +.SS via +.sp +An ordered list of source IP addresses which are used as source addresses +for communication with the remote. For the N\-th \fI\%remote address\fP, +the last, but at most N\-th, specified \fI\%via address\fP +of the same family is used. +This option can help if the server listens on more addresses. +Optional source port (default is random) can be appended +to the address using \fB@\fP separator. +.sp +\fIDefault:\fP not set +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +For the following configuration: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +remote: + \- id: example + address: [198.51.100.10, 2001:db8::10, 198.51.100.20, 2001:db8::20] + via: [198.51.100.1, 198.51.100.2, 2001:db8::1] +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +the (\fBvia\fP \-> \fBaddress\fP) mapping is: +.INDENT 0.0 +.IP \(bu 2 +\fB198.51.100.1\fP \-> \fB198.51.100.10\fP +.IP \(bu 2 +\fB2001:db8::1\fP \-> \fB2001:db8::10\fP +.IP \(bu 2 +\fB198.51.100.2\fP \-> \fB198.51.100.20\fP +.IP \(bu 2 +\fB2001:db8::1\fP \-> \fB2001:db8::20\fP +.UNINDENT +.UNINDENT +.UNINDENT +.SS quic +.sp +If this option is set, the QUIC protocol will be used for outgoing communication +with this remote. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +One connection per each remote is opened; \fI\%remote\-pool\-limit\fP +does not take effect for QUIC. However, fast QUIC handshakes utilizing obtained +session tickets are used for reopening connections to recently (up to 1 day) +queried remotes. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBoff\fP +.SS tls +.sp +If this option is set, the TLS (DoT) protocol will be used for outgoing communication +with this remote. +.sp +\fIDefault:\fP \fBoff\fP +.SS key +.sp +A \fI\%reference\fP to the TSIG key which is used to authenticate +the communication with the remote server. +.sp +\fIDefault:\fP not set +.SS cert\-key +.sp +An ordered list of remote certificate public key PINs. If the list is non\-empty, +communication with the remote is possible only via QUIC protocol and +a peer certificate is required. The peer certificate key must match one of the +specified PINs. +.sp +A PIN is a unique identifier that represents the public key of the peer certificate. +It\(aqs a base64\-encoded SHA\-256 hash of the public key. This identifier +remains the same on a certificate renewal. +.sp +\fIDefault:\fP not set +.SS block\-notify\-after\-transfer +.sp +When incoming AXFR/IXFR from this remote (as a primary server), suppress +sending NOTIFY messages to all configured secondary servers. +.sp +\fIDefault:\fP \fBoff\fP +.SS no\-edns +.sp +If enabled, no OPT record (EDNS) is inserted to outgoing requests to this +remote server. This mode is necessary for communication with some broken +implementations (e.g. Windows Server 2016). +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This option effectively disables \fI\%zone expire\fP timer +updates via EDNS EXPIRE option specified in \fI\%RFC 7314\fP\&. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBoff\fP +.SS automatic\-acl +.sp +If enabled, some authorized operations for the remote are automatically allowed +based on the context: +.INDENT 0.0 +.IP \(bu 2 +Incoming NOTIFY is allowed from the remote if it\(aqs configured as a +\fI\%primary server\fP for the zone. +.IP \(bu 2 +Outgoing zone transfer is allowed to the remote if it\(aqs configured as a +\fI\%NOTIFY target\fP for the zone. +.UNINDENT +.sp +Automatic ACL rules are evaluated before explicit \fI\%zone ACL\fP configuration. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This functionality requires global activation via +\fI\%automatic\-acl\fP in the server section. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBon\fP +.SH REMOTES SECTION +.sp +Definitions of groups of remote servers. Remote grouping can simplify the +configuration. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +remotes: + \- id: STR + remote: remote_id ... +.ft P +.fi +.UNINDENT +.UNINDENT +.SS id +.sp +A remote group identifier. +.SS remote +.sp +An ordered list of \fI\%references\fP to remote server definitions. +.sp +\fIDefault:\fP not set +.SH ACL SECTION +.sp +Access control list rule definitions. An ACL rule is a description of one +or more authorized actions (zone transfer request, zone change notification, +and dynamic DNS update) which are allowed to be processed or denied. Normal +DNS queries are always allowed. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +acl: + \- id: STR + address: ADDR[/INT] | ADDR\-ADDR | STR ... + key: key_id ... + cert\-key: BASE64 ... + remote: remote_id | remotes_id ... + action: query | notify | transfer | update ... + deny: BOOL + update\-type: STR ... + update\-owner: key | zone | name + update\-owner\-match: sub\-or\-equal | equal | sub | pattern + update\-owner\-name: STR ... +.ft P +.fi +.UNINDENT +.UNINDENT +.SS id +.sp +An ACL rule identifier. +.SS address +.sp +An ordered list of IP addresses, absolute UNIX socket paths, network subnets, +or network ranges. The query\(aqs +source address must match one of them. If this item is not set, address match is not +required. +.sp +\fIDefault:\fP not set +.SS key +.sp +An ordered list of \fI\%reference\fPs to TSIG keys. The query must +match one of them. If this item is not set, transaction authentication is not used. +.sp +\fIDefault:\fP not set +.SS cert\-key +.sp +An ordered list of remote certificate public key PINs. If the list is non\-empty, +communication with the remote is possible only via QUIC protocol and +a peer certificate is required. The peer certificate key must match one of the +specified PINs. +.sp +A PIN is a unique identifier that represents the public key of the peer certificate. +It\(aqs a base64\-encoded SHA\-256 hash of the public key. This identifier +remains the same on a certificate renewal. +.sp +\fIDefault:\fP not set +.SS remote +.sp +An ordered list of references \fI\%remote\fP and +\fI\%remotes\fP\&. The query must +match one of the remotes. Specifically, one of the remote\(aqs addresses and remote\(aqs +TSIG key if configured must match. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This option cannot be specified along with the \fI\%address\fP or +\fI\%key\fP option at one ACL item. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP not set +.SS action +.sp +An ordered list of allowed, or denied, actions (request types). +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBquery\fP – Allow regular DNS query. As normal queries are always allowed, +this action is only useful in combination with \fI\%TSIG key\fP\&. +.IP \(bu 2 +\fBnotify\fP – Allow incoming notify (NOTIFY). +.IP \(bu 2 +\fBtransfer\fP – Allow zone transfer (AXFR, IXFR). +.IP \(bu 2 +\fBupdate\fP – Allow zone updates (DDNS). +.UNINDENT +.sp +\fIDefault:\fP \fBquery\fP +.SS deny +.sp +If enabled, instead of allowing, deny the specified \fI\%action\fP, +\fI\%address\fP, \fI\%key\fP, or combination if these +items. If no action is specified, deny all actions. +.sp +\fIDefault:\fP \fBoff\fP +.SS update\-type +.sp +A list of allowed types of Resource Records in a zone update. Every record in an update +must match one of the specified types. +.sp +\fIDefault:\fP not set +.SS update\-owner +.sp +This option restricts possible owners of Resource Records in a zone update by comparing +them to either the \fI\%TSIG key\fP identity, the current zone name, or to a list of +domain names given by the \fI\%update\-owner\-name\fP option. +The comparison method is given by the \fI\%update\-owner\-match\fP option. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBkey\fP — The owner of each updated RR must match the identity of the TSIG key if used. +.IP \(bu 2 +\fBname\fP — The owner of each updated RR must match at least one name in the +\fI\%update\-owner\-name\fP list. +.IP \(bu 2 +\fBzone\fP — The owner of each updated RR must match the current zone name. +.UNINDENT +.sp +\fIDefault:\fP not set +.SS update\-owner\-match +.sp +This option defines how the owners of Resource Records in an update are matched to the domain name(s) +set by the \fI\%update\-owner\fP option. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBsub\-or\-equal\fP — The owner of each RR in an update must either be equal to +or be a subdomain of at least one domain name set by \fI\%update\-owner\fP\&. +.IP \(bu 2 +\fBequal\fP — The owner of each updated RR must be equal to at least one domain +name set by \fI\%update\-owner\fP\&. +.IP \(bu 2 +\fBsub\fP — The owner of each updated RR must be a subdomain of, but MUST NOT +be equal to at least one domain name set by \fI\%update\-owner\fP\&. +.IP \(bu 2 +\fBpattern\fP — The owner of each updated RR must match a pattern specified by +\fI\%update\-owner\fP\&. The pattern can be an arbitrary FQDN or non\-FQDN +domain name. If a label consists of one \fB*\fP (asterisk) character, it +matches any label. More asterisk labels can be specified. +.UNINDENT +.sp +\fIDefault:\fP \fBsub\-or\-equal\fP +.SS update\-owner\-name +.sp +A list of allowed owners of RRs in a zone update used with \fI\%update\-owner\fP +set to \fBname\fP\&. Every listed owner name which is not FQDN (i.e. it doesn\(aqt end +in a dot) is considered as if it was appended with the target zone name. +Such a relative owner name specification allows better ACL rule reusability across +multiple zones. +.sp +\fIDefault:\fP not set +.SH SUBMISSION SECTION +.sp +Parameters of KSK submission checks. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +submission: + \- id: STR + parent: remote_id | remotes_id ... + check\-interval: TIME + timeout: TIME + parent\-delay: TIME +.ft P +.fi +.UNINDENT +.UNINDENT +.SS id +.sp +A submission identifier. +.SS parent +.sp +A list of references \fI\%remote\fP and \fI\%remotes\fP +to parent\(aqs DNS servers to be checked for +presence of corresponding DS records in the case of KSK submission. All of them must +have a corresponding DS for the rollover to continue. If none is specified, the +rollover must be pushed forward manually. +.sp +\fIDefault:\fP not set +.sp +\fBTIP:\fP +.INDENT 0.0 +.INDENT 3.5 +A DNSSEC\-validating resolver can be set as a parent. +.UNINDENT +.UNINDENT +.SS check\-interval +.sp +Interval (in seconds) for periodic checks of DS presence on parent\(aqs DNS +servers, in the case of the KSK submission. +.sp +\fIDefault:\fP \fB1h\fP (1 hour) +.SS timeout +.sp +After this time period (in seconds) the KSK submission is automatically considered +successful, even if all the checks were negative or no parents are configured. +Set to 0 for infinity. +.sp +\fIDefault:\fP \fB0\fP +.SS parent\-delay +.sp +After successful parent DS check, wait for this period (in seconds) before +continuing the next key roll\-over step. This delay shall cover the propagation +delay of update in the parent zone. +.sp +\fIDefault:\fP \fB0\fP +.SH DNSKEY-SYNC SECTION +.sp +Parameters of DNSKEY dynamic\-update synchronization. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +dnskey\-sync: + \- id: STR + remote: remote_id | remotes_id ... + check\-interval: TIME +.ft P +.fi +.UNINDENT +.UNINDENT +.SS id +.sp +A dnskey\-sync identifier. +.SS remote +.sp +A list of references \fI\%remote\fP and \fI\%remotes\fP +to other signers or common master, which the DDNS updates with +DNSKEY/CDNSKEY/CDS records shall be sent to. +.sp +\fIDefault:\fP not set +.SS check\-interval +.sp +If the last DNSKEY sync failed or resulted in any change, re\-check +the consistence after this interval (in seconds) and re\-try if needed. +.sp +\fIDefault:\fP \fB60\fP (1 minute) +.SH POLICY SECTION +.sp +DNSSEC policy configuration. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +policy: + \- id: STR + keystore: keystore_id + manual: BOOL + single\-type\-signing: BOOL + algorithm: rsasha1 | rsasha1\-nsec3\-sha1 | rsasha256 | rsasha512 | ecdsap256sha256 | ecdsap384sha384 | ed25519 | ed448 + ksk\-size: SIZE + zsk\-size: SIZE + ksk\-shared: BOOL + dnskey\-ttl: TIME + zone\-max\-ttl: TIME + keytag\-modulo: INT/INT + ksk\-lifetime: TIME + zsk\-lifetime: TIME + delete\-delay: TIME + propagation\-delay: TIME + rrsig\-lifetime: TIME + rrsig\-refresh: TIME + rrsig\-pre\-refresh: TIME + reproducible\-signing: BOOL + nsec3: BOOL + nsec3\-iterations: INT + nsec3\-opt\-out: BOOL + nsec3\-salt\-length: INT + nsec3\-salt\-lifetime: TIME + signing\-threads: INT + ksk\-submission: submission_id + ds\-push: remote_id | remotes_id ... + cds\-cdnskey\-publish: none | delete\-dnssec | rollover | always | double\-ds + cds\-digest\-type: sha256 | sha384 + dnskey\-management: full | incremental + offline\-ksk: BOOL + unsafe\-operation: none | no\-check\-keyset | no\-update\-dnskey | no\-update\-nsec | no\-update\-expired ... +.ft P +.fi +.UNINDENT +.UNINDENT +.SS id +.sp +A policy identifier. +.SS keystore +.sp +A \fI\%reference\fP to a keystore holding private key material +for zones. +.sp +\fIDefault:\fP an imaginary keystore with all default values +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +A configured keystore called \(dqdefault\(dq won\(aqt be used unless explicitly referenced. +.UNINDENT +.UNINDENT +.SS manual +.sp +If enabled, automatic key management is not used. +.sp +\fIDefault:\fP \fBoff\fP +.SS single\-type\-signing +.sp +If enabled, Single\-Type Signing Scheme is used in the automatic key management +mode. +.sp +\fIDefault:\fP \fBoff\fP (\fI\%module onlinesign\fP has default \fBon\fP) +.SS algorithm +.sp +An algorithm of signing keys and issued signatures. See +\fI\%DNSSEC Algorithm Numbers\fP\&. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBrsasha1\fP +.IP \(bu 2 +\fBrsasha1\-nsec3\-sha1\fP +.IP \(bu 2 +\fBrsasha256\fP +.IP \(bu 2 +\fBrsasha512\fP +.IP \(bu 2 +\fBecdsap256sha256\fP +.IP \(bu 2 +\fBecdsap384sha384\fP +.IP \(bu 2 +\fBed25519\fP +.IP \(bu 2 +\fBed448\fP +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Ed448 algorithm is only available if compiled with GnuTLS 3.6.12+ and Nettle 3.6+. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBecdsap256sha256\fP +.SS ksk\-size +.sp +A length of newly generated KSK or +CSK keys. +.sp +\fIDefault:\fP \fB2048\fP (rsa*), \fB256\fP (ecdsap256), \fB384\fP (ecdsap384), \fB256\fP (ed25519), +\fB456\fP (ed448) +.SS zsk\-size +.sp +A length of newly generated ZSK keys. +.sp +\fIDefault:\fP see default for \fI\%ksk\-size\fP +.SS ksk\-shared +.sp +If enabled, all zones with this policy assigned will share one or more KSKs. +More KSKs can be shared during a KSK rollover. +.sp +\fBWARNING:\fP +.INDENT 0.0 +.INDENT 3.5 +As the shared KSK set is bound to the policy \fI\%id\fP, renaming the +policy breaks this connection and new shared KSK set is initiated when +a new KSK is needed. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBoff\fP +.SS dnskey\-ttl +.sp +A TTL value for DNSKEY records added into zone apex. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Has influence over ZSK key lifetime. +.UNINDENT +.UNINDENT +.sp +\fBWARNING:\fP +.INDENT 0.0 +.INDENT 3.5 +Ensure all DNSKEYs with updated TTL are propagated before any subsequent +DNSKEY rollover starts. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP zone SOA TTL +.SS zone\-max\-ttl +.sp +Declare (override) maximal TTL value among all the records in zone. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +It\(aqs generally recommended to override the maximal TTL computation by setting this +explicitly whenever possible. It\(aqs required for \fI\%DNSSEC Offline KSK\fP and +really reasonable when records are generated dynamically +(e.g. by a \fI\%module\fP). +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP computed after zone is loaded +.SS keytag\-modulo +.sp +Specifies that the keytags of any generated keys shall be congruent by specified modulo. +The option value must be a string in the format \fBR/M\fP, where \fBR < M <= 256\fP are +positive integers. Whenever a DNSSEC key is generated, it is ensured +that \fBkeytag % M == R\fP\&. This prevents keytag conflict in \fI\%DNSSEC Offline KSK\fP +or \fI\%DNSSEC multi\-signer\fP (and possibly other) setups. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This only applies to newly generated keys when they are generated. Keys from +before this option and keys imported from elsewhere might not fulfill the policy. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB0/1\fP +.SS ksk\-lifetime +.sp +A period (in seconds) between KSK generation and the next rollover initiation. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +KSK key lifetime is also influenced by propagation\-delay, dnskey\-ttl, +and KSK submission delay. +.sp +Zero (aka infinity) value causes no KSK rollover as a result. +.sp +This applies for CSK lifetime if single\-type\-signing is enabled. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB0\fP (infinity) +.SS zsk\-lifetime +.sp +A period (in seconds) between ZSK activation and the next rollover initiation. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +More exactly, this period is measured since a ZSK is activated, +and after this, a new ZSK is generated to replace it within +following roll\-over. +.sp +As a consequence, in normal operation, this results in the period +of ZSK generation being \fIzsk\-lifetime + propagation\-delay + dnskey_ttl\fP\&. +.sp +Zero (aka infinity) value causes no ZSK rollover as a result. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB30d\fP (30 days) +.SS delete\-delay +.sp +Once a key (KSK or ZSK) is rolled\-over and removed from the zone, +keep it in the KASP database for at least this period (in seconds) before deleting +it completely. This might be useful in some troubleshooting cases when resurrection +is needed. +.sp +\fIDefault:\fP \fB0\fP +.SS propagation\-delay +.sp +An extra delay added for each key rollover step. This value (in seconds) +should be high enough to cover propagation of data from the primary server +to all secondary servers, as well as the duration of signing routine itself +and possible outages in signing and propagation infrastructure. In other +words, this delay should ensure that within this period of time after +planned change of the key set, all public\-facing secondaries will already +serve new DNSKEY RRSet for sure. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Has influence over ZSK key lifetime. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB1h\fP (1 hour) +.SS rrsig\-lifetime +.sp +A validity period (in seconds) of newly issued signatures. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +The RRSIG\(aqs signature inception time is set to 90 minutes in the past. This +time period is not counted to the signature lifetime. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB14d\fP (14 days) +.SS rrsig\-refresh +.sp +A period (in seconds) how long at least before a signature expiration the signature +will be refreshed, in order to prevent expired RRSIGs on secondary servers or +resolvers\(aq caches. +.sp +\fIDefault:\fP 0.1 * \fI\%rrsig\-lifetime\fP + \fI\%propagation\-delay\fP + \fI\%zone\-max\-ttl\fP +.sp +If \fI\%dnssec\-validation\fP is enabled: +.sp +\fIDefault:\fP \fB1d\fP (1 day) +.SS rrsig\-pre\-refresh +.sp +A period (in seconds) how long at most before a signature refresh time the signature +might be refreshed, in order to refresh RRSIGs in bigger batches on a frequently updated +zone (avoid re\-sign event too often). +.sp +\fIDefault:\fP \fB1h\fP (1 hour) +.SS reproducible\-signing +.sp +For ECDSA algorithms, generate RRSIG signatures deterministically (\fI\%RFC 6979\fP). +Besides better theoretical cryptographic security, this mode allows significant +speed\-up of loading signed (by the same method) zones. However, the zone signing +is a bit slower. +.sp +\fIDefault:\fP \fBoff\fP +.SS nsec3 +.sp +Specifies if NSEC3 will be used instead of NSEC. +.sp +\fIDefault:\fP \fBoff\fP +.SS nsec3\-iterations +.sp +A number of additional times the hashing is performed. +.sp +\fIDefault:\fP \fB0\fP +.SS nsec3\-opt\-out +.sp +If set, NSEC3 records won\(aqt be created for insecure delegations. +This speeds up the zone signing and reduces overall zone size. +.sp +\fBWARNING:\fP +.INDENT 0.0 +.INDENT 3.5 +NSEC3 with the Opt\-Out bit set no longer works as a proof of non\-existence +in this zone. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBoff\fP +.SS nsec3\-salt\-length +.sp +A length of a salt field in octets, which is appended to the original owner +name before hashing. +.sp +\fIDefault:\fP \fB8\fP +.SS nsec3\-salt\-lifetime +.sp +A validity period (in seconds) of newly issued salt field. +.sp +Zero value means infinity. +.sp +Special value \fI\-1\fP triggers re\-salt every time when active ZSK changes. +This optimizes the number of big changes to the zone. +.sp +\fIDefault:\fP \fB30d\fP (30 days) +.SS signing\-threads +.sp +When signing zone or update, use this number of threads for parallel signing. +.sp +Those are extra threads independent of \fI\%Background workers\fP\&. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Some steps of the DNSSEC signing operation are not parallelized. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB1\fP (no extra threads) +.SS ksk\-submission +.sp +A reference to \fI\%submission\fP section holding parameters of +KSK submission checks. +.sp +\fIDefault:\fP not set +.SS ds\-push +.sp +Optional references \fI\%remote\fP and \fI\%remotes\fP +to authoritative DNS server of the +parent\(aqs zone. The remote server must be configured to accept DS record +updates via DDNS. Whenever a CDS record in the local zone is changed, the +corresponding DS record is sent as a dynamic update (DDNS) to the parent +DNS server. All previous DS records are deleted within the DDNS message. +It\(aqs possible to manage both child and parent zones by the same Knot DNS server. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This feature requires \fI\%cds\-cdnskey\-publish\fP +not to be set to \fBnone\fP\&. +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +The mentioned change to CDS record usually means that a KSK roll\-over is running +and the new key being rolled\-in is in \(dqready\(dq state already for the period of +\fI\%propagation\-delay\fP\&. +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Module \fI\%Onlinesign\fP doesn\(aqt support DS push. +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +When turning this feature on while a KSK roll\-over is already running, it might +not take effect for the already\-running roll\-over. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP not set +.SS dnskey\-sync +.sp +A reference to \fI\%dnskey\-sync\fP section holding parameters +of DNSKEY synchronization. +.sp +\fIDefault:\fP not set +.SS cds\-cdnskey\-publish +.sp +Controls if and how shall the CDS and CDNSKEY be published in the zone. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBnone\fP – Never publish any CDS or CDNSKEY records in the zone. +.IP \(bu 2 +\fBdelete\-dnssec\fP – Publish special CDS and CDNSKEY records indicating turning off DNSSEC. +.IP \(bu 2 +\fBrollover\fP – Publish CDS and CDNSKEY records for ready and not yet active KSK (submission phase of KSK rollover). +.IP \(bu 2 +\fBalways\fP – Always publish one CDS and one CDNSKEY records for the current KSK. +.IP \(bu 2 +\fBdouble\-ds\fP – Always publish up to two CDS and two CDNSKEY records for ready and/or active KSKs. +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +If the zone keys are managed manually, the CDS and CDNSKEY rrsets may contain +more records depending on the keys available. +.UNINDENT +.UNINDENT +.sp +\fBWARNING:\fP +.INDENT 0.0 +.INDENT 3.5 +The \fBdouble\-ds\fP value does not trigger double\-DS roll\-over method. That method is +only supported when performed manually, with unset \fI\%ksk\-submission\fP\&. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBrollover\fP +.SS cds\-digest\-type +.sp +Specify digest type for published CDS records. +.sp +\fIDefault:\fP \fBsha256\fP +.SS dnskey\-management +.sp +Specify how the DNSKEY, CDNSKEY, and CDS RRSets at the zone apex are handled +when (re\-)signing the zone. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBfull\fP – Upon every zone (re\-)sign, delete all unknown DNSKEY, CDNSKEY, and CDS +records and keep just those that are related to the zone keys stored in the KASP database. +.IP \(bu 2 +\fBincremental\fP – Keep unknown DNSKEY, CDNSKEY, and CDS records in the zone, and +modify server\-managed records incrementally by employing changes in the KASP database. +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Prerequisites for \fIincremental\fP: +.INDENT 0.0 +.IP \(bu 2 +The \fI\%Offline KSK\fP isn\(aqt supported. +.IP \(bu 2 +The \fI\%delete\-delay\fP is long enough to cover possible daemon +shutdown (e.g. due to server maintenance). +.IP \(bu 2 +Avoided manual deletion of keys with \fI\%keymgr\fP\&. +.UNINDENT +.sp +Otherwise there might remain some DNSKEY records in the zone, belonging to +deleted keys. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBfull\fP +.SS offline\-ksk +.sp +Specifies if \fI\%Offline KSK\fP feature is enabled. +.sp +\fIDefault:\fP \fBoff\fP +.SS unsafe\-operation +.sp +Turn off some DNSSEC safety features. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBnone\fP – Nothing disabled. +.IP \(bu 2 +\fBno\-check\-keyset\fP – Don\(aqt check active keys in present algorithms. This may +lead to violation of \fI\%RFC 4035#section\-2.2\fP\&. +.IP \(bu 2 +\fBno\-update\-dnskey\fP – Don\(aqt maintain/update DNSKEY, CDNSKEY, and CDS records +in the zone apex according to KASP database. Juste leave them as they are in the zone. +.IP \(bu 2 +\fBno\-update\-nsec\fP – Don\(aqt maintain/update NSEC/NSEC3 chain. Leave all the records +as they are in the zone. +.IP \(bu 2 +\fBno\-update\-expired\fP – Don\(aqt update expired RRSIGs. +.UNINDENT +.sp +Multiple values may be specified. +.sp +\fBWARNING:\fP +.INDENT 0.0 +.INDENT 3.5 +This mode is intended for DNSSEC experts who understand the corresponding consequences. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBnone\fP +.SH TEMPLATE SECTION +.sp +A template is shareable zone settings, which can simplify configuration by +reducing duplicates. A special default template (with the \fIdefault\fP identifier) +can be used for global zone configuration or as an implicit configuration +if a zone doesn\(aqt have another template specified. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +template: + \- id: STR + global\-module: STR/STR ... + # All zone options (excluding \(aqtemplate\(aq item) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +If an item is explicitly specified both in the referenced template and +the zone, the template item value is overridden by the zone item value. +.UNINDENT +.UNINDENT +.SS id +.sp +A template identifier. +.SS global\-module +.sp +An ordered list of references to query modules in the form of \fImodule_name\fP or +\fImodule_name/module_id\fP\&. These modules apply to all queries. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This option is only available in the \fIdefault\fP template. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP not set +.SH ZONE SECTION +.sp +Definition of zones served by the server. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +zone: + \- domain: DNAME + template: template_id + storage: STR + file: STR + master: remote_id | remotes_id ... + ddns\-master: remote_id + notify: remote_id | remotes_id ... + acl: acl_id ... + master\-pin\-tolerance: TIME + provide\-ixfr: BOOL + semantic\-checks: BOOL | soft + default\-ttl: TIME + zonefile\-sync: TIME + zonefile\-load: none | difference | difference\-no\-serial | whole + journal\-content: none | changes | all + journal\-max\-usage: SIZE + journal\-max\-depth: INT + ixfr\-benevolent: BOOL + ixfr\-by\-one: BOOL + ixfr\-from\-axfr: BOOL + zone\-max\-size : SIZE + adjust\-threads: INT + dnssec\-signing: BOOL + dnssec\-validation: BOOL + dnssec\-policy: policy_id + ds\-push: remote_id | remotes_id ... + zonemd\-verify: BOOL + zonemd\-generate: none | zonemd\-sha384 | zonemd\-sha512 | remove + serial\-policy: increment | unixtime | dateserial + serial\-modulo: INT/INT + reverse\-generate: DNAME + refresh\-min\-interval: TIME + refresh\-max\-interval: TIME + retry\-min\-interval: TIME + retry\-max\-interval: TIME + expire\-min\-interval: TIME + expire\-max\-interval: TIME + catalog\-role: none | interpret | generate | member + catalog\-template: template_id ... + catalog\-zone: DNAME + catalog\-group: STR + module: STR/STR ... +.ft P +.fi +.UNINDENT +.UNINDENT +.SS domain +.sp +A zone name identifier. +.SS template +.sp +A \fI\%reference\fP to a configuration template. +.sp +\fIDefault:\fP not set or \fBdefault\fP (if the template exists) +.SS storage +.sp +A data directory for storing zone files. A non\-absolute path is relative to +the \fI\%knotd\fP startup directory. +.sp +\fIDefault:\fP \fB${localstatedir}/lib/knot\fP (configured with \fB\-\-with\-storage=path\fP) +.SS file +.sp +A \fI\%path\fP to the zone file. It is also possible to use +the following formatters: +.INDENT 0.0 +.IP \(bu 2 +\fB%c[\fP\fIN\fP\fB]\fP or \fB%c[\fP\fIN\fP\fB\-\fP\fIM\fP\fB]\fP – Means the \fIN\fPth +character or a sequence of characters beginning from the \fIN\fPth and ending +with the \fIM\fPth character of the textual zone name (see \fB%s\fP). The +indexes are counted from 0 from the left. All dots (including the terminal +one) are considered. If the character is not available, the formatter has no effect. +.IP \(bu 2 +\fB%l[\fP\fIN\fP\fB]\fP – Means the \fIN\fPth label of the textual zone name +(see \fB%s\fP). The index is counted from 0 from the right (0 ~ TLD). +If the label is not available, the formatter has no effect. +.IP \(bu 2 +\fB%s\fP – Means the current zone name in the textual representation. +The zone name doesn\(aqt include the terminating dot (the result for the root +zone is the empty string!). +.IP \(bu 2 +\fB%%\fP – Means the \fB%\fP character. +.UNINDENT +.sp +\fBWARNING:\fP +.INDENT 0.0 +.INDENT 3.5 +Beware of special characters which are escaped or encoded in the \eDDD form +where DDD is corresponding decimal ASCII code. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fI\%storage\fP\fB/%s.zone\fP +.SS master +.sp +An ordered list of references \fI\%remote\fP and +\fI\%remotes\fP to zone primary servers +(formerly known as master servers). +Empty value is allowed for template value overriding. +.sp +\fIDefault:\fP not set +.SS ddns\-master +.sp +A \fI\%reference\fP to a zone primary master where DDNS messages +should be forwarded to. If not specified, the first \fI\%master\fP +server is used. +.sp +If set to the empty value (\(dq\(dq), incoming DDNS messages aren\(aqt forwarded but are applied +to the local zone instead, no matter if it is a secondary server. This is only allowed in +combination with \fI\%dnssec\-signing\fP enabled. +.sp +\fIDefault:\fP not set +.SS notify +.sp +An ordered list of references \fI\%remote\fP and +\fI\%remotes\fP to secondary servers to which notify +message is sent if the zone changes. +Empty value is allowed for template value overriding. +.sp +\fIDefault:\fP not set +.SS acl +.sp +An ordered list of \fI\%references\fP to ACL rules which can allow +or disallow zone transfers, updates or incoming notifies. +.sp +\fIDefault:\fP not set +.SS master\-pin\-tolerance +.sp +If set to a nonzero value on a secondary, always request AXFR/IXFR from the same +primary as the last time, effectively pinning one primary. Only when another +primary is updated and the current one lags behind for the specified amount of time +(defined by this option in seconds), change to the updated primary and force AXFR. +.sp +This option is useful when multiple primaries may have different zone history +in their journals, making it unsafe to combine interchanged IXFR +from different primaries. +.sp +\fIDefault:\fP \fB0\fP (disabled) +.SS provide\-ixfr +.sp +If disabled, the server is forced to respond with AXFR to IXFR queries. +If enabled, IXFR requests are responded normally. +.sp +\fIDefault:\fP \fBon\fP +.SS semantic\-checks +.sp +Selects if extra zone semantic checks are used or impacts of the mandatory checks. +.sp +There are several mandatory checks which are always enabled and cannot be turned +off. An error in a mandatory check causes the zone not to be loaded. Most of +the mandatory checks can be weakened by setting \fBsoft\fP, which allows the zone to +be loaded even if the check fails. +.sp +If enabled, extra checks are used. These checks don\(aqt prevent the zone from loading. +.sp +The mandatory checks are applied to zone files, zone transfers, and updates via +control interface. The extra checks are applied to zone files only! +.sp +Mandatory checks: +.INDENT 0.0 +.IP \(bu 2 +Missing SOA record at the zone apex (\fI\%RFC 1034\fP) (*) +.IP \(bu 2 +An extra record exists together with a CNAME record except for RRSIG and NSEC (\fI\%RFC 1034\fP) +.IP \(bu 2 +Multiple CNAME records with the same owner exist (\fI\%RFC 1034\fP) +.IP \(bu 2 +DNAME record having a record under it (\fI\%RFC 6672\fP) +.IP \(bu 2 +Multiple DNAME records with the same owner exist (\fI\%RFC 6672\fP) +.IP \(bu 2 +NS record exists together with a DNAME record (\fI\%RFC 6672\fP) +.IP \(bu 2 +DS record exists at the zone apex (\fI\%RFC 3658\fP) +.UNINDENT +.sp +(*) The marked check can\(aqt be weakened by the soft mode. All other mandatory checks +are subject to the optional soft mode. +.sp +Extra checks: +.INDENT 0.0 +.IP \(bu 2 +Missing NS record at the zone apex +.IP \(bu 2 +Missing glue A or AAAA record +.IP \(bu 2 +Invalid DS or NSEC3PARAM record +.IP \(bu 2 +CDS or CDNSKEY inconsistency +.IP \(bu 2 +All other DNSSEC checks executed during \fI\%dnssec\-validation\fP +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +The soft mode allows the refresh event to ignore a CNAME response to a SOA +query (malformed message) and triggers a zone bootstrap instead. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBoff\fP +.SS default\-ttl +.sp +The default TTL value if none is specified in a zone file or zone insertion +using the dynamic configuration. +.sp +\fBWARNING:\fP +.INDENT 0.0 +.INDENT 3.5 +As changing this value can result in differently parsed zone file(s), +the corresponding zone SOA serial(s) should be incremented before +reloading or commiting the configuration. Alternatively, setting +\fI\%zonefile\-load\fP to \fBdifference\-no\-serial\fP ensures +the resulting zone(s) update is correct. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB3600\fP +.SS zonefile\-sync +.sp +The time in seconds after which the current zone in memory will be synced with +a zone file on the disk (see \fI\%file\fP). The server will serve the latest +zone even after a restart using zone journal, but the zone file on the disk will +only be synced after \fBzonefile\-sync\fP time has expired (or after manual zone +flush). This is applicable when the zone is updated via IXFR, DDNS or automatic +DNSSEC signing. In order to completely disable automatic zone file synchronization, +set the value to \-1. In that case, it is still possible to force a manual zone flush +using the \fB\-f\fP option. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +If you are serving large zones with frequent updates where +the immediate sync with a zone file is not desirable, increase the value. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB0\fP (immediate) +.SS zonefile\-load +.sp +Selects how the zone file contents are applied during zone load. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBnone\fP – The zone file is not used at all. +.IP \(bu 2 +\fBdifference\fP – If the zone contents are already available during server start or reload, +the difference is computed between them and the contents of the zone file. This difference +is then checked for semantic errors and applied to the current zone contents. +.IP \(bu 2 +\fBdifference\-no\-serial\fP – Same as \fBdifference\fP, but the SOA serial in the zone file is +ignored, the server takes care of incrementing the serial automatically. +.IP \(bu 2 +\fBwhole\fP – Zone contents are loaded from the zone file. +.UNINDENT +.sp +When \fBdifference\fP is configured and there are no zone contents yet (cold start +and no zone contents in the journal), it behaves the same way as \fBwhole\fP\&. +.sp +\fIDefault:\fP \fBwhole\fP +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +See \fI\%Handling zone file, journal, changes, serials\fP for guidance on +configuring these and related options to ensure reliable operation. +.UNINDENT +.UNINDENT +.SS journal\-content +.sp +Selects how the journal shall be used to store zone and its changes. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBnone\fP – The journal is not used at all. +.IP \(bu 2 +\fBchanges\fP – Zone changes history is stored in journal. +.IP \(bu 2 +\fBall\fP – Zone contents and history is stored in journal. +.UNINDENT +.sp +\fIDefault:\fP \fBchanges\fP +.sp +\fBWARNING:\fP +.INDENT 0.0 +.INDENT 3.5 +When this option is changed, the journal still contains data respective to +the previous setting. For example, changing it to \fBnone\fP does not purge +the journal. Also, changing it from \fBall\fP to \fBchanges\fP +does not cause the deletion of the zone\-in\-journal and the behaviour of the +zone loading procedure might be different than expected. It is recommended +to consider purging the journal when this option is changed. +.UNINDENT +.UNINDENT +.SS journal\-max\-usage +.sp +Policy how much space in journal DB will the zone\(aqs journal occupy. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Journal DB may grow far above the sum of journal\-max\-usage across +all zones, because of DB free space fragmentation. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB100M\fP (100 MiB) +.SS journal\-max\-depth +.sp +Maximum history length of the journal. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Zone\-in\-journal changeset isn\(aqt counted to the limit. +.UNINDENT +.UNINDENT +.sp +\fIMinimum:\fP \fB2\fP +.sp +\fIDefault:\fP \fB20\fP +.SS ixfr\-benevolent +.sp +If enabled, incoming IXFR is applied even when it contains removals of non\-existing +or additions of existing records. +.sp +\fIDefault:\fP \fBoff\fP +.SS ixfr\-by\-one +.sp +Within incoming IXFR, process only one changeset at a time, not multiple together. +This preserves the complete history in the journal and prevents the merging of +changesets when multiple changesets are IXFRed simultaneously. However, this does not +prevent the merging (or deletion) of old changesets in the journal to save space, +as described in \fI\%journal behaviour\fP\&. +.sp +This option leads to increased server load when processing IXFR, including +network traffic. +.sp +\fIDefault:\fP \fBoff\fP +.SS ixfr\-from\-axfr +.sp +If a primary sends AXFR\-style\-IXFR upon an IXFR request, compute the difference +and process it as an incremental zone update (e.g. by storing the changeset in +the journal). +.sp +\fIDefault:\fP \fBoff\fP +.SS zone\-max\-size +.sp +Maximum size of the zone. The size is measured as size of the zone records +in wire format without compression. The limit is enforced for incoming zone +transfers and dynamic updates. +.sp +For incremental transfers (IXFR), the effective limit for the total size of +the records in the transfer is twice the configured value. However the final +size of the zone must satisfy the configured value. +.sp +\fIDefault:\fP unlimited +.SS adjust\-threads +.sp +Parallelize internal zone adjusting procedures by using specified number of +threads. This is useful with huge zones with NSEC3. Speedup observable at +server startup and while processing NSEC3 re\-salt. +.sp +\fIDefault:\fP \fB1\fP (no extra threads) +.SS dnssec\-signing +.sp +If enabled, automatic DNSSEC signing for the zone is turned on. +.sp +\fIDefault:\fP \fBoff\fP +.SS dnssec\-validation +.sp +If enabled, the zone contents are validated for being correctly signed +(including NSEC/NSEC3 chain) with DNSSEC signatures every time the zone +is loaded or changed (including AXFR/IXFR). +.sp +When the validation fails, the zone being loaded or update being applied +is cancelled with an error, and either none or previous zone state is published. +.sp +List of DNSSEC checks: +.INDENT 0.0 +.IP \(bu 2 +Every zone RRSet is correctly signed by at least one present DNSKEY. +.IP \(bu 2 +For every RRSIG there are at most 3 non\-matching DNSKEYs with the same keytag. +.IP \(bu 2 +DNSKEY RRSet is signed by KSK. +.IP \(bu 2 +NSEC(3) RR exists for each name (unless opt\-out) with correct bitmap. +.IP \(bu 2 +Every NSEC(3) RR is linked to the lexicographically next one. +.UNINDENT +.sp +The validation is not affected by \fI\%dnssec\-policy\fP configuration, +except for \fI\%signing\-threads\fP option, which specifies the number +of threads for parallel validation, and \fI\%rrsig\-refresh\fP, which +defines minimal allowed remaining RRSIG validity (otherwise a warning is +logged). +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Redundant or garbage NSEC3 records are ignored. +.sp +This mode is not compatible with \fI\%dnssec\-signing\fP\&. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP not set +.SS dnssec\-policy +.sp +A \fI\%reference\fP to DNSSEC signing policy. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +A configured policy called \(dqdefault\(dq won\(aqt be used unless explicitly referenced. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP an imaginary policy with all default values +.SS ds\-push +.sp +Per zone configuration of \fI\%ds\-push\fP\&. This option overrides possible +per policy option. Empty value is allowed for template value overriding. +.sp +\fIDefault:\fP not set +.SS zonemd\-verify +.sp +On each zone load/update, verify that ZONEMD is present in the zone and valid. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Zone digest calculation may take much time and CPU on large zones. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBoff\fP +.SS zonemd\-generate +.sp +On each zone update, calculate ZONEMD and put it into the zone. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBnone\fP – No action regarding ZONEMD. +.IP \(bu 2 +\fBzonemd\-sha384\fP – Generate ZONEMD using SHA384 algorithm. +.IP \(bu 2 +\fBzonemd\-sha512\fP – Generate ZONEMD using SHA512 algorithm. +.IP \(bu 2 +\fBremove\fP – Remove any ZONEMD from the zone apex. +.UNINDENT +.sp +\fIDefault:\fP \fBnone\fP +.SS serial\-policy +.sp +Specifies how the zone serial is updated after a dynamic update or +automatic DNSSEC signing. If the serial is changed by the dynamic update, +no change is made. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBincrement\fP – The serial is incremented according to serial number arithmetic. +.IP \(bu 2 +\fBunixtime\fP – The serial is set to the current unix time. +.IP \(bu 2 +\fBdateserial\fP – The 10\-digit serial (YYYYMMDDnn) is incremented, the first +8 digits match the current iso\-date. +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +If the resulting serial for \fBunixtime\fP or \fBdateserial\fP is lower than or +equal to the current serial (this happens e.g. when migrating from other policy or +frequent updates), the serial is incremented instead. +.sp +To avoid user confusion, use \fBdateserial\fP only if you expect at most +100 updates per day per zone and \fBunixtime\fP only if you expect at most +one update per second per zone. +.sp +Generated catalog zones use \fBunixtime\fP only. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBincrement\fP (\fBunixtime\fP for generated catalog zones) +.SS serial\-modulo +.sp +Specifies that the zone serials shall be congruent by specified modulo. +The option value must be a string in the format \fBR/M\fP, where \fBR < M <= 256\fP are +positive integers. Whenever the zone serial is incremented, it is ensured +that \fBserial % M == R\fP\&. This can be useful in the case of multiple inconsistent +primaries, where distinct zone serial sequences prevent cross\-master\-IXFR +by any secondary. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +In order to ensure the congruent policy, this option is only allowed +with \fI\%DNSSEC signing enabled\fP and +\fI\%zonefile\-load\fP to be either \fBdifference\-no\-serial\fP or \fBnone\fP\&. +.sp +Because the zone serial effectively always increments by \fBM\fP instead of +\fB1\fP, it is not recommended to use \fBdateserial\fP \fI\%serial\-policy\fP +or even \fBunixtime\fP in case of rapidly updated zone. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB0/1\fP +.SS reverse\-generate +.sp +This option triggers the automatic generation of reverse PTR records based on +A/AAAA records in the specified zone. The entire generated zone is automatically +stored in the journal. +.sp +Current limitations: +.INDENT 0.0 +.IP \(bu 2 +Only one zone to be reversed can be specified. +.IP \(bu 2 +Is slow for large zones (even when changing a little). +.UNINDENT +.sp +\fIDefault:\fP none +.SS refresh\-min\-interval +.sp +Forced minimum zone refresh interval (in seconds) to avoid flooding primary server. +.sp +\fIMinimum:\fP \fB2\fP +.sp +\fIDefault:\fP \fB2\fP +.SS refresh\-max\-interval +.sp +Forced maximum zone refresh interval (in seconds). +.sp +\fIDefault:\fP not set +.SS retry\-min\-interval +.sp +Forced minimum zone retry interval (in seconds) to avoid flooding primary server. +.sp +\fIMinimum:\fP \fB1\fP +.sp +\fIDefault:\fP \fB1\fP +.SS retry\-max\-interval +.sp +Forced maximum zone retry interval (in seconds). +.sp +\fIDefault:\fP not set +.SS expire\-min\-interval +.sp +Forced minimum zone expire interval (in seconds) to avoid flooding primary server. +.sp +\fIMinimum:\fP \fB3\fP +.sp +\fIDefault:\fP \fB3\fP +.SS expire\-max\-interval +.sp +Forced maximum zone expire interval (in seconds). +.sp +\fIDefault:\fP not set +.SS catalog\-role +.sp +Trigger zone catalog feature. Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBnone\fP – Not a catalog zone. +.IP \(bu 2 +\fBinterpret\fP – A catalog zone which is loaded from a zone file or XFR, +and member zones shall be configured based on its contents. +.IP \(bu 2 +\fBgenerate\fP – A catalog zone whose contents are generated according to +assigned member zones. +.IP \(bu 2 +\fBmember\fP – A member zone that is assigned to one generated catalog zone. +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +If set to \fBgenerate\fP, the \fI\%zonefile\-load\fP option has no effect +since a zone file is never loaded. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fBnone\fP +.SS catalog\-template +.sp +For the catalog member zones, the specified configuration template will be applied. +.sp +Multiple catalog templates may be defined. The first one is used unless the member zone +has the \fIgroup\fP property defined, matching another catalog template. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This option must be set if and only if \fI\%catalog\-role\fP is \fIinterpret\fP\&. +.sp +Nested catalog zones aren\(aqt supported. Therefore catalog templates can\(aqt +contain \fI\%catalog\-role\fP set to \fBinterpret\fP or \fBgenerate\fP\&. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP not set +.SS catalog\-zone +.sp +Assign this member zone to specified generated catalog zone. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This option must be set if and only if \fI\%catalog\-role\fP is \fImember\fP\&. +.sp +The referenced catalog zone must exist and have \fI\%catalog\-role\fP set to \fIgenerate\fP\&. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP not set +.SS catalog\-group +.sp +Assign this member zone to specified catalog group (configuration template). +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This option has effect if and only if \fI\%catalog\-role\fP is \fImember\fP\&. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP not set +.SS module +.sp +An ordered list of references to query modules in the form of \fImodule_name\fP or +\fImodule_name/module_id\fP\&. These modules apply only to the current zone queries. +.sp +\fIDefault:\fP not set +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/knot.conf.5in b/doc/man/knot.conf.5in deleted file mode 100644 index d091d15..0000000 --- a/doc/man/knot.conf.5in +++ /dev/null @@ -1,2887 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KNOT.CONF" "5" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -knot.conf \- Knot DNS configuration file -.SH DESCRIPTION -.sp -Configuration files for Knot DNS use simplified YAML format. Simplified means -that not all of the features are supported. -.sp -For the description of configuration items, we have to declare a meaning of -the following symbols: -.INDENT 0.0 -.IP \(bu 2 -\fBINT\fP – Integer -.IP \(bu 2 -\fBSTR\fP – Textual string -.IP \(bu 2 -\fBHEXSTR\fP – Hexadecimal string (with \fB0x\fP prefix) -.IP \(bu 2 -\fBBOOL\fP – Boolean value (\fBon\fP/\fBoff\fP or \fBtrue\fP/\fBfalse\fP) -.IP \(bu 2 -\fBTIME\fP – Number of seconds, an integer with possible time multiplier suffix -(\fBs\fP ~ 1, \fBm\fP ~ 60, \fBh\fP ~ 3600 or \fBd\fP ~ 24 * 3600) -.IP \(bu 2 -\fBSIZE\fP – Number of bytes, an integer with possible size multiplier suffix -(\fBB\fP ~ 1, \fBK\fP ~ 1024, \fBM\fP ~ 1024^2 or \fBG\fP ~ 1024^3) -.IP \(bu 2 -\fBBASE64\fP – Base64 encoded string -.IP \(bu 2 -\fBADDR\fP – IPv4 or IPv6 address -.IP \(bu 2 -\fBDNAME\fP – Domain name -.IP \(bu 2 -\fB\&...\fP – Multi\-valued item, order of the values is preserved -.IP \(bu 2 -\fB[\fP \fB]\fP – Optional value -.IP \(bu 2 -\fB|\fP – Choice -.UNINDENT -.sp -The configuration consists of several fixed sections and optional module -sections. There are 17 fixed sections (\fBmodule\fP, \fBserver\fP, \fBxdp\fP, \fBcontrol\fP, -\fBlog\fP, \fBstatistics\fP, \fBdatabase\fP, \fBkeystore\fP, \fBkey\fP, \fBremote\fP, -\fBremotes\fP, \fBacl\fP, \fBsubmission\fP, \fBdnskey\-sync\fP, \fBpolicy\fP, \fBtemplate\fP, -\fBzone\fP). -Module sections are prefixed with the \fBmod\-\fP prefix (e.g. \fBmod\-stats\fP). -.sp -Most of the sections (e.g. \fBzone\fP) are sequences of settings blocks. Each -settings block begins with a unique identifier, which can be used as a reference -from other sections (such an identifier must be defined in advance). -.sp -A multi\-valued item can be specified either as a YAML sequence: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -address: [10.0.0.1, 10.0.0.2] -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -or as more single\-valued items each on an extra line: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -address: 10.0.0.1 -address: 10.0.0.2 -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -If an item value contains spaces or other special characters, it is necessary -to enclose such a value within double quotes \fB\(dq\fP \fB\(dq\fP\&. -.sp -If not specified otherwise, an item representing a file or a directory path may -be defined either as an absolute path (starting with \fB/\fP), or a path relative -to the same directory as the default value of the item. -.SH COMMENTS -.sp -A comment begins with a \fB#\fP character and is ignored during processing. -Also each configuration section or sequence block allows a permanent -comment using the \fBcomment\fP item which is stored in the server beside the -configuration. -.SH INCLUDING CONFIGURATION -.sp -Another configuration file or files, matching a pattern, can be included at -the top level in the current file. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -include: STR -.ft P -.fi -.UNINDENT -.UNINDENT -.SS include -.sp -A path or a matching pattern specifying one or more files that are included -at the place of the include option position in the configuration. -If the path is not absolute, then it is considered to be relative to the -current file. The pattern can be an arbitrary string meeting POSIX \fIglob\fP -requirements, e.g. dir/*.conf. Matching files are processed in sorted order. -.sp -\fIDefault:\fP not set -.SH CLEARING CONFIGURATION SECTIONS -.sp -It\(aqs possible to clear specified configuration sections at given phases -of the configuration parsing. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -clear: STR -.ft P -.fi -.UNINDENT -.UNINDENT -.SS clear -.sp -A matching pattern specifying configuration sections that are cleared when -this item is parsed. This allows overriding of existing configuration -in the configuration database when including a configuration file or -ensures that some configuration wasn\(aqt specified in previous includes. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -For the pattern matching the POSIX function -\fI\%fnmatch()\fP -is used. On Linux, the GNU extension -\fI\%FNM_EXTMATCH\fP -is enabled, which allows extended pattern matching. -Examples: -.INDENT 0.0 -.IP \(bu 2 -\fBclear: zone\fP – Clears the \fBzone\fP section. -.IP \(bu 2 -\fBclear: mod\-*\fP – Clears all module sections. -.IP \(bu 2 -\fBclear: \(dq[!z]*\(dq\fP – Clears all sections not beginning with letter \fBz\fP\&. -.IP \(bu 2 -\fBclear: !(zone)\fP – (GNU only) Clears all sections except the \fBzone\fP one. -.IP \(bu 2 -\fBclear: @(zone|template)\fP – (GNU only) Clears the \fBzone\fP and \fBtemplate\fP sections. -.UNINDENT -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP not set -.SH MODULE SECTION -.sp -Dynamic modules loading configuration. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -If configured with non\-empty \fB\-\-with\-moduledir=path\fP parameter, all -shared modules in this directory will be automatically loaded. -.UNINDENT -.UNINDENT -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -module: - \- id: STR - file: STR -.ft P -.fi -.UNINDENT -.UNINDENT -.SS id -.sp -A module identifier in the form of the \fBmod\-\fP prefix and module name suffix. -.SS file -.sp -A path to a shared library file with the module implementation. -.sp -\fBWARNING:\fP -.INDENT 0.0 -.INDENT 3.5 -If the path is not absolute, the library is searched in the set of -system directories. See \fBman dlopen\fP for more details. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB${libdir}/knot/modules\-${version}\fP/module_name.so -(or \fB${path}\fP/module_name.so if configured with \fB\-\-with\-moduledir=path\fP) -.SH SERVER SECTION -.sp -General options related to the server. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -server: - identity: [STR] - version: [STR] - nsid: [STR|HEXSTR] - rundir: STR - user: STR[:STR] - pidfile: STR - udp\-workers: INT - tcp\-workers: INT - background\-workers: INT - async\-start: BOOL - tcp\-idle\-timeout: TIME - tcp\-io\-timeout: INT - tcp\-remote\-io\-timeout: INT - tcp\-max\-clients: INT - tcp\-reuseport: BOOL - tcp\-fastopen: BOOL - quic\-max\-clients: INT - quic\-outbuf\-max\-size: SIZE - quic\-idle\-close\-timeout: TIME - remote\-pool\-limit: INT - remote\-pool\-timeout: TIME - remote\-retry\-delay: INT - socket\-affinity: BOOL - udp\-max\-payload: SIZE - udp\-max\-payload\-ipv4: SIZE - udp\-max\-payload\-ipv6: SIZE - key\-file: STR - cert\-file: STR - edns\-client\-subnet: BOOL - answer\-rotation: BOOL - automatic\-acl: BOOL - proxy\-allowlist: ADDR[/INT] | ADDR\-ADDR ... - dbus\-event: none | running | zone\-updated | ksk\-submission | dnssec\-invalid ... - dbus\-init\-delay: TIME - listen: ADDR[@INT] | STR ... - listen\-quic: ADDR[@INT] ... -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -\fBCAUTION:\fP -.INDENT 0.0 -.INDENT 3.5 -When you change configuration parameters dynamically or via configuration file -reload, some parameters in the Server section require restarting the Knot server -so that the changes take effect. See below for the details. -.UNINDENT -.UNINDENT -.SS identity -.sp -An identity of the server returned in the response to the query for TXT -record \fBid.server.\fP or \fBhostname.bind.\fP in the CHAOS class (\fI\%RFC 4892\fP). -Set to an empty value to disable. -.sp -\fIDefault:\fP FQDN hostname -.SS version -.sp -A version of the server software returned in the response to the query -for TXT record \fBversion.server.\fP or \fBversion.bind.\fP in the CHAOS -class (\fI\%RFC 4892\fP). Set to an empty value to disable. -.sp -\fIDefault:\fP server version -.SS nsid -.sp -A DNS name server identifier (\fI\%RFC 5001\fP). Set to an empty value to disable. -.sp -\fIDefault:\fP FQDN hostname at the moment of the daemon start -.SS rundir -.sp -A path for storing run\-time data (PID file, unix sockets, etc.). A non\-absolute -path is relative to the \fI\%knotd\fP startup directory. -.sp -Depending on the usage of this parameter, its change may require restart of the Knot -server to take effect. -.sp -\fIDefault:\fP \fB${localstatedir}/run/knot\fP (configured with \fB\-\-with\-rundir=path\fP) -.SS user -.sp -A system user with an optional system group (\fBuser:group\fP) under which the -server is run after starting and binding to interfaces. Linux capabilities -are employed if supported. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fBroot:root\fP -.SS pidfile -.sp -A PID file \fI\%location\fP\&. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fI\%rundir\fP\fB/knot.pid\fP -.SS udp\-workers -.sp -A number of UDP workers (threads) used to process incoming queries -over UDP. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP equal to the number of online CPUs -.SS tcp\-workers -.sp -A number of TCP workers (threads) used to process incoming queries -over TCP. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP equal to the number of online CPUs, default value is at least 10 -.SS background\-workers -.sp -A number of workers (threads) used to execute background operations (zone -loading, zone updates, etc.). -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP equal to the number of online CPUs, default value is at most 10 -.SS async\-start -.sp -If enabled, server doesn\(aqt wait for the zones to be loaded and starts -responding immediately with SERVFAIL answers until the zone loads. -.sp -\fIDefault:\fP \fBoff\fP -.SS tcp\-idle\-timeout -.sp -Maximum idle time (in seconds) between requests on an inbound TCP connection. -It means if there is no activity on an inbound TCP connection during this limit, -the connection is closed by the server. -.sp -\fIMinimum:\fP \fB1\fP -.sp -\fIDefault:\fP \fB10\fP -.SS tcp\-io\-timeout -.sp -Maximum time (in milliseconds) to receive or send one DNS message over an inbound -TCP connection. It means this limit applies to normal DNS queries and replies, -incoming DDNS, and \fBoutgoing zone transfers\fP\&. The timeout is measured since some -data is already available for processing. -Set to 0 for infinity. -.sp -\fIDefault:\fP \fB500\fP (milliseconds) -.sp -\fBCAUTION:\fP -.INDENT 0.0 -.INDENT 3.5 -In order to reduce the risk of Slow Loris attacks, it\(aqs recommended setting -this limit as low as possible on public servers. -.UNINDENT -.UNINDENT -.SS tcp\-remote\-io\-timeout -.sp -Maximum time (in milliseconds) to receive or send one DNS message over an outbound -TCP connection which has already been established to a configured remote server. -It means this limit applies to incoming zone transfers, sending NOTIFY, -DDNS forwarding, and DS check or push. This timeout includes the time needed -for a network round\-trip and for a query processing by the remote. -Set to 0 for infinity. -.sp -\fIDefault:\fP \fB5000\fP (milliseconds) -.SS tcp\-reuseport -.sp -If enabled, each TCP worker listens on its own socket and the OS kernel -socket load balancing is employed using SO_REUSEPORT (or SO_REUSEPORT_LB -on FreeBSD). Due to the lack of one shared socket, the server can offer -higher response rate processing over TCP. However, in the case of -time\-consuming requests (e.g. zone transfers of a TLD zone), enabled reuseport -may result in delayed or not being responded client requests. So it is -advisable to use this option on secondary servers. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fBoff\fP -.SS tcp\-fastopen -.sp -If enabled, use TCP Fast Open for outbound TCP communication (client side): -incoming zone transfers, sending NOTIFY, and DDNS forwarding. This mode simplifies -TCP handshake and can result in better networking performance. TCP Fast Open -for inbound TCP communication (server side) isn\(aqt affected by this -configuration as it\(aqs enabled automatically if supported by OS. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -The TCP Fast Open support must also be enabled on the OS level: -.INDENT 0.0 -.IP \(bu 2 -Linux/macOS: ensure kernel parameter \fBnet.ipv4.tcp_fastopen\fP is \fB2\fP or -\fB3\fP for server side, and \fB1\fP or \fB3\fP for client side. -.IP \(bu 2 -FreeBSD: ensure kernel parameter \fBnet.inet.tcp.fastopen.server_enable\fP -is \fB1\fP for server side, and \fBnet.inet.tcp.fastopen.client_enable\fP is -\fB1\fP for client side. -.UNINDENT -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBoff\fP -.SS quic\-max\-clients -.sp -A maximum number of QUIC clients connected in parallel. -.sp -See also \fI\%quic\fP\&. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIMinimum:\fP \fB128\fP -.sp -\fIDefault:\fP \fB10000\fP (ten thousand) -.SS quic\-outbuf\-max\-size -.sp -Maximum cumulative size of memory used for buffers of unACKed -sent messages. This limit is per one UDP worker. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Set low if little memory is available (together with \fI\%quic\-max\-clients\fP -since QUIC connections are memory\-heavy). Set to high value if outgoing zone -transfers of big zone over QUIC are expected. -.UNINDENT -.UNINDENT -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIMinimum:\fP \fB1M\fP (1 MiB) -.sp -\fIDefault:\fP \fB100M\fP (100 MiB) -.SS quic\-idle\-close\-timeout -.sp -Time in seconds, after which any idle QUIC connection is gracefully closed. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIMinimum:\fP \fB1\fP -.sp -\fIDefault:\fP \fB4\fP -.SS remote\-pool\-limit -.sp -If nonzero, the server will keep up to this number of outgoing TCP connections -open for later use. This is an optimization to avoid frequent opening of -TCP connections to the same remote. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fB0\fP -.SS remote\-pool\-timeout -.sp -The timeout in seconds after which the unused kept\-open outgoing TCP connections -to remote servers are closed. -.sp -\fIDefault:\fP \fB5\fP -.SS remote\-retry\-delay -.sp -When a connection attempt times out to some remote address, this information will be -kept for this specified time (in milliseconds) and other connections to the same address won\(aqt -be attempted. This prevents repetitive waiting for timeout on an unreachable remote. -.sp -\fIDefault:\fP \fB0\fP -.SS socket\-affinity -.sp -If enabled and if SO_REUSEPORT is available on Linux, all configured network -sockets are bound to UDP and TCP workers in order to increase the networking performance. -This mode isn\(aqt recommended for setups where the number of network card queues -is lower than the number of UDP or TCP workers. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fBoff\fP -.SS tcp\-max\-clients -.sp -A maximum number of TCP clients connected in parallel, set this below the file -descriptor limit to avoid resource exhaustion. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -It is advisable to adjust the maximum number of open files per process in your -operating system configuration. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP one half of the file descriptor limit for the server process -.SS udp\-max\-payload -.sp -Maximum EDNS0 UDP payload size default for both IPv4 and IPv6. -.sp -\fIDefault:\fP \fB1232\fP -.SS udp\-max\-payload\-ipv4 -.sp -Maximum EDNS0 UDP payload size for IPv4. -.sp -\fIDefault:\fP \fB1232\fP -.SS udp\-max\-payload\-ipv6 -.sp -Maximum EDNS0 UDP payload size for IPv6. -.sp -\fIDefault:\fP \fB1232\fP -.SS key\-file -.sp -Path to a server key PEM file which is used for DNS over QUIC communication. -A non\-absolute path of a user specified key file is relative to the -\fB@config_dir@\fP directory. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP auto\-generated key -.SS cert\-file -.sp -Path to a server certificate PEM file which is used for DNS over QUIC communication. -A non\-absolute path is relative to the \fB@config_dir@\fP directory. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP one\-time in\-memory certificate -.SS edns\-client\-subnet -.sp -Enable or disable EDNS Client Subnet support. If enabled, responses to queries -containing the EDNS Client Subnet option -always contain a valid EDNS Client Subnet option according to \fI\%RFC 7871\fP\&. -.sp -\fIDefault:\fP \fBoff\fP -.SS answer\-rotation -.sp -Enable or disable sorted\-rrset rotation in the answer section of normal replies. -The rotation shift is simply determined by a query ID. -.sp -\fIDefault:\fP \fBoff\fP -.SS automatic\-acl -.sp -If enabled, \fI\%automatic ACL\fP setting of -configured remotes is considered when evaluating authorized operations. -.sp -\fIDefault:\fP \fBoff\fP -.SS proxy\-allowlist -.sp -An ordered list of IP addresses, network subnets, or network ranges -which are allowed as a source address of proxied DNS traffic over UDP. -The supported proxy protocol is -\fI\%haproxy PROXY v2\fP\&. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -TCP is not supported. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP not set -.SS dbus\-event -.sp -Specification of server or zone states which emit a D\-Bus signal on the system -bus. The bus name is \fBcz.nic.knotd\fP, the object path is \fB/cz/nic/knotd\fP, and -the interface name is \fBcz.nic.knotd.events\fP\&. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBnone\fP – No signal is emitted. -.IP \(bu 2 -\fBrunning\fP – There are two possible signals emitted: -.INDENT 2.0 -.IP \(bu 2 -\fBstarted\fP when the server is started and all configured zones (including -catalog zones and their members) are loaded or successfully bootstrapped. -.IP \(bu 2 -\fBstopped\fP when the server shutdown sequence is initiated. -.UNINDENT -.IP \(bu 2 -\fBzone\-updated\fP – The signal \fBzone_updated\fP is emitted when a zone has been updated; -the signal parameters are \fIzone name\fP and \fIzone SOA serial\fP\&. -.IP \(bu 2 -\fBkeys\-updated\fP \- The signal \fBkeys_updated\fP is emitted when a DNSSEC key set -of this zone is updated. -.IP \(bu 2 -\fBksk\-submission\fP – The signal \fBzone_ksk_submission\fP is emitted if there is -a ready KSK present when the zone is signed; the signal parameters are -\fIzone name\fP, \fIKSK keytag\fP, and \fIKSK KASP id\fP\&. -.IP \(bu 2 -\fBdnssec\-invalid\fP – The signal \fBzone_dnssec_invalid\fP is emitted when DNSSEC -validation fails; the signal parameter is \fIzone name\fP\&. -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This function requires systemd version at least 221. -.UNINDENT -.UNINDENT -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fBnone\fP -.SS dbus\-init\-delay -.sp -Time in seconds which the server waits upon D\-Bus initialization to ensure -the D\-Bus client is ready to receive signals. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIMinimum:\fP \fB0\fP -.sp -\fIDefault:\fP \fB1\fP -.SS listen -.sp -One or more IP addresses where the server listens for incoming queries. -Optional port specification (default is 53) can be appended to each address -using \fB@\fP separator. Use \fB0.0.0.0\fP for all configured IPv4 addresses or -\fB::\fP for all configured IPv6 addresses. Filesystem path can be specified -for listening on local unix SOCK_STREAM socket. Non\-absolute path -(i.e. not starting with \fB/\fP) is relative to \fI\%rundir\fP\&. -Non\-local address binding is automatically enabled if supported by the operating system. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP not set -.SS listen\-quic -.sp -One or more IP addresses (and optionally ports) where the server listens -for incoming queries over QUIC protocol. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP not set -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Incoming \fI\%DDNS\fP over QUIC isn\(aqt supported. -The server always responds with SERVFAIL. -.UNINDENT -.UNINDENT -.SH XDP SECTION -.sp -Various options related to XDP listening, especially TCP. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -xdp: - listen: STR[@INT] | ADDR[@INT] ... - udp: BOOL - tcp: BOOL - quic: BOOL - quic\-port: INT - tcp\-max\-clients: INT - tcp\-inbuf\-max\-size: SIZE - tcp\-outbuf\-max\-size: SIZE - tcp\-idle\-close\-timeout: TIME - tcp\-idle\-reset\-timeout: TIME - tcp\-resend\-timeout: TIME - route\-check: BOOL -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -\fBCAUTION:\fP -.INDENT 0.0 -.INDENT 3.5 -When you change configuration parameters dynamically or via configuration file -reload, some parameters in the XDP section require restarting the Knot server -so that the changes take effect. -.UNINDENT -.UNINDENT -.SS listen -.sp -One or more network device names (e.g. \fBens786f0\fP) on which the \fI\%Mode XDP\fP -is enabled. Alternatively, an IP address can be used instead of a device name, -but the server will still listen on all addresses belonging to the same interface! -Optional port specification (default is 53) can be appended to each device name -or address using \fB@\fP separator. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fBCAUTION:\fP -.INDENT 0.0 -.INDENT 3.5 -If XDP workers only process regular DNS traffic over UDP, it is strongly -recommended to also \fI\%listen\fP on the addresses which are -intended to offer the DNS service, at least to fulfil the DNS requirement for -working TCP. -.UNINDENT -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Incoming \fI\%DDNS\fP over XDP isn\(aqt supported. -The server always responds with SERVFAIL. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP not set -.SS udp -.sp -If enabled, DNS over UDP is processed with XDP workers. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fBon\fP -.SS tcp -.sp -If enabled, DNS over TCP traffic is processed with XDP workers. -.sp -The TCP stack limitations: -.INDENT 0.0 -.INDENT 3.5 -.INDENT 0.0 -.IP \(bu 2 -Congestion control is not implemented. -.IP \(bu 2 -Lost packets that do not contain TCP payload may not be resend. -.IP \(bu 2 -Not optimized for transfers of non\-trivial zones. -.UNINDENT -.UNINDENT -.UNINDENT -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fBoff\fP -.SS quic -.sp -If enabled, DNS over QUIC is processed with XDP workers. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fBoff\fP -.SS quic\-port -.sp -DNS over QUIC will listen on the interfaces configured by \fI\%listen\fP, -but on different port, configured by this option. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fB853\fP -.SS tcp\-max\-clients -.sp -A maximum number of TCP clients connected in parallel. -.sp -\fIMinimum:\fP \fB1024\fP -.sp -\fIDefault:\fP \fB1000000\fP (one million) -.SS tcp\-inbuf\-max\-size -.sp -Maximum cumulative size of memory used for buffers of incompletely -received messages. -.sp -\fIMinimum:\fP \fB1M\fP (1 MiB) -.sp -\fIDefault:\fP \fB100M\fP (100 MiB) -.SS tcp\-outbuf\-max\-size -.sp -Maximum cumulative size of memory used for buffers of unACKed -sent messages. -.sp -\fIMinimum:\fP \fB1M\fP (1 MiB) -.sp -\fIDefault:\fP \fB100M\fP (100 MiB) -.SS tcp\-idle\-close\-timeout -.sp -Time in seconds, after which any idle connection is gracefully closed. -.sp -\fIMinimum:\fP \fB1\fP -.sp -\fIDefault:\fP \fB10\fP -.SS tcp\-idle\-reset\-timeout -.sp -Time in seconds, after which any idle connection is forcibly closed. -.sp -\fIMinimum:\fP \fB1\fP -.sp -\fIDefault:\fP \fB20\fP -.SS tcp\-resend\-timeout -.sp -Resend outgoing data packets (with DNS response payload) if not ACKed -before this timeout (in seconds). -.sp -\fIMinimum:\fP \fB1\fP -.sp -\fIDefault:\fP \fB5\fP -.SS route\-check -.sp -If enabled, routing information from the operating system is considered -when processing every incoming DNS packet received over the XDP interface: -.INDENT 0.0 -.IP \(bu 2 -If the outgoing interface of the corresponding DNS response differs from -the incoming one, the packet is processed normally by UDP/TCP workers -(XDP isn\(aqt used). -.IP \(bu 2 -If the destination address is blackholed, unreachable, or prohibited, -the DNS packet is dropped without any response. -.IP \(bu 2 -The destination MAC address and possible VLAN tag for the response are taken -from the routing system. -.UNINDENT -.sp -If disabled, symmetrical routing is applied. It means that the query source -MAC address is used as a response destination MAC address. Possible VLAN tag -is preserved. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This mode requires forwarding enabled on the loopback interface -(\fBsysctl \-w net.ipv4.conf.lo.forwarding=1\fP and \fBsysctl \-w net.ipv6.conf.lo.forwarding=1\fP). -If forwarding is disabled, all incoming DNS packets are dropped! -.sp -Only VLAN 802.1Q is supported. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBoff\fP -.SH CONTROL SECTION -.sp -Configuration of the server control interface. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -control: - listen: STR - backlog: INT - timeout: TIME -.ft P -.fi -.UNINDENT -.UNINDENT -.SS listen -.sp -A UNIX socket \fI\%path\fP where the server listens for -control commands. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fI\%rundir\fP\fB/knot.sock\fP -.SS backlog -.sp -The control UNIX socket listen backlog size. -.sp -Change of this parameter requires restart of the Knot server to take effect. -.sp -\fIDefault:\fP \fB5\fP -.SS timeout -.sp -Maximum time (in seconds) the control socket operations can take. -Set to 0 for infinity. -.sp -\fIDefault:\fP \fB5\fP -.SH LOG SECTION -.sp -Server can be configured to log to the standard output, standard error -output, syslog (or systemd journal if systemd is enabled) or into an arbitrary -file. -.sp -There are 6 logging severity levels: -.INDENT 0.0 -.IP \(bu 2 -\fBcritical\fP – Non\-recoverable error resulting in server shutdown. -.IP \(bu 2 -\fBerror\fP – Recoverable error, action should be taken. -.IP \(bu 2 -\fBwarning\fP – Warning that might require user action. -.IP \(bu 2 -\fBnotice\fP – Server notice or hint. -.IP \(bu 2 -\fBinfo\fP – Informational message. -.IP \(bu 2 -\fBdebug\fP – Debug or detailed message. -.UNINDENT -.sp -In the case of a missing log section, \fBwarning\fP or more serious messages -will be logged to both standard error output and syslog. The \fBinfo\fP and -\fBnotice\fP messages will be logged to standard output. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -log: - \- target: stdout | stderr | syslog | STR - server: critical | error | warning | notice | info | debug - control: critical | error | warning | notice | info | debug - zone: critical | error | warning | notice | info | debug - quic: critical | error | warning | notice | info | debug - any: critical | error | warning | notice | info | debug -.ft P -.fi -.UNINDENT -.UNINDENT -.SS target -.sp -A logging output. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBstdout\fP – Standard output. -.IP \(bu 2 -\fBstderr\fP – Standard error output. -.IP \(bu 2 -\fBsyslog\fP – Syslog or systemd journal. -.IP \(bu 2 -\fIfile_name\fP – A specific file. -.UNINDENT -.sp -With \fBsyslog\fP target, syslog service is used. However, if Knot DNS has been compiled -with systemd support and operating system has been booted with systemd, systemd journal -is used for logging instead of syslog. -.sp -A \fIfile_name\fP may be specified as an absolute path or a path relative to the -\fI\%knotd\fP startup directory. -.SS server -.sp -Minimum severity level for messages related to general operation of the server to be -logged. -.sp -\fIDefault:\fP not set -.SS control -.sp -Minimum severity level for messages related to server control to be logged. -.sp -\fIDefault:\fP not set -.SS zone -.sp -Minimum severity level for messages related to zones to be logged. -.sp -\fIDefault:\fP not set -.SS quic -.sp -Minimum severity level for messages related to QUIC to be logged. -.sp -\fIDefault:\fP not set -.SS any -.sp -Minimum severity level for all message types, except \fBquic\fP, to be logged. -.sp -\fIDefault:\fP not set -.SH STATISTICS SECTION -.sp -Periodic server statistics dumping. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -statistics: - timer: TIME - file: STR - append: BOOL -.ft P -.fi -.UNINDENT -.UNINDENT -.SS timer -.sp -A period (in seconds) after which all available statistics metrics will by written to the -\fI\%file\fP\&. -.sp -\fIDefault:\fP not set -.SS file -.sp -A file \fI\%path\fP of statistics output in the YAML format. -.sp -\fIDefault:\fP \fI\%rundir\fP\fB/stats.yaml\fP -.SS append -.sp -If enabled, the output will be appended to the \fI\%file\fP -instead of file replacement. -.sp -\fIDefault:\fP \fBoff\fP -.SH DATABASE SECTION -.sp -Configuration of databases for zone contents, DNSSEC metadata, or event timers. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -database: - storage: STR - journal\-db: STR - journal\-db\-mode: robust | asynchronous - journal\-db\-max\-size: SIZE - kasp\-db: STR - kasp\-db\-max\-size: SIZE - timer\-db: STR - timer\-db\-max\-size: SIZE - catalog\-db: str - catalog\-db\-max\-size: SIZE -.ft P -.fi -.UNINDENT -.UNINDENT -.SS storage -.sp -A data directory for storing journal, KASP, and timer databases. A non\-absolute -path is relative to the \fI\%knotd\fP startup directory. -.sp -\fIDefault:\fP \fB${localstatedir}/lib/knot\fP (configured with \fB\-\-with\-storage=path\fP) -.SS journal\-db -.sp -An explicit \fI\%specification\fP of the persistent journal database -directory. -.sp -\fIDefault:\fP \fI\%storage\fP\fB/journal\fP -.SS journal\-db\-mode -.sp -Specifies journal LMDB backend configuration, which influences performance -and durability. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBrobust\fP – The journal database disk synchronization ensures database -durability but is generally slower. -.IP \(bu 2 -\fBasynchronous\fP – The journal database disk synchronization is optimized for -better performance at the expense of lower database durability in the case of -a crash. This mode is recommended on secondary servers with many zones. -.UNINDENT -.sp -\fIDefault:\fP \fBrobust\fP -.SS journal\-db\-max\-size -.sp -The hard limit for the journal database maximum size. There is no cleanup logic -in journal to recover from reaching this limit. Journal simply starts refusing -changes across all zones. Decreasing this value has no effect if it is lower -than the actual database file size. -.sp -It is recommended to limit \fI\%journal\-max\-usage\fP -per\-zone instead of \fI\%journal\-db\-max\-size\fP -in most cases. Please keep this value larger than the sum of all zones\(aq -journal usage limits. See more details regarding -\fI\%journal behaviour\fP\&. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This value also influences server\(aqs usage of virtual memory. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB20G\fP (20 GiB), or \fB512M\fP (512 MiB) for 32\-bit -.SS kasp\-db -.sp -An explicit \fI\%specification\fP of the KASP database directory. -.sp -\fIDefault:\fP \fI\%storage\fP\fB/keys\fP -.SS kasp\-db\-max\-size -.sp -The hard limit for the KASP database maximum size. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This value also influences server\(aqs usage of virtual memory. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB500M\fP (500 MiB) -.SS timer\-db -.sp -An explicit \fI\%specification\fP of the persistent timer -database directory. -.sp -\fIDefault:\fP \fI\%storage\fP\fB/timers\fP -.SS timer\-db\-max\-size -.sp -The hard limit for the timer database maximum size. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This value also influences server\(aqs usage of virtual memory. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB100M\fP (100 MiB) -.SS catalog\-db -.sp -An explicit \fI\%specification\fP of the zone catalog -database directory. Only useful if \fI\%Catalog zones\fP are enabled. -.sp -\fIDefault:\fP \fI\%storage\fP\fB/catalog\fP -.SS catalog\-db\-max\-size -.sp -The hard limit for the catalog database maximum size. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This value also influences server\(aqs usage of virtual memory. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB20G\fP (20 GiB), or \fB512M\fP (512 MiB) for 32\-bit -.SH KEYSTORE SECTION -.sp -DNSSEC keystore configuration. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -keystore: - \- id: STR - backend: pem | pkcs11 - config: STR - key\-label: BOOL -.ft P -.fi -.UNINDENT -.UNINDENT -.SS id -.sp -A keystore identifier. -.SS backend -.sp -A key storage backend type. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBpem\fP – PEM files. -.IP \(bu 2 -\fBpkcs11\fP – PKCS #11 storage. -.UNINDENT -.sp -\fIDefault:\fP \fBpem\fP -.SS config -.sp -A backend specific configuration. A directory with PEM files (the path can -be specified as a relative path to \fI\%kasp\-db\fP) or -a configuration string for PKCS #11 storage (\fI \fP). -The PKCS #11 URI Scheme is defined in \fI\%RFC 7512\fP\&. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Example configuration string for PKCS #11: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -\(dqpkcs11:token=knot;pin\-value=1234 /usr/lib64/pkcs11/libsofthsm2.so\(dq -.ft P -.fi -.UNINDENT -.UNINDENT -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fI\%kasp\-db\fP\fB/keys\fP -.SS key\-label -.sp -If enabled in combination with the PKCS #11 \fI\%backend\fP, generated keys -are labeled in the form \fB KSK|ZSK\fP\&. -.sp -\fIDefault:\fP \fBoff\fP -.SH KEY SECTION -.sp -Shared TSIG keys used to authenticate communication with the server. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -key: - \- id: DNAME - algorithm: hmac\-md5 | hmac\-sha1 | hmac\-sha224 | hmac\-sha256 | hmac\-sha384 | hmac\-sha512 - secret: BASE64 -.ft P -.fi -.UNINDENT -.UNINDENT -.SS id -.sp -A key name identifier. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This value MUST be exactly the same as the name of the TSIG key on the -opposite primary/secondary server(s). -.UNINDENT -.UNINDENT -.SS algorithm -.sp -A TSIG key algorithm. See -\fI\%TSIG Algorithm Numbers\fP\&. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBhmac\-md5\fP -.IP \(bu 2 -\fBhmac\-sha1\fP -.IP \(bu 2 -\fBhmac\-sha224\fP -.IP \(bu 2 -\fBhmac\-sha256\fP -.IP \(bu 2 -\fBhmac\-sha384\fP -.IP \(bu 2 -\fBhmac\-sha512\fP -.UNINDENT -.sp -\fIDefault:\fP not set -.SS secret -.sp -Shared key secret. -.sp -\fIDefault:\fP not set -.SH REMOTE SECTION -.sp -Definitions of remote servers for outgoing connections (source of a zone -transfer, target for a notification, etc.). -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -remote: - \- id: STR - address: ADDR[@INT] | STR ... - via: ADDR[@INT] ... - quic: BOOL - key: key_id - cert\-key: BASE64 ... - block\-notify\-after\-transfer: BOOL - no\-edns: BOOL - automatic\-acl: BOOL -.ft P -.fi -.UNINDENT -.UNINDENT -.SS id -.sp -A remote identifier. -.SS address -.sp -An ordered list of destination IP addresses or UNIX socket paths which are -used for communication with the remote server. Non\-absolute path -(i.e. not starting with \fB/\fP) is relative to \fI\%rundir\fP\&. -Optional destination port (default is 53 for UDP/TCP and 853 for QUIC) -can be appended to the address using \fB@\fP separator. -The addresses are tried in sequence until the -remote is reached. -.sp -\fIDefault:\fP not set -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -If the remote is contacted and it refuses to perform requested action, -no more addresses will be tried for this remote. -.UNINDENT -.UNINDENT -.SS via -.sp -An ordered list of source IP addresses which are used as source addresses -for communication with the remote. For the N\-th \fI\%remote address\fP, -the last, but at most N\-th, specified \fI\%via address\fP -of the same family is used. -This option can help if the server listens on more addresses. -Optional source port (default is random) can be appended -to the address using \fB@\fP separator. -.sp -\fIDefault:\fP not set -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -For the following configuration: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -remote: - \- id: example - address: [198.51.100.10, 2001:db8::10, 198.51.100.20, 2001:db8::20] - via: [198.51.100.1, 198.51.100.2, 2001:db8::1] -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -the (\fBvia\fP \-> \fBaddress\fP) mapping is: -.INDENT 0.0 -.IP \(bu 2 -\fB198.51.100.1\fP \-> \fB198.51.100.10\fP -.IP \(bu 2 -\fB2001:db8::1\fP \-> \fB2001:db8::10\fP -.IP \(bu 2 -\fB198.51.100.2\fP \-> \fB198.51.100.20\fP -.IP \(bu 2 -\fB2001:db8::1\fP \-> \fB2001:db8::20\fP -.UNINDENT -.UNINDENT -.UNINDENT -.SS quic -.sp -If this option is set, the QUIC protocol will be used for outgoing communication -with this remote. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -One connection per each remote is opened; \fI\%remote\-pool\-limit\fP -does not take effect for QUIC. However, fast QUIC handshakes utilizing obtained -session tickets are used for reopening connections to recently (up to 1 day) -queried remotes. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBoff\fP -.SS key -.sp -A \fI\%reference\fP to the TSIG key which is used to authenticate -the communication with the remote server. -.sp -\fIDefault:\fP not set -.SS cert\-key -.sp -An ordered list of remote certificate public key PINs. If the list is non\-empty, -communication with the remote is possible only via QUIC protocol and -a peer certificate is required. The peer certificate key must match one of the -specified PINs. -.sp -A PIN is a unique identifier that represents the public key of the peer certificate. -It\(aqs a base64\-encoded SHA\-256 hash of the public key. This identifier -remains the same on a certificate renewal. -.sp -\fIDefault:\fP not set -.SS block\-notify\-after\-transfer -.sp -When incoming AXFR/IXFR from this remote (as a primary server), suppress -sending NOTIFY messages to all configured secondary servers. -.sp -\fIDefault:\fP \fBoff\fP -.SS no\-edns -.sp -If enabled, no OPT record (EDNS) is inserted to outgoing requests to this -remote server. This mode is necessary for communication with some broken -implementations (e.g. Windows Server 2016). -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This option effectively disables \fI\%zone expire\fP timer -updates via EDNS EXPIRE option specified in \fI\%RFC 7314\fP\&. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBoff\fP -.SS automatic\-acl -.sp -If enabled, some authorized operations for the remote are automatically allowed -based on the context: -.INDENT 0.0 -.IP \(bu 2 -Incoming NOTIFY is allowed from the remote if it\(aqs configured as a -\fI\%primary server\fP for the zone. -.IP \(bu 2 -Outgoing zone transfer is allowed to the remote if it\(aqs configured as a -\fI\%NOTIFY target\fP for the zone. -.UNINDENT -.sp -Automatic ACL rules are evaluated before explicit \fI\%zone ACL\fP configuration. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This functionality requires global activation via -\fI\%automatic\-acl\fP in the server section. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBon\fP -.SH REMOTES SECTION -.sp -Definitions of groups of remote servers. Remote grouping can simplify the -configuration. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -remotes: - \- id: STR - remote: remote_id ... -.ft P -.fi -.UNINDENT -.UNINDENT -.SS id -.sp -A remote group identifier. -.SS remote -.sp -An ordered list of \fI\%references\fP to remote server definitions. -.sp -\fIDefault:\fP not set -.SH ACL SECTION -.sp -Access control list rule definitions. An ACL rule is a description of one -or more authorized actions (zone transfer request, zone change notification, -and dynamic DNS update) which are allowed to be processed or denied. Normal -DNS queries are always allowed. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -acl: - \- id: STR - address: ADDR[/INT] | ADDR\-ADDR | STR ... - key: key_id ... - cert\-key: BASE64 ... - remote: remote_id | remotes_id ... - action: query | notify | transfer | update ... - deny: BOOL - update\-type: STR ... - update\-owner: key | zone | name - update\-owner\-match: sub\-or\-equal | equal | sub | pattern - update\-owner\-name: STR ... -.ft P -.fi -.UNINDENT -.UNINDENT -.SS id -.sp -An ACL rule identifier. -.SS address -.sp -An ordered list of IP addresses, absolute UNIX socket paths, network subnets, -or network ranges. The query\(aqs -source address must match one of them. If this item is not set, address match is not -required. -.sp -\fIDefault:\fP not set -.SS key -.sp -An ordered list of \fI\%reference\fPs to TSIG keys. The query must -match one of them. If this item is not set, transaction authentication is not used. -.sp -\fIDefault:\fP not set -.SS cert\-key -.sp -An ordered list of remote certificate public key PINs. If the list is non\-empty, -communication with the remote is possible only via QUIC protocol and -a peer certificate is required. The peer certificate key must match one of the -specified PINs. -.sp -A PIN is a unique identifier that represents the public key of the peer certificate. -It\(aqs a base64\-encoded SHA\-256 hash of the public key. This identifier -remains the same on a certificate renewal. -.sp -\fIDefault:\fP not set -.SS remote -.sp -An ordered list of references \fI\%remote\fP and -\fI\%remotes\fP\&. The query must -match one of the remotes. Specifically, one of the remote\(aqs addresses and remote\(aqs -TSIG key if configured must match. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This option cannot be specified along with the \fI\%address\fP or -\fI\%key\fP option at one ACL item. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP not set -.SS action -.sp -An ordered list of allowed, or denied, actions (request types). -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBquery\fP – Allow regular DNS query. As normal queries are always allowed, -this action is only useful in combination with \fI\%TSIG key\fP\&. -.IP \(bu 2 -\fBnotify\fP – Allow incoming notify (NOTIFY). -.IP \(bu 2 -\fBtransfer\fP – Allow zone transfer (AXFR, IXFR). -.IP \(bu 2 -\fBupdate\fP – Allow zone updates (DDNS). -.UNINDENT -.sp -\fIDefault:\fP \fBquery\fP -.SS deny -.sp -If enabled, instead of allowing, deny the specified \fI\%action\fP, -\fI\%address\fP, \fI\%key\fP, or combination if these -items. If no action is specified, deny all actions. -.sp -\fIDefault:\fP \fBoff\fP -.SS update\-type -.sp -A list of allowed types of Resource Records in a zone update. Every record in an update -must match one of the specified types. -.sp -\fIDefault:\fP not set -.SS update\-owner -.sp -This option restricts possible owners of Resource Records in a zone update by comparing -them to either the \fI\%TSIG key\fP identity, the current zone name, or to a list of -domain names given by the \fI\%update\-owner\-name\fP option. -The comparison method is given by the \fI\%update\-owner\-match\fP option. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBkey\fP — The owner of each updated RR must match the identity of the TSIG key if used. -.IP \(bu 2 -\fBname\fP — The owner of each updated RR must match at least one name in the -\fI\%update\-owner\-name\fP list. -.IP \(bu 2 -\fBzone\fP — The owner of each updated RR must match the current zone name. -.UNINDENT -.sp -\fIDefault:\fP not set -.SS update\-owner\-match -.sp -This option defines how the owners of Resource Records in an update are matched to the domain name(s) -set by the \fI\%update\-owner\fP option. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBsub\-or\-equal\fP — The owner of each RR in an update must either be equal to -or be a subdomain of at least one domain name set by \fI\%update\-owner\fP\&. -.IP \(bu 2 -\fBequal\fP — The owner of each updated RR must be equal to at least one domain -name set by \fI\%update\-owner\fP\&. -.IP \(bu 2 -\fBsub\fP — The owner of each updated RR must be a subdomain of, but MUST NOT -be equal to at least one domain name set by \fI\%update\-owner\fP\&. -.IP \(bu 2 -\fBpattern\fP — The owner of each updated RR must match a pattern specified by -\fI\%update\-owner\fP\&. The pattern can be an arbitrary FQDN or non\-FQDN -domain name. If a label consists of one \fB*\fP (asterisk) character, it -matches any label. More asterisk labels can be specified. -.UNINDENT -.sp -\fIDefault:\fP \fBsub\-or\-equal\fP -.SS update\-owner\-name -.sp -A list of allowed owners of RRs in a zone update used with \fI\%update\-owner\fP -set to \fBname\fP\&. Every listed owner name which is not FQDN (i.e. it doesn\(aqt end -in a dot) is considered as if it was appended with the target zone name. -Such a relative owner name specification allows better ACL rule reusability across -multiple zones. -.sp -\fIDefault:\fP not set -.SH SUBMISSION SECTION -.sp -Parameters of KSK submission checks. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -submission: - \- id: STR - parent: remote_id | remotes_id ... - check\-interval: TIME - timeout: TIME - parent\-delay: TIME -.ft P -.fi -.UNINDENT -.UNINDENT -.SS id -.sp -A submission identifier. -.SS parent -.sp -A list of references \fI\%remote\fP and \fI\%remotes\fP -to parent\(aqs DNS servers to be checked for -presence of corresponding DS records in the case of KSK submission. All of them must -have a corresponding DS for the rollover to continue. If none is specified, the -rollover must be pushed forward manually. -.sp -\fIDefault:\fP not set -.sp -\fBTIP:\fP -.INDENT 0.0 -.INDENT 3.5 -A DNSSEC\-validating resolver can be set as a parent. -.UNINDENT -.UNINDENT -.SS check\-interval -.sp -Interval (in seconds) for periodic checks of DS presence on parent\(aqs DNS -servers, in the case of the KSK submission. -.sp -\fIDefault:\fP \fB1h\fP (1 hour) -.SS timeout -.sp -After this time period (in seconds) the KSK submission is automatically considered -successful, even if all the checks were negative or no parents are configured. -Set to 0 for infinity. -.sp -\fIDefault:\fP \fB0\fP -.SS parent\-delay -.sp -After successful parent DS check, wait for this period (in seconds) before -continuing the next key roll\-over step. This delay shall cover the propagation -delay of update in the parent zone. -.sp -\fIDefault:\fP \fB0\fP -.SH DNSKEY-SYNC SECTION -.sp -Parameters of DNSKEY dynamic\-update synchronization. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -dnskey\-sync: - \- id: STR - remote: remote_id | remotes_id ... - check\-interval: TIME -.ft P -.fi -.UNINDENT -.UNINDENT -.SS id -.sp -A dnskey\-sync identifier. -.SS remote -.sp -A list of references \fI\%remote\fP and \fI\%remotes\fP -to other signers or common master, which the DDNS updates with -DNSKEY/CDNSKEY/CDS records shall be sent to. -.sp -\fIDefault:\fP not set -.SS check\-interval -.sp -If the last DNSKEY sync failed or resulted in any change, re\-check -the consistence after this interval (in seconds) and re\-try if needed. -.sp -\fIDefault:\fP \fB60\fP (1 minute) -.SH POLICY SECTION -.sp -DNSSEC policy configuration. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -policy: - \- id: STR - keystore: keystore_id - manual: BOOL - single\-type\-signing: BOOL - algorithm: rsasha1 | rsasha1\-nsec3\-sha1 | rsasha256 | rsasha512 | ecdsap256sha256 | ecdsap384sha384 | ed25519 | ed448 - ksk\-size: SIZE - zsk\-size: SIZE - ksk\-shared: BOOL - dnskey\-ttl: TIME - zone\-max\-ttl: TIME - keytag\-modulo: INT/INT - ksk\-lifetime: TIME - zsk\-lifetime: TIME - delete\-delay: TIME - propagation\-delay: TIME - rrsig\-lifetime: TIME - rrsig\-refresh: TIME - rrsig\-pre\-refresh: TIME - reproducible\-signing: BOOL - nsec3: BOOL - nsec3\-iterations: INT - nsec3\-opt\-out: BOOL - nsec3\-salt\-length: INT - nsec3\-salt\-lifetime: TIME - signing\-threads: INT - ksk\-submission: submission_id - ds\-push: remote_id | remotes_id ... - cds\-cdnskey\-publish: none | delete\-dnssec | rollover | always | double\-ds - cds\-digest\-type: sha256 | sha384 - dnskey\-management: full | incremental - offline\-ksk: BOOL - unsafe\-operation: none | no\-check\-keyset | no\-update\-dnskey | no\-update\-nsec | no\-update\-expired ... -.ft P -.fi -.UNINDENT -.UNINDENT -.SS id -.sp -A policy identifier. -.SS keystore -.sp -A \fI\%reference\fP to a keystore holding private key material -for zones. -.sp -\fIDefault:\fP an imaginary keystore with all default values -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -A configured keystore called \(dqdefault\(dq won\(aqt be used unless explicitly referenced. -.UNINDENT -.UNINDENT -.SS manual -.sp -If enabled, automatic key management is not used. -.sp -\fIDefault:\fP \fBoff\fP -.SS single\-type\-signing -.sp -If enabled, Single\-Type Signing Scheme is used in the automatic key management -mode. -.sp -\fIDefault:\fP \fBoff\fP (\fI\%module onlinesign\fP has default \fBon\fP) -.SS algorithm -.sp -An algorithm of signing keys and issued signatures. See -\fI\%DNSSEC Algorithm Numbers\fP\&. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBrsasha1\fP -.IP \(bu 2 -\fBrsasha1\-nsec3\-sha1\fP -.IP \(bu 2 -\fBrsasha256\fP -.IP \(bu 2 -\fBrsasha512\fP -.IP \(bu 2 -\fBecdsap256sha256\fP -.IP \(bu 2 -\fBecdsap384sha384\fP -.IP \(bu 2 -\fBed25519\fP -.IP \(bu 2 -\fBed448\fP -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Ed25519 algorithm is only available if compiled with GnuTLS 3.6.0+. -.sp -Ed448 algorithm is only available if compiled with GnuTLS 3.6.12+ and Nettle 3.6+. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBecdsap256sha256\fP -.SS ksk\-size -.sp -A length of newly generated KSK or -CSK keys. -.sp -\fIDefault:\fP \fB2048\fP (rsa*), \fB256\fP (ecdsap256), \fB384\fP (ecdsap384), \fB256\fP (ed25519), -\fB456\fP (ed448) -.SS zsk\-size -.sp -A length of newly generated ZSK keys. -.sp -\fIDefault:\fP see default for \fI\%ksk\-size\fP -.SS ksk\-shared -.sp -If enabled, all zones with this policy assigned will share one or more KSKs. -More KSKs can be shared during a KSK rollover. -.sp -\fBWARNING:\fP -.INDENT 0.0 -.INDENT 3.5 -As the shared KSK set is bound to the policy \fI\%id\fP, renaming the -policy breaks this connection and new shared KSK set is initiated when -a new KSK is needed. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBoff\fP -.SS dnskey\-ttl -.sp -A TTL value for DNSKEY records added into zone apex. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Has influence over ZSK key lifetime. -.UNINDENT -.UNINDENT -.sp -\fBWARNING:\fP -.INDENT 0.0 -.INDENT 3.5 -Ensure all DNSKEYs with updated TTL are propagated before any subsequent -DNSKEY rollover starts. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP zone SOA TTL -.SS zone\-max\-ttl -.sp -Declare (override) maximal TTL value among all the records in zone. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -It\(aqs generally recommended to override the maximal TTL computation by setting this -explicitly whenever possible. It\(aqs required for \fI\%DNSSEC Offline KSK\fP and -really reasonable when records are generated dynamically -(e.g. by a \fI\%module\fP). -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP computed after zone is loaded -.SS keytag\-modulo -.sp -Specifies that the keytags of any generated keys shall be congruent by specified modulo. -The option value must be a string in the format \fBR/M\fP, where \fBR < M <= 256\fP are -positive integers. Whenever a DNSSEC key is generated, it is ensured -that \fBkeytag % M == R\fP\&. This prevents keytag conflict in \fI\%DNSSEC Offline KSK\fP -or \fI\%DNSSEC multi\-signer\fP (and possibly other) setups. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This only applies to newly generated keys when they are generated. Keys from -before this option and keys imported from elsewhere might not fulfill the policy. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB0/1\fP -.SS ksk\-lifetime -.sp -A period (in seconds) between KSK generation and the next rollover initiation. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -KSK key lifetime is also influenced by propagation\-delay, dnskey\-ttl, -and KSK submission delay. -.sp -Zero (aka infinity) value causes no KSK rollover as a result. -.sp -This applies for CSK lifetime if single\-type\-signing is enabled. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB0\fP (infinity) -.SS zsk\-lifetime -.sp -A period (in seconds) between ZSK activation and the next rollover initiation. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -More exactly, this period is measured since a ZSK is activated, -and after this, a new ZSK is generated to replace it within -following roll\-over. -.sp -As a consequence, in normal operation, this results in the period -of ZSK generation being \fIzsk\-lifetime + propagation\-delay + dnskey_ttl\fP\&. -.sp -Zero (aka infinity) value causes no ZSK rollover as a result. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB30d\fP (30 days) -.SS delete\-delay -.sp -Once a key (KSK or ZSK) is rolled\-over and removed from the zone, -keep it in the KASP database for at least this period (in seconds) before deleting -it completely. This might be useful in some troubleshooting cases when resurrection -is needed. -.sp -\fIDefault:\fP \fB0\fP -.SS propagation\-delay -.sp -An extra delay added for each key rollover step. This value (in seconds) -should be high enough to cover propagation of data from the primary server -to all secondary servers, as well as the duration of signing routine itself -and possible outages in signing and propagation infrastructure. In other -words, this delay should ensure that within this period of time after -planned change of the key set, all public\-facing secondaries will already -serve new DNSKEY RRSet for sure. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Has influence over ZSK key lifetime. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB1h\fP (1 hour) -.SS rrsig\-lifetime -.sp -A validity period (in seconds) of newly issued signatures. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -The RRSIG\(aqs signature inception time is set to 90 minutes in the past. This -time period is not counted to the signature lifetime. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB14d\fP (14 days) -.SS rrsig\-refresh -.sp -A period (in seconds) how long at least before a signature expiration the signature -will be refreshed, in order to prevent expired RRSIGs on secondary servers or -resolvers\(aq caches. -.sp -\fIDefault:\fP 0.1 * \fI\%rrsig\-lifetime\fP + \fI\%propagation\-delay\fP + \fI\%zone\-max\-ttl\fP -.SS rrsig\-pre\-refresh -.sp -A period (in seconds) how long at most before a signature refresh time the signature -might be refreshed, in order to refresh RRSIGs in bigger batches on a frequently updated -zone (avoid re\-sign event too often). -.sp -\fIDefault:\fP \fB1h\fP (1 hour) -.SS reproducible\-signing -.sp -For ECDSA algorithms, generate RRSIG signatures deterministically (\fI\%RFC 6979\fP). -Besides better theoretical cryptographic security, this mode allows significant -speed\-up of loading signed (by the same method) zones. However, the zone signing -is a bit slower. -.sp -\fIDefault:\fP \fBoff\fP -.SS nsec3 -.sp -Specifies if NSEC3 will be used instead of NSEC. -.sp -\fIDefault:\fP \fBoff\fP -.SS nsec3\-iterations -.sp -A number of additional times the hashing is performed. -.sp -\fIDefault:\fP \fB0\fP -.SS nsec3\-opt\-out -.sp -If set, NSEC3 records won\(aqt be created for insecure delegations. -This speeds up the zone signing and reduces overall zone size. -.sp -\fBWARNING:\fP -.INDENT 0.0 -.INDENT 3.5 -NSEC3 with the Opt\-Out bit set no longer works as a proof of non\-existence -in this zone. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBoff\fP -.SS nsec3\-salt\-length -.sp -A length of a salt field in octets, which is appended to the original owner -name before hashing. -.sp -\fIDefault:\fP \fB8\fP -.SS nsec3\-salt\-lifetime -.sp -A validity period (in seconds) of newly issued salt field. -.sp -Zero value means infinity. -.sp -Special value \fI\-1\fP triggers re\-salt every time when active ZSK changes. -This optimizes the number of big changes to the zone. -.sp -\fIDefault:\fP \fB30d\fP (30 days) -.SS signing\-threads -.sp -When signing zone or update, use this number of threads for parallel signing. -.sp -Those are extra threads independent of \fI\%Background workers\fP\&. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Some steps of the DNSSEC signing operation are not parallelized. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB1\fP (no extra threads) -.SS ksk\-submission -.sp -A reference to \fI\%submission\fP section holding parameters of -KSK submission checks. -.sp -\fIDefault:\fP not set -.SS ds\-push -.sp -Optional references \fI\%remote\fP and \fI\%remotes\fP -to authoritative DNS server of the -parent\(aqs zone. The remote server must be configured to accept DS record -updates via DDNS. Whenever a CDS record in the local zone is changed, the -corresponding DS record is sent as a dynamic update (DDNS) to the parent -DNS server. All previous DS records are deleted within the DDNS message. -It\(aqs possible to manage both child and parent zones by the same Knot DNS server. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This feature requires \fI\%cds\-cdnskey\-publish\fP -not to be set to \fBnone\fP\&. -.UNINDENT -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -The mentioned change to CDS record usually means that a KSK roll\-over is running -and the new key being rolled\-in is in \(dqready\(dq state already for the period of -\fI\%propagation\-delay\fP\&. -.UNINDENT -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Module \fI\%Onlinesign\fP doesn\(aqt support DS push. -.UNINDENT -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -When turning this feature on while a KSK roll\-over is already running, it might -not take effect for the already\-running roll\-over. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP not set -.SS dnskey\-sync -.sp -A reference to \fI\%dnskey\-sync\fP section holding parameters -of DNSKEY synchronization. -.sp -\fIDefault:\fP not set -.SS cds\-cdnskey\-publish -.sp -Controls if and how shall the CDS and CDNSKEY be published in the zone. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBnone\fP – Never publish any CDS or CDNSKEY records in the zone. -.IP \(bu 2 -\fBdelete\-dnssec\fP – Publish special CDS and CDNSKEY records indicating turning off DNSSEC. -.IP \(bu 2 -\fBrollover\fP – Publish CDS and CDNSKEY records for ready and not yet active KSK (submission phase of KSK rollover). -.IP \(bu 2 -\fBalways\fP – Always publish one CDS and one CDNSKEY records for the current KSK. -.IP \(bu 2 -\fBdouble\-ds\fP – Always publish up to two CDS and two CDNSKEY records for ready and/or active KSKs. -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -If the zone keys are managed manually, the CDS and CDNSKEY rrsets may contain -more records depending on the keys available. -.UNINDENT -.UNINDENT -.sp -\fBWARNING:\fP -.INDENT 0.0 -.INDENT 3.5 -The \fBdouble\-ds\fP value does not trigger double\-DS roll\-over method. That method is -only supported when performed manually, with unset \fI\%ksk\-submission\fP\&. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBrollover\fP -.SS cds\-digest\-type -.sp -Specify digest type for published CDS records. -.sp -\fIDefault:\fP \fBsha256\fP -.SS dnskey\-management -.sp -Specify how the DNSKEY, CDNSKEY, and CDS RRSets at the zone apex are handled -when (re\-)signing the zone. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBfull\fP – Upon every zone (re\-)sign, delete all unknown DNSKEY, CDNSKEY, and CDS -records and keep just those that are related to the zone keys stored in the KASP database. -.IP \(bu 2 -\fBincremental\fP – Keep unknown DNSKEY, CDNSKEY, and CDS records in the zone, and -modify server\-managed records incrementally by employing changes in the KASP database. -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Prerequisites for \fIincremental\fP: -.INDENT 0.0 -.IP \(bu 2 -The \fI\%Offline KSK\fP isn\(aqt supported. -.IP \(bu 2 -The \fI\%delete\-delay\fP is long enough to cover possible daemon -shutdown (e.g. due to server maintenance). -.IP \(bu 2 -Avoided manual deletion of keys with \fI\%keymgr\fP\&. -.UNINDENT -.sp -Otherwise there might remain some DNSKEY records in the zone, belonging to -deleted keys. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBfull\fP -.SS offline\-ksk -.sp -Specifies if \fI\%Offline KSK\fP feature is enabled. -.sp -\fIDefault:\fP \fBoff\fP -.SS unsafe\-operation -.sp -Turn off some DNSSEC safety features. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBnone\fP – Nothing disabled. -.IP \(bu 2 -\fBno\-check\-keyset\fP – Don\(aqt check active keys in present algorithms. This may -lead to violation of \fI\%RFC 4035#section\-2.2\fP\&. -.IP \(bu 2 -\fBno\-update\-dnskey\fP – Don\(aqt maintain/update DNSKEY, CDNSKEY, and CDS records -in the zone apex according to KASP database. Juste leave them as they are in the zone. -.IP \(bu 2 -\fBno\-update\-nsec\fP – Don\(aqt maintain/update NSEC/NSEC3 chain. Leave all the records -as they are in the zone. -.IP \(bu 2 -\fBno\-update\-expired\fP – Don\(aqt update expired RRSIGs. -.UNINDENT -.sp -Multiple values may be specified. -.sp -\fBWARNING:\fP -.INDENT 0.0 -.INDENT 3.5 -This mode is intended for DNSSEC experts who understand the corresponding consequences. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBnone\fP -.SH TEMPLATE SECTION -.sp -A template is shareable zone settings, which can simplify configuration by -reducing duplicates. A special default template (with the \fIdefault\fP identifier) -can be used for global zone configuration or as an implicit configuration -if a zone doesn\(aqt have another template specified. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -template: - \- id: STR - global\-module: STR/STR ... - # All zone options (excluding \(aqtemplate\(aq item) -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -If an item is explicitly specified both in the referenced template and -the zone, the template item value is overridden by the zone item value. -.UNINDENT -.UNINDENT -.SS id -.sp -A template identifier. -.SS global\-module -.sp -An ordered list of references to query modules in the form of \fImodule_name\fP or -\fImodule_name/module_id\fP\&. These modules apply to all queries. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This option is only available in the \fIdefault\fP template. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP not set -.SH ZONE SECTION -.sp -Definition of zones served by the server. -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -zone: - \- domain: DNAME - template: template_id - storage: STR - file: STR - master: remote_id | remotes_id ... - ddns\-master: remote_id - notify: remote_id | remotes_id ... - acl: acl_id ... - master\-pin\-tolerance: TIME - provide\-ixfr: BOOL - semantic\-checks: BOOL | soft - default\-ttl: TIME - zonefile\-sync: TIME - zonefile\-load: none | difference | difference\-no\-serial | whole - journal\-content: none | changes | all - journal\-max\-usage: SIZE - journal\-max\-depth: INT - ixfr\-benevolent: BOOL - ixfr\-by\-one: BOOL - ixfr\-from\-axfr: BOOL - zone\-max\-size : SIZE - adjust\-threads: INT - dnssec\-signing: BOOL - dnssec\-validation: BOOL - dnssec\-policy: policy_id - ds\-push: remote_id | remotes_id ... - zonemd\-verify: BOOL - zonemd\-generate: none | zonemd\-sha384 | zonemd\-sha512 | remove - serial\-policy: increment | unixtime | dateserial - serial\-modulo: INT/INT - reverse\-generate: DNAME - refresh\-min\-interval: TIME - refresh\-max\-interval: TIME - retry\-min\-interval: TIME - retry\-max\-interval: TIME - expire\-min\-interval: TIME - expire\-max\-interval: TIME - catalog\-role: none | interpret | generate | member - catalog\-template: template_id ... - catalog\-zone: DNAME - catalog\-group: STR - module: STR/STR ... -.ft P -.fi -.UNINDENT -.UNINDENT -.SS domain -.sp -A zone name identifier. -.SS template -.sp -A \fI\%reference\fP to a configuration template. -.sp -\fIDefault:\fP not set or \fBdefault\fP (if the template exists) -.SS storage -.sp -A data directory for storing zone files. A non\-absolute path is relative to -the \fI\%knotd\fP startup directory. -.sp -\fIDefault:\fP \fB${localstatedir}/lib/knot\fP (configured with \fB\-\-with\-storage=path\fP) -.SS file -.sp -A \fI\%path\fP to the zone file. It is also possible to use -the following formatters: -.INDENT 0.0 -.IP \(bu 2 -\fB%c[\fP\fIN\fP\fB]\fP or \fB%c[\fP\fIN\fP\fB\-\fP\fIM\fP\fB]\fP – Means the \fIN\fPth -character or a sequence of characters beginning from the \fIN\fPth and ending -with the \fIM\fPth character of the textual zone name (see \fB%s\fP). The -indexes are counted from 0 from the left. All dots (including the terminal -one) are considered. If the character is not available, the formatter has no effect. -.IP \(bu 2 -\fB%l[\fP\fIN\fP\fB]\fP – Means the \fIN\fPth label of the textual zone name -(see \fB%s\fP). The index is counted from 0 from the right (0 ~ TLD). -If the label is not available, the formatter has no effect. -.IP \(bu 2 -\fB%s\fP – Means the current zone name in the textual representation. -The zone name doesn\(aqt include the terminating dot (the result for the root -zone is the empty string!). -.IP \(bu 2 -\fB%%\fP – Means the \fB%\fP character. -.UNINDENT -.sp -\fBWARNING:\fP -.INDENT 0.0 -.INDENT 3.5 -Beware of special characters which are escaped or encoded in the \eDDD form -where DDD is corresponding decimal ASCII code. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fI\%storage\fP\fB/%s.zone\fP -.SS master -.sp -An ordered list of references \fI\%remote\fP and -\fI\%remotes\fP to zone primary servers -(formerly known as master servers). -Empty value is allowed for template value overriding. -.sp -\fIDefault:\fP not set -.SS ddns\-master -.sp -A \fI\%reference\fP to a zone primary master where DDNS messages -should be forwarded to. If not specified, the first \fI\%master\fP -server is used. -.sp -If set to the empty value (\(dq\(dq), incoming DDNS messages aren\(aqt forwarded but are applied -to the local zone instead, no matter if it is a secondary server. This is only allowed in -combination with \fI\%dnssec\-signing\fP enabled. -.sp -\fIDefault:\fP not set -.SS notify -.sp -An ordered list of references \fI\%remote\fP and -\fI\%remotes\fP to secondary servers to which notify -message is sent if the zone changes. -Empty value is allowed for template value overriding. -.sp -\fIDefault:\fP not set -.SS acl -.sp -An ordered list of \fI\%references\fP to ACL rules which can allow -or disallow zone transfers, updates or incoming notifies. -.sp -\fIDefault:\fP not set -.SS master\-pin\-tolerance -.sp -If set to a nonzero value on a secondary, always request AXFR/IXFR from the same -primary as the last time, effectively pinning one primary. Only when another -primary is updated and the current one lags behind for the specified amount of time -(defined by this option in seconds), change to the updated primary and force AXFR. -.sp -This option is useful when multiple primaries may have different zone history -in their journals, making it unsafe to combine interchanged IXFR -from different primaries. -.sp -\fIDefault:\fP \fB0\fP (disabled) -.SS provide\-ixfr -.sp -If disabled, the server is forced to respond with AXFR to IXFR queries. -If enabled, IXFR requests are responded normally. -.sp -\fIDefault:\fP \fBon\fP -.SS semantic\-checks -.sp -Selects if extra zone semantic checks are used or impacts of the mandatory checks. -.sp -There are several mandatory checks which are always enabled and cannot be turned -off. An error in a mandatory check causes the zone not to be loaded. Most of -the mandatory checks can be weakened by setting \fBsoft\fP, which allows the zone to -be loaded even if the check fails. -.sp -If enabled, extra checks are used. These checks don\(aqt prevent the zone from loading. -.sp -The mandatory checks are applied to zone files, zone transfers, and updates via -control interface. The extra checks are applied to zone files only! -.sp -Mandatory checks: -.INDENT 0.0 -.IP \(bu 2 -Missing SOA record at the zone apex (\fI\%RFC 1034\fP) (*) -.IP \(bu 2 -An extra record exists together with a CNAME record except for RRSIG and NSEC (\fI\%RFC 1034\fP) -.IP \(bu 2 -Multiple CNAME records with the same owner exist (\fI\%RFC 1034\fP) -.IP \(bu 2 -DNAME record having a record under it (\fI\%RFC 6672\fP) -.IP \(bu 2 -Multiple DNAME records with the same owner exist (\fI\%RFC 6672\fP) -.IP \(bu 2 -NS record exists together with a DNAME record (\fI\%RFC 6672\fP) -.IP \(bu 2 -DS record exists at the zone apex (\fI\%RFC 3658\fP) -.UNINDENT -.sp -(*) The marked check can\(aqt be weakened by the soft mode. All other mandatory checks -are subject to the optional soft mode. -.sp -Extra checks: -.INDENT 0.0 -.IP \(bu 2 -Missing NS record at the zone apex -.IP \(bu 2 -Missing glue A or AAAA record -.IP \(bu 2 -Invalid DS or NSEC3PARAM record -.IP \(bu 2 -CDS or CDNSKEY inconsistency -.IP \(bu 2 -All other DNSSEC checks executed during \fI\%dnssec\-validation\fP -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -The soft mode allows the refresh event to ignore a CNAME response to a SOA -query (malformed message) and triggers a zone bootstrap instead. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBoff\fP -.SS default\-ttl -.sp -The default TTL value if none is specified in a zone file or zone insertion -using the dynamic configuration. -.sp -\fBWARNING:\fP -.INDENT 0.0 -.INDENT 3.5 -As changing this value can result in differently parsed zone file(s), -the corresponding zone SOA serial(s) should be incremented before -reloading or commiting the configuration. Alternatively, setting -\fI\%zonefile\-load\fP to \fBdifference\-no\-serial\fP ensures -the resulting zone(s) update is correct. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB3600\fP -.SS zonefile\-sync -.sp -The time in seconds after which the current zone in memory will be synced with -a zone file on the disk (see \fI\%file\fP). The server will serve the latest -zone even after a restart using zone journal, but the zone file on the disk will -only be synced after \fBzonefile\-sync\fP time has expired (or after manual zone -flush). This is applicable when the zone is updated via IXFR, DDNS or automatic -DNSSEC signing. In order to completely disable automatic zone file synchronization, -set the value to \-1. In that case, it is still possible to force a manual zone flush -using the \fB\-f\fP option. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -If you are serving large zones with frequent updates where -the immediate sync with a zone file is not desirable, increase the value. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB0\fP (immediate) -.SS zonefile\-load -.sp -Selects how the zone file contents are applied during zone load. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBnone\fP – The zone file is not used at all. -.IP \(bu 2 -\fBdifference\fP – If the zone contents are already available during server start or reload, -the difference is computed between them and the contents of the zone file. This difference -is then checked for semantic errors and applied to the current zone contents. -.IP \(bu 2 -\fBdifference\-no\-serial\fP – Same as \fBdifference\fP, but the SOA serial in the zone file is -ignored, the server takes care of incrementing the serial automatically. -.IP \(bu 2 -\fBwhole\fP – Zone contents are loaded from the zone file. -.UNINDENT -.sp -When \fBdifference\fP is configured and there are no zone contents yet (cold start -and no zone contents in the journal), it behaves the same way as \fBwhole\fP\&. -.sp -\fIDefault:\fP \fBwhole\fP -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -See \fI\%Handling zone file, journal, changes, serials\fP for guidance on -configuring these and related options to ensure reliable operation. -.UNINDENT -.UNINDENT -.SS journal\-content -.sp -Selects how the journal shall be used to store zone and its changes. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBnone\fP – The journal is not used at all. -.IP \(bu 2 -\fBchanges\fP – Zone changes history is stored in journal. -.IP \(bu 2 -\fBall\fP – Zone contents and history is stored in journal. -.UNINDENT -.sp -\fIDefault:\fP \fBchanges\fP -.sp -\fBWARNING:\fP -.INDENT 0.0 -.INDENT 3.5 -When this option is changed, the journal still contains data respective to -the previous setting. For example, changing it to \fBnone\fP does not purge -the journal. Also, changing it from \fBall\fP to \fBchanges\fP -does not cause the deletion of the zone\-in\-journal and the behaviour of the -zone loading procedure might be different than expected. It is recommended -to consider purging the journal when this option is changed. -.UNINDENT -.UNINDENT -.SS journal\-max\-usage -.sp -Policy how much space in journal DB will the zone\(aqs journal occupy. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Journal DB may grow far above the sum of journal\-max\-usage across -all zones, because of DB free space fragmentation. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB100M\fP (100 MiB) -.SS journal\-max\-depth -.sp -Maximum history length of the journal. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Zone\-in\-journal changeset isn\(aqt counted to the limit. -.UNINDENT -.UNINDENT -.sp -\fIMinimum:\fP \fB2\fP -.sp -\fIDefault:\fP \fB20\fP -.SS ixfr\-benevolent -.sp -If enabled, incoming IXFR is applied even when it contains removals of non\-existing -or additions of existing records. -.sp -\fIDefault:\fP \fBoff\fP -.SS ixfr\-by\-one -.sp -Within incoming IXFR, process only one changeset at a time, not multiple together. -This preserves the complete history in the journal and prevents the merging of -changesets when multiple changesets are IXFRed simultaneously. However, this does not -prevent the merging (or deletion) of old changesets in the journal to save space, -as described in \fI\%journal behaviour\fP\&. -.sp -This option leads to increased server load when processing IXFR, including -network traffic. -.sp -\fIDefault:\fP \fBoff\fP -.SS ixfr\-from\-axfr -.sp -If a primary sends AXFR\-style\-IXFR upon an IXFR request, compute the difference -and process it as an incremental zone update (e.g. by storing the changeset in -the journal). -.sp -\fIDefault:\fP \fBoff\fP -.SS zone\-max\-size -.sp -Maximum size of the zone. The size is measured as size of the zone records -in wire format without compression. The limit is enforced for incoming zone -transfers and dynamic updates. -.sp -For incremental transfers (IXFR), the effective limit for the total size of -the records in the transfer is twice the configured value. However the final -size of the zone must satisfy the configured value. -.sp -\fIDefault:\fP unlimited -.SS adjust\-threads -.sp -Parallelize internal zone adjusting procedures by using specified number of -threads. This is useful with huge zones with NSEC3. Speedup observable at -server startup and while processing NSEC3 re\-salt. -.sp -\fIDefault:\fP \fB1\fP (no extra threads) -.SS dnssec\-signing -.sp -If enabled, automatic DNSSEC signing for the zone is turned on. -.sp -\fIDefault:\fP \fBoff\fP -.SS dnssec\-validation -.sp -If enabled, the zone contents are validated for being correctly signed -(including NSEC/NSEC3 chain) with DNSSEC signatures every time the zone -is loaded or changed (including AXFR/IXFR). -.sp -When the validation fails, the zone being loaded or update being applied -is cancelled with an error, and either none or previous zone state is published. -.sp -List of DNSSEC checks: -.INDENT 0.0 -.IP \(bu 2 -Every zone RRSet is correctly signed by at least one present DNSKEY. -.IP \(bu 2 -For every RRSIG there are at most 3 non\-matching DNSKEYs with the same keytag. -.IP \(bu 2 -DNSKEY RRSet is signed by KSK. -.IP \(bu 2 -NSEC(3) RR exists for each name (unless opt\-out) with correct bitmap. -.IP \(bu 2 -Every NSEC(3) RR is linked to the lexicographically next one. -.UNINDENT -.sp -The validation is not affected by \fI\%dnssec\-policy\fP configuration, -except for \fI\%signing\-threads\fP option, which specifies the number -of threads for parallel validation. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Redundant or garbage NSEC3 records are ignored. -.sp -This mode is not compatible with \fI\%dnssec\-signing\fP\&. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP not set -.SS dnssec\-policy -.sp -A \fI\%reference\fP to DNSSEC signing policy. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -A configured policy called \(dqdefault\(dq won\(aqt be used unless explicitly referenced. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP an imaginary policy with all default values -.SS ds\-push -.sp -Per zone configuration of \fI\%ds\-push\fP\&. This option overrides possible -per policy option. Empty value is allowed for template value overriding. -.sp -\fIDefault:\fP not set -.SS zonemd\-verify -.sp -On each zone load/update, verify that ZONEMD is present in the zone and valid. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -Zone digest calculation may take much time and CPU on large zones. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBoff\fP -.SS zonemd\-generate -.sp -On each zone update, calculate ZONEMD and put it into the zone. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBnone\fP – No action regarding ZONEMD. -.IP \(bu 2 -\fBzonemd\-sha384\fP – Generate ZONEMD using SHA384 algorithm. -.IP \(bu 2 -\fBzonemd\-sha512\fP – Generate ZONEMD using SHA512 algorithm. -.IP \(bu 2 -\fBremove\fP – Remove any ZONEMD from the zone apex. -.UNINDENT -.sp -\fIDefault:\fP \fBnone\fP -.SS serial\-policy -.sp -Specifies how the zone serial is updated after a dynamic update or -automatic DNSSEC signing. If the serial is changed by the dynamic update, -no change is made. -.sp -Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBincrement\fP – The serial is incremented according to serial number arithmetic. -.IP \(bu 2 -\fBunixtime\fP – The serial is set to the current unix time. -.IP \(bu 2 -\fBdateserial\fP – The 10\-digit serial (YYYYMMDDnn) is incremented, the first -8 digits match the current iso\-date. -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -If the resulting serial for \fBunixtime\fP or \fBdateserial\fP is lower than or -equal to the current serial (this happens e.g. when migrating from other policy or -frequent updates), the serial is incremented instead. -.sp -To avoid user confusion, use \fBdateserial\fP only if you expect at most -100 updates per day per zone and \fBunixtime\fP only if you expect at most -one update per second per zone. -.sp -Generated catalog zones use \fBunixtime\fP only. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBincrement\fP (\fBunixtime\fP for generated catalog zones) -.SS serial\-modulo -.sp -Specifies that the zone serials shall be congruent by specified modulo. -The option value must be a string in the format \fBR/M\fP, where \fBR < M <= 256\fP are -positive integers. Whenever the zone serial is incremented, it is ensured -that \fBserial % M == R\fP\&. This can be useful in the case of multiple inconsistent -primaries, where distinct zone serial sequences prevent cross\-master\-IXFR -by any secondary. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -In order to ensure the congruent policy, this option is only allowed -with \fI\%DNSSEC signing enabled\fP and -\fI\%zonefile\-load\fP to be either \fBdifference\-no\-serial\fP or \fBnone\fP\&. -.sp -Because the zone serial effectively always increments by \fBM\fP instead of -\fB1\fP, it is not recommended to use \fBdateserial\fP \fI\%serial\-policy\fP -or even \fBunixtime\fP in case of rapidly updated zone. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fB0/1\fP -.SS reverse\-generate -.sp -This option triggers the automatic generation of reverse PTR records based on -A/AAAA records in the specified zone. The entire generated zone is automatically -stored in the journal. -.sp -Current limitations: -.INDENT 0.0 -.IP \(bu 2 -Only one zone to be reversed can be specified. -.IP \(bu 2 -Is slow for large zones (even when changing a little). -.UNINDENT -.sp -\fIDefault:\fP none -.SS refresh\-min\-interval -.sp -Forced minimum zone refresh interval (in seconds) to avoid flooding primary server. -.sp -\fIMinimum:\fP \fB2\fP -.sp -\fIDefault:\fP \fB2\fP -.SS refresh\-max\-interval -.sp -Forced maximum zone refresh interval (in seconds). -.sp -\fIDefault:\fP not set -.SS retry\-min\-interval -.sp -Forced minimum zone retry interval (in seconds) to avoid flooding primary server. -.sp -\fIMinimum:\fP \fB1\fP -.sp -\fIDefault:\fP \fB1\fP -.SS retry\-max\-interval -.sp -Forced maximum zone retry interval (in seconds). -.sp -\fIDefault:\fP not set -.SS expire\-min\-interval -.sp -Forced minimum zone expire interval (in seconds) to avoid flooding primary server. -.sp -\fIMinimum:\fP \fB3\fP -.sp -\fIDefault:\fP \fB3\fP -.SS expire\-max\-interval -.sp -Forced maximum zone expire interval (in seconds). -.sp -\fIDefault:\fP not set -.SS catalog\-role -.sp -Trigger zone catalog feature. Possible values: -.INDENT 0.0 -.IP \(bu 2 -\fBnone\fP – Not a catalog zone. -.IP \(bu 2 -\fBinterpret\fP – A catalog zone which is loaded from a zone file or XFR, -and member zones shall be configured based on its contents. -.IP \(bu 2 -\fBgenerate\fP – A catalog zone whose contents are generated according to -assigned member zones. -.IP \(bu 2 -\fBmember\fP – A member zone that is assigned to one generated catalog zone. -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -If set to \fBgenerate\fP, the \fI\%zonefile\-load\fP option has no effect -since a zone file is never loaded. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP \fBnone\fP -.SS catalog\-template -.sp -For the catalog member zones, the specified configuration template will be applied. -.sp -Multiple catalog templates may be defined. The first one is used unless the member zone -has the \fIgroup\fP property defined, matching another catalog template. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This option must be set if and only if \fI\%catalog\-role\fP is \fIinterpret\fP\&. -.sp -Nested catalog zones aren\(aqt supported. Therefore catalog templates can\(aqt -contain \fI\%catalog\-role\fP set to \fBinterpret\fP or \fBgenerate\fP\&. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP not set -.SS catalog\-zone -.sp -Assign this member zone to specified generated catalog zone. -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This option must be set if and only if \fI\%catalog\-role\fP is \fImember\fP\&. -.sp -The referenced catalog zone must exist and have \fI\%catalog\-role\fP set to \fIgenerate\fP\&. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP not set -.SS catalog\-group -.sp -Assign this member zone to specified catalog group (configuration template). -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -This option has effect if and only if \fI\%catalog\-role\fP is \fImember\fP\&. -.UNINDENT -.UNINDENT -.sp -\fIDefault:\fP not set -.SS module -.sp -An ordered list of references to query modules in the form of \fImodule_name\fP or -\fImodule_name/module_id\fP\&. These modules apply only to the current zone queries. -.sp -\fIDefault:\fP not set -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/knotc.8 b/doc/man/knotc.8 new file mode 100644 index 0000000..5e41e97 --- /dev/null +++ b/doc/man/knotc.8 @@ -0,0 +1,447 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KNOTC" "8" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +knotc \- Knot DNS control utility +.SH SYNOPSIS +.sp +\fBknotc\fP [\fIconfig_option\fP] [\fIoptions\fP] [\fIaction\fP] +.SH DESCRIPTION +.sp +This program controls a running \fIknotd\fP process using a socket. +.sp +If an \fIaction\fP is specified, it is performed and \fIknotc\fP exits, otherwise the program +is executed in the interactive mode. +.SS Config options +.INDENT 0.0 +.TP +\fB\-c\fP, \fB\-\-config\fP \fIfile\fP +Use a textual configuration file (default is \fB/usr/local/etc/knot/knot.conf\fP). +.TP +\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP +Use a binary configuration database directory (default is \fB/usr/local/var/lib/knot/confdb\fP). +The default configuration database, if exists, has a preference to the default +configuration file. +.UNINDENT +.SS Options +.INDENT 0.0 +.TP +\fB\-m\fP, \fB\-\-max\-conf\-size\fP \fIMiB\fP +Set maximum size of the configuration database +(default is 500 MiB, maximum 10000 MiB). +.TP +\fB\-s\fP, \fB\-\-socket\fP \fIpath\fP +Use a control UNIX socket path (default is \fB/usr/local/var/run/knot/knot.sock\fP). +.TP +\fB\-t\fP, \fB\-\-timeout\fP \fIseconds\fP +Use a control timeout in seconds. Set to 0 for infinity (default is 60). +The control socket operations are also subject to the \fI\%timeout\fP +parameter set on the server side in server\(aqs Control configuration section. +.TP +\fB\-b\fP, \fB\-\-blocking\fP +Zone event trigger commands wait until the event is finished. Control timeout +is set to infinity if not forced by explicit timeout specification. +.TP +\fB\-e\fP, \fB\-\-extended\fP +Show extended output (even empty items in zone status). +.TP +\fB\-f\fP, \fB\-\-force\fP +Forced operation. Overrides some checks. +.TP +\fB\-x\fP, \fB\-\-mono\fP +Don\(aqt generate colorized output. +.TP +\fB\-X\fP, \fB\-\-color\fP +Force colorized output in extended output or to a pipe. +.TP +\fB\-v\fP, \fB\-\-verbose\fP +Enable debug output. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.UNINDENT +.SS Actions +.INDENT 0.0 +.TP +\fBstatus\fP [\fIdetail\fP] +Check if the server is running. Details are \fBversion\fP for the running +server version, \fBworkers\fP for the numbers of worker threads, +\fBconfigure\fP for the configure summary, or \fBcert\-key\fP for the +public key pin of the currently used certificate. +.TP +\fBstop\fP +Stop the server if running. +.TP +\fBreload\fP +Reload the server configuration and modified zone files, and reopen the log files +if they are configured. All open zone transactions will be aborted! +.TP +\fBstats\fP [\fImodule\fP[\fB\&.\fP\fIcounter\fP]] +Show global statistics counter(s). To print also counters with value 0, use +force option. +.TP +\fBzone\-check\fP [\fIzone\fP\&...] +Test if the server can load the zone. Semantic checks are executed if enabled +in the configuration. If invoked with the force option, an error is returned +when semantic check warning appears. (*) +.TP +\fBzone\-status\fP [\fIzone\fP\&...] [\fIfilter\fP] +Show the zone status. Filters are \fB+role\fP, \fB+serial\fP, \fB+transaction\fP, +\fB+events\fP, \fB+freeze\fP, and \fB+catalog\fP\&. Empty zone parameters are omitted, +unless the \fB\-\-extended\fP option is used. A single dash in the output represents +an unset value. Automatic colorization can be overruled using the \fB\-\-mono\fP and +\fB\-\-color\fP options. +.sp +The color code is: +\fIgreen\fP \- zone acts as a master / \fIred\fP \- zone acts as a slave, +\fIbold font (highlited)\fP \- zone is active / \fInormal\fP \- zone is empty, +\fIunderscored\fP \- zone is an interpreted catalog member. +.TP +\fBzone\-reload\fP [\fIzone\fP\&...] +Trigger a zone reload from a disk without checking its modification time. For +secondary zone, the refresh event from primary server(s) is scheduled; +for primary zone, the notify event to secondary server(s) is scheduled. An open +zone transaction will be aborted! If invoked with the force option, also zone +modules will be re\-loaded, but blocking mode might not work reliably. (#) +.TP +\fBzone\-refresh\fP [\fIzone\fP\&...] +Trigger a check for the zone serial on the zone\(aqs primary server. If +the primary server has a newer zone, a transfer is scheduled. This command is +valid for secondary zones. (#) +.TP +\fBzone\-retransfer\fP [\fIzone\fP\&...] +Trigger a zone transfer from the zone\(aqs primary server. The server +doesn\(aqt check the serial of the primary server\(aqs zone. This command is valid +for secondary zones. (#) +.TP +\fBzone\-notify\fP [\fIzone\fP\&...] +Trigger a NOTIFY message to all configured remotes. This can help in cases +when previous NOTIFY had been lost or the secondary servers have been +offline. (#) +.TP +\fBzone\-flush\fP [\fIzone\fP\&...] [\fB+outdir\fP \fIdirectory\fP] +Trigger a zone journal flush to the configured zone file. If an output +directory is specified, the current zone is immediately dumped (in the +blocking mode) to a zone file in the specified directory. See +\fI\%Notes\fP below about the directory permissions. (#) +.TP +\fBzone\-backup\fP [\fIzone\fP\&...] \fB+backupdir\fP \fIdirectory\fP [\fIfilter\fP\&...] +Trigger a zone data and metadata backup to a specified directory. +Available filters are \fB+zonefile\fP, \fB+journal\fP, \fB+timers\fP, \fB+kaspdb\fP, +\fB+keysonly\fP, \fB+catalog\fP, \fB+quic\fP, and their negative counterparts +\fB+nozonefile\fP, \fB+nojournal\fP, \fB+notimers\fP, \fB+nokaspdb\fP, \fB+nokeysonly\fP, +\fB+nocatalog\fP, and \fB+noquic\fP\&. With these filters set, zone contents, +zone\(aqs journal, zone\-related timers, zone\-related data in the KASP database +together with keys (or keys without the KASP database), zone\(aqs catalog, +and the server QUIC key and certificate, respectively, are backed up, +or omitted from the backup. By default, filters \fB+zonefile\fP, \fB+timers\fP, +\fB+kaspdb\fP, \fB+catalog\fP, \fB+quic\fP, \fB+nojournal\fP, and \fB+nokeysonly\fP +are set for backup. The same defaults are set for restore, with the only +difference being \fB+noquic\fP\&. Setting a filter for an item doesn\(aqt change the +default settings for other items. The only exception is \fB+keysonly\fP, which +disables all other filters by default, but they can still be turned on +explicitly. If zone flushing is disabled, the original zone file is backed +up instead of writing out zone contents to a file. When backing\-up a catalog +zone, it is recommended to prevent ongoing changes to it by use of +\fBzone\-freeze\fP\&. The force option allows an already existing backupdir to +be overwritten. See \fI\%Notes\fP below about the directory permissions. +(#) +.TP +\fBzone\-restore\fP [\fIzone\fP\&...] \fB+backupdir\fP \fIdirectory\fP [\fIfilter\fP\&...] +Trigger a zone data and metadata restore from a specified backup directory. +Optional filters are equivalent to the same filters of \fBzone\-backup\fP\&. +Restore from backups created by Knot DNS releases prior to 3.1 is possible +with the force option. See \fI\%Notes\fP below about the directory +permissions. (#) +.TP +\fBzone\-sign\fP [\fIzone\fP\&...] +Trigger a DNSSEC re\-sign of the zone. Existing signatures will be dropped. +This command is valid for zones with DNSSEC signing enabled. (#) +.TP +\fBzone\-validate\fP [\fIzone\fP\&...] +Trigger a DNSSEC validation of the zone. If the validation fails and the +zone is secondary, the zone expires immediately! (#) +.TP +\fBzone\-keys\-load\fP [\fIzone\fP\&...] +Trigger a load of DNSSEC keys and other signing material from KASP database +(which might have been altered manually). If suitable, re\-sign the zone +afterwards (keeping valid signatures intact). (#) +.TP +\fBzone\-key\-rollover\fP \fIzone\fP \fIkey_type\fP +Trigger immediate key rollover. Publish new key and start a key rollover, +even when the key has a lifetime to go. Key type can be \fBksk\fP (also for CSK) +or \fBzsk\fP\&. This command is valid for zones with DNSSEC signing and automatic +key management enabled. Note that complete key rollover consists of several steps +and the blocking mode relates to the initial one only! (#) +.TP +\fBzone\-ksk\-submitted\fP \fIzone\fP\&... +Use when the zone\(aqs KSK rollover is in submission phase. By calling this command +the user confirms manually that the parent zone contains DS record for the new +KSK in submission phase and the old KSK can be retired. (#) +.TP +\fBzone\-freeze\fP [\fIzone\fP\&...] +Trigger a zone freeze. All running events will be finished and all new and pending +(planned) zone\-changing events (load, refresh, update, flush, and DNSSEC signing) +will be held up until the zone is thawed. Up to 8 (this limit is hardcoded) DDNS +updates per zone will be queued, subsequent updates will be refused. (#) +.TP +\fBzone\-thaw\fP [\fIzone\fP\&...] +Trigger dismissal of zone freeze. (#) +.TP +\fBzone\-xfr\-freeze\fP [\fIzone\fP\&...] +Temporarily disable outgoing AXFR/IXFR for the zone(s). (#) +.TP +\fBzone\-xfr\-thaw\fP [\fIzone\fP\&...] +Dismiss outgoing XFR freeze. (#) +.TP +\fBzone\-read\fP \fIzone\fP [\fIowner\fP [\fItype\fP]] +Get zone data that are currently being presented. +.TP +\fBzone\-begin\fP \fIzone\fP\&... +Begin a zone transaction. +.TP +\fBzone\-commit\fP \fIzone\fP\&... +Commit the zone transaction. All changes are applied to the zone. +.TP +\fBzone\-abort\fP \fIzone\fP\&... +Abort the zone transaction. All changes are discarded. +.TP +\fBzone\-diff\fP \fIzone\fP +Get zone changes within the transaction. +.TP +\fBzone\-get\fP \fIzone\fP [\fIowner\fP [\fItype\fP]] +Get zone data within the transaction. +.TP +\fBzone\-set\fP \fIzone\fP \fIowner\fP [\fIttl\fP] \fItype\fP \fIrdata\fP +Add zone record within the transaction. The first record in a rrset +requires a ttl value specified. +.TP +\fBzone\-unset\fP \fIzone\fP \fIowner\fP [\fItype\fP [\fIrdata\fP]] +Remove zone data within the transaction. +.TP +\fBzone\-purge\fP \fIzone\fP\&... [\fB+orphan\fP] [\fIfilter\fP\&...] +Purge zone data, zone file, journal, timers, and/or KASP data of specified zones. +Available filters are \fB+expire\fP, \fB+zonefile\fP, \fB+journal\fP, \fB+timers\fP, +\fB+kaspdb\fP, and \fB+catalog\fP\&. If no filter is specified, all filters are enabled. +If the zone is no longer configured, add \fB+orphan\fP parameter (zone file cannot +be purged in this case). When purging orphans, always check the server log for +possible errors. For proper operation, it\(aqs necessary to prevent ongoing changes +to the zone and triggering of zone related events during purge; use of +\fBzone\-freeze\fP is advisable. This command always requires the force option. (#) +.TP +\fBzone\-stats\fP \fIzone\fP [\fImodule\fP[\fB\&.\fP\fIcounter\fP]] +Show zone statistics counter(s). To print also counters with value 0, use +force option. +.TP +\fBconf\-init\fP +Initialize the configuration database. If the database doesn\(aqt exist yet, +execute this command as an intended user to ensure the server is permitted +to access the database (e.g. \fIsudo \-u knot knotc conf\-init\fP). (*) +.TP +\fBconf\-check\fP +Check the server configuration. (*) +.TP +\fBconf\-import\fP \fIfilename\fP [+nopurge] +Import a configuration file into the configuration database. If the database +doesn\(aqt exist yet, execute this command as an intended user to ensure the server +is permitted to access the database (e.g. \fIsudo \-u knot knotc conf\-import ...\fP). +An optional filter \fB+nopurge\fP prevents possibly existing configuration +database from purging before the import itself. +Also ensure the server is not using the configuration database at the same time! (*) +.TP +\fBconf\-export\fP [\fIfilename\fP] [+schema] +Export the configuration database (or JSON schema) into a file or stdout. (*) +.TP +\fBconf\-list\fP [\fIitem\fP] +List the configuration database sections or section items. +.TP +\fBconf\-read\fP [\fIitem\fP] +Read the item from the active configuration database. +.TP +\fBconf\-begin\fP +Begin a writing configuration database transaction. Only one transaction +can be opened at a time. +.TP +\fBconf\-commit\fP +Commit the configuration database transaction. +.TP +\fBconf\-abort\fP +Rollback the configuration database transaction. +.TP +\fBconf\-diff\fP [\fIitem\fP] +Get the item difference in the transaction. +.TP +\fBconf\-get\fP [\fIitem\fP] +Get the item data from the transaction. +.TP +\fBconf\-set\fP \fIitem\fP [\fIdata\fP\&...] +Set the item data in the transaction. +.TP +\fBconf\-unset\fP [\fIitem\fP] [\fIdata\fP\&...] +Unset the item data in the transaction. +.UNINDENT +.SS Notes +.sp +Empty or \fB\-\-\fP \fIzone\fP parameter means all zones or all zones with a transaction. +.sp +Use \fB@\fP \fIowner\fP to denote the zone name. +.sp +Type \fIitem\fP parameter in the form of \fIsection\fP[\fB[\fP\fIid\fP\fB]\fP][\fB\&.\fP\fIname\fP]. +.sp +(*) indicates a local operation which requires a configuration. +.sp +(#) indicates an optionally blocking operation. +.sp +The \fB\-b\fP and \fB\-f\fP options can be placed right after the command name. +.sp +Responses returned by \fIknotc\fP commands depend on the mode: +.INDENT 0.0 +.IP \(bu 2 +In the blocking mode, \fIknotc\fP reports if an error occurred during processing +of the command by the server. If an error is reported, a more detailed information +about the failure can usually be found in the server log. +.IP \(bu 2 +In the non\-blocking (default) mode, \fIknotc\fP doesn\(aqt report processing errors. +The \fIOK\fP response to triggering commands means that the command has been successfully +sent to the server. To verify if the operation succeeded, it\(aqs necessary to +check the server log. +.UNINDENT +.sp +Actions \fBzone\-flush\fP, \fBzone\-backup\fP, and \fBzone\-restore\fP are carried out by +the \fIknotd\fP process. The directory specified must be accessible to the user account +that \fIknotd\fP runs under and if the directory already exists, its permissions must be +appropriate for that user account. +.SS Interactive mode +.sp +The utility provides interactive mode with basic line editing functionality, +command completion, and command history. +.sp +Interactive mode behavior can be customized in \fI~/.editrc\fP\&. Refer to +\fBeditrc(5)\fP for details. +.sp +Command history is saved in \fI~/.knotc_history\fP\&. +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH EXAMPLES +.SS Reload the whole server configuration +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ knotc reload +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Flush the example.com and example.org zones +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ knotc zone\-flush example.com example.org +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Get the current server configuration +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ knotc conf\-read server +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Get the list of the current zones +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ knotc conf\-read zone.domain +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Get the primary servers for the example.com zone +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ knotc conf\-read \(aqzone[example.com].master\(aq +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Add example.org zone with a zonefile location +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ knotc conf\-begin +$ knotc conf\-set \(aqzone[example.org]\(aq +$ knotc conf\-set \(aqzone[example.org].file\(aq \(aq/var/zones/example.org.zone\(aq +$ knotc conf\-commit +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Get the SOA record for each configured zone +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ knotc zone\-read \-\- @ SOA +.ft P +.fi +.UNINDENT +.UNINDENT +.SH SEE ALSO +.sp +\fBknotd(8)\fP, \fBknot.conf(5)\fP, \fBeditrc(5)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/knotc.8in b/doc/man/knotc.8in deleted file mode 100644 index 01bfc95..0000000 --- a/doc/man/knotc.8in +++ /dev/null @@ -1,440 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KNOTC" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -knotc \- Knot DNS control utility -.SH SYNOPSIS -.sp -\fBknotc\fP [\fIconfig_option\fP] [\fIoptions\fP] [\fIaction\fP] -.SH DESCRIPTION -.sp -This program controls a running \fIknotd\fP process using a socket. -.sp -If an \fIaction\fP is specified, it is performed and \fIknotc\fP exits, otherwise the program -is executed in the interactive mode. -.SS Config options -.INDENT 0.0 -.TP -\fB\-c\fP, \fB\-\-config\fP \fIfile\fP -Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP). -.TP -\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP -Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP). -The default configuration database, if exists, has a preference to the default -configuration file. -.UNINDENT -.SS Options -.INDENT 0.0 -.TP -\fB\-m\fP, \fB\-\-max\-conf\-size\fP \fIMiB\fP -Set maximum size of the configuration database -(default is @conf_mapsize@ MiB, maximum 10000 MiB). -.TP -\fB\-s\fP, \fB\-\-socket\fP \fIpath\fP -Use a control UNIX socket path (default is \fB@run_dir@/knot.sock\fP). -.TP -\fB\-t\fP, \fB\-\-timeout\fP \fIseconds\fP -Use a control timeout in seconds. Set to 0 for infinity (default is 60). -The control socket operations are also subject to the \fI\%timeout\fP -parameter set on the server side in server\(aqs Control configuration section. -.TP -\fB\-b\fP, \fB\-\-blocking\fP -Zone event trigger commands wait until the event is finished. Control timeout -is set to infinity if not forced by explicit timeout specification. -.TP -\fB\-e\fP, \fB\-\-extended\fP -Show extended output (even empty items in zone status). -.TP -\fB\-f\fP, \fB\-\-force\fP -Forced operation. Overrides some checks. -.TP -\fB\-x\fP, \fB\-\-mono\fP -Don\(aqt generate colorized output. -.TP -\fB\-X\fP, \fB\-\-color\fP -Force colorized output in extended output or to a pipe. -.TP -\fB\-v\fP, \fB\-\-verbose\fP -Enable debug output. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print the program help. -.TP -\fB\-V\fP, \fB\-\-version\fP -Print the program version. -.UNINDENT -.SS Actions -.INDENT 0.0 -.TP -\fBstatus\fP [\fIdetail\fP] -Check if the server is running. Details are \fBversion\fP for the running -server version, \fBworkers\fP for the numbers of worker threads, -\fBconfigure\fP for the configure summary, or \fBcert\-key\fP for the -public key pin of the currently used certificate. -.TP -\fBstop\fP -Stop the server if running. -.TP -\fBreload\fP -Reload the server configuration and modified zone files, and reopen the log files -if they are configured. All open zone transactions will be aborted! -.TP -\fBstats\fP [\fImodule\fP[\fB\&.\fP\fIcounter\fP]] -Show global statistics counter(s). To print also counters with value 0, use -force option. -.TP -\fBzone\-check\fP [\fIzone\fP\&...] -Test if the server can load the zone. Semantic checks are executed if enabled -in the configuration. If invoked with the force option, an error is returned -when semantic check warning appears. (*) -.TP -\fBzone\-status\fP [\fIzone\fP\&...] [\fIfilter\fP] -Show the zone status. Filters are \fB+role\fP, \fB+serial\fP, \fB+transaction\fP, -\fB+events\fP, \fB+freeze\fP, and \fB+catalog\fP\&. Empty zone parameters are omitted, -unless the \fB\-\-extended\fP option is used. A single dash in the output represents -an unset value. Automatic colorization can be overruled using the \fB\-\-mono\fP and -\fB\-\-color\fP options. -.sp -The color code is: -\fIgreen\fP \- zone acts as a master / \fIred\fP \- zone acts as a slave, -\fIbold font (highlited)\fP \- zone is active / \fInormal\fP \- zone is empty, -\fIunderscored\fP \- zone is an interpreted catalog member. -.TP -\fBzone\-reload\fP [\fIzone\fP\&...] -Trigger a zone reload from a disk without checking its modification time. For -secondary zone, the refresh event from primary server(s) is scheduled; -for primary zone, the notify event to secondary server(s) is scheduled. An open -zone transaction will be aborted! If invoked with the force option, also zone -modules will be re\-loaded, but blocking mode might not work reliably. (#) -.TP -\fBzone\-refresh\fP [\fIzone\fP\&...] -Trigger a check for the zone serial on the zone\(aqs primary server. If -the primary server has a newer zone, a transfer is scheduled. This command is -valid for secondary zones. (#) -.TP -\fBzone\-retransfer\fP [\fIzone\fP\&...] -Trigger a zone transfer from the zone\(aqs primary server. The server -doesn\(aqt check the serial of the primary server\(aqs zone. This command is valid -for secondary zones. (#) -.TP -\fBzone\-notify\fP [\fIzone\fP\&...] -Trigger a NOTIFY message to all configured remotes. This can help in cases -when previous NOTIFY had been lost or the secondary servers have been -offline. (#) -.TP -\fBzone\-flush\fP [\fIzone\fP\&...] [\fB+outdir\fP \fIdirectory\fP] -Trigger a zone journal flush to the configured zone file. If an output -directory is specified, the current zone is immediately dumped (in the -blocking mode) to a zone file in the specified directory. See -\fI\%Notes\fP below about the directory permissions. (#) -.TP -\fBzone\-backup\fP [\fIzone\fP\&...] \fB+backupdir\fP \fIdirectory\fP [\fIfilter\fP\&...] -Trigger a zone data and metadata backup to a specified directory. -Available filters are \fB+zonefile\fP, \fB+journal\fP, \fB+timers\fP, \fB+kaspdb\fP, -\fB+keysonly\fP, \fB+catalog\fP, \fB+quic\fP, and their negative counterparts -\fB+nozonefile\fP, \fB+nojournal\fP, \fB+notimers\fP, \fB+nokaspdb\fP, \fB+nokeysonly\fP, -\fB+nocatalog\fP, and \fB+noquic\fP\&. With these filters set, zone contents, -zone\(aqs journal, zone\-related timers, zone\-related data in the KASP database -together with keys (or keys without the KASP database), zone\(aqs catalog, -and the server QUIC key and certificate, respectively, are backed up, -or omitted from the backup. By default, filters \fB+zonefile\fP, \fB+timers\fP, -\fB+kaspdb\fP, \fB+catalog\fP, \fB+quic\fP, \fB+nojournal\fP, and \fB+nokeysonly\fP -are set for backup. The same defaults are set for restore, with the only -difference being \fB+noquic\fP\&. Setting a filter for an item doesn\(aqt change the -default settings for other items. The only exception is \fB+keysonly\fP, which -disables all other filters by default, but they can still be turned on -explicitly. If zone flushing is disabled, the original zone file is backed -up instead of writing out zone contents to a file. When backing\-up a catalog -zone, it is recommended to prevent ongoing changes to it by use of -\fBzone\-freeze\fP\&. -See \fI\%Notes\fP below about the directory permissions. (#) -.TP -\fBzone\-restore\fP [\fIzone\fP\&...] \fB+backupdir\fP \fIdirectory\fP [\fIfilter\fP\&...] -Trigger a zone data and metadata restore from a specified backup directory. -Optional filters are equivalent to the same filters of \fBzone\-backup\fP\&. -Restore from backups created by Knot DNS releases prior to 3.1 is possible -with the force option. See \fI\%Notes\fP below about the directory -permissions. (#) -.TP -\fBzone\-sign\fP [\fIzone\fP\&...] -Trigger a DNSSEC re\-sign of the zone. Existing signatures will be dropped. -This command is valid for zones with DNSSEC signing enabled. (#) -.TP -\fBzone\-keys\-load\fP [\fIzone\fP\&...] -Trigger a load of DNSSEC keys and other signing material from KASP database -(which might have been altered manually). If suitable, re\-sign the zone -afterwards (keeping valid signatures intact). (#) -.TP -\fBzone\-key\-rollover\fP \fIzone\fP \fIkey_type\fP -Trigger immediate key rollover. Publish new key and start a key rollover, -even when the key has a lifetime to go. Key type can be \fBksk\fP (also for CSK) -or \fBzsk\fP\&. This command is valid for zones with DNSSEC signing and automatic -key management enabled. Note that complete key rollover consists of several steps -and the blocking mode relates to the initial one only! (#) -.TP -\fBzone\-ksk\-submitted\fP \fIzone\fP\&... -Use when the zone\(aqs KSK rollover is in submission phase. By calling this command -the user confirms manually that the parent zone contains DS record for the new -KSK in submission phase and the old KSK can be retired. (#) -.TP -\fBzone\-freeze\fP [\fIzone\fP\&...] -Trigger a zone freeze. All running events will be finished and all new and pending -(planned) zone\-changing events (load, refresh, update, flush, and DNSSEC signing) -will be held up until the zone is thawed. (#) -.TP -\fBzone\-thaw\fP [\fIzone\fP\&...] -Trigger dismissal of zone freeze. (#) -.TP -\fBzone\-xfr\-freeze\fP [\fIzone\fP\&...] -Temporarily disable outgoing AXFR/IXFR for the zone(s). (#) -.TP -\fBzone\-xfr\-thaw\fP [\fIzone\fP\&...] -Dismiss outgoing XFR freeze. (#) -.TP -\fBzone\-read\fP \fIzone\fP [\fIowner\fP [\fItype\fP]] -Get zone data that are currently being presented. -.TP -\fBzone\-begin\fP \fIzone\fP\&... -Begin a zone transaction. -.TP -\fBzone\-commit\fP \fIzone\fP\&... -Commit the zone transaction. All changes are applied to the zone. -.TP -\fBzone\-abort\fP \fIzone\fP\&... -Abort the zone transaction. All changes are discarded. -.TP -\fBzone\-diff\fP \fIzone\fP -Get zone changes within the transaction. -.TP -\fBzone\-get\fP \fIzone\fP [\fIowner\fP [\fItype\fP]] -Get zone data within the transaction. -.TP -\fBzone\-set\fP \fIzone\fP \fIowner\fP [\fIttl\fP] \fItype\fP \fIrdata\fP -Add zone record within the transaction. The first record in a rrset -requires a ttl value specified. -.TP -\fBzone\-unset\fP \fIzone\fP \fIowner\fP [\fItype\fP [\fIrdata\fP]] -Remove zone data within the transaction. -.TP -\fBzone\-purge\fP \fIzone\fP\&... [\fB+orphan\fP] [\fIfilter\fP\&...] -Purge zone data, zone file, journal, timers, and/or KASP data of specified zones. -Available filters are \fB+expire\fP, \fB+zonefile\fP, \fB+journal\fP, \fB+timers\fP, -\fB+kaspdb\fP, and \fB+catalog\fP\&. If no filter is specified, all filters are enabled. -If the zone is no longer configured, add \fB+orphan\fP parameter (zone file cannot -be purged in this case). When purging orphans, always check the server log for -possible errors. For proper operation, it\(aqs necessary to prevent ongoing changes -to the zone and triggering of zone related events during purge; use of -\fBzone\-freeze\fP is advisable. This command always requires the force option. (#) -.TP -\fBzone\-stats\fP \fIzone\fP [\fImodule\fP[\fB\&.\fP\fIcounter\fP]] -Show zone statistics counter(s). To print also counters with value 0, use -force option. -.TP -\fBconf\-init\fP -Initialize the configuration database. If the database doesn\(aqt exist yet, -execute this command as an intended user to ensure the server is permitted -to access the database (e.g. \fIsudo \-u knot knotc conf\-init\fP). (*) -.TP -\fBconf\-check\fP -Check the server configuration. (*) -.TP -\fBconf\-import\fP \fIfilename\fP [+nopurge] -Import a configuration file into the configuration database. If the database -doesn\(aqt exist yet, execute this command as an intended user to ensure the server -is permitted to access the database (e.g. \fIsudo \-u knot knotc conf\-import ...\fP). -An optional filter \fB+nopurge\fP prevents possibly existing configuration -database from purging before the import itself. -Also ensure the server is not using the configuration database at the same time! (*) -.TP -\fBconf\-export\fP [\fIfilename\fP] [+schema] -Export the configuration database (or JSON schema) into a file or stdout. (*) -.TP -\fBconf\-list\fP [\fIitem\fP] -List the configuration database sections or section items. -.TP -\fBconf\-read\fP [\fIitem\fP] -Read the item from the active configuration database. -.TP -\fBconf\-begin\fP -Begin a writing configuration database transaction. Only one transaction -can be opened at a time. -.TP -\fBconf\-commit\fP -Commit the configuration database transaction. -.TP -\fBconf\-abort\fP -Rollback the configuration database transaction. -.TP -\fBconf\-diff\fP [\fIitem\fP] -Get the item difference in the transaction. -.TP -\fBconf\-get\fP [\fIitem\fP] -Get the item data from the transaction. -.TP -\fBconf\-set\fP \fIitem\fP [\fIdata\fP\&...] -Set the item data in the transaction. -.TP -\fBconf\-unset\fP [\fIitem\fP] [\fIdata\fP\&...] -Unset the item data in the transaction. -.UNINDENT -.SS Notes -.sp -Empty or \fB\-\-\fP \fIzone\fP parameter means all zones or all zones with a transaction. -.sp -Use \fB@\fP \fIowner\fP to denote the zone name. -.sp -Type \fIitem\fP parameter in the form of \fIsection\fP[\fB[\fP\fIid\fP\fB]\fP][\fB\&.\fP\fIname\fP]. -.sp -(*) indicates a local operation which requires a configuration. -.sp -(#) indicates an optionally blocking operation. -.sp -The \fB\-b\fP and \fB\-f\fP options can be placed right after the command name. -.sp -Responses returned by \fIknotc\fP commands depend on the mode: -.INDENT 0.0 -.IP \(bu 2 -In the blocking mode, \fIknotc\fP reports if an error occurred during processing -of the command by the server. If an error is reported, a more detailed information -about the failure can usually be found in the server log. -.IP \(bu 2 -In the non\-blocking (default) mode, \fIknotc\fP doesn\(aqt report processing errors. -The \fIOK\fP response to triggering commands means that the command has been successfully -sent to the server. To verify if the operation succeeded, it\(aqs necessary to -check the server log. -.UNINDENT -.sp -Actions \fBzone\-flush\fP, \fBzone\-backup\fP, and \fBzone\-restore\fP are carried out by -the \fIknotd\fP process. The directory specified must be accessible to the user account -that \fIknotd\fP runs under and if the directory already exists, its permissions must be -appropriate for that user account. -.SS Interactive mode -.sp -The utility provides interactive mode with basic line editing functionality, -command completion, and command history. -.sp -Interactive mode behavior can be customized in \fI~/.editrc\fP\&. Refer to -\fBeditrc(5)\fP for details. -.sp -Command history is saved in \fI~/.knotc_history\fP\&. -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH EXAMPLES -.SS Reload the whole server configuration -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ knotc reload -.ft P -.fi -.UNINDENT -.UNINDENT -.SS Flush the example.com and example.org zones -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ knotc zone\-flush example.com example.org -.ft P -.fi -.UNINDENT -.UNINDENT -.SS Get the current server configuration -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ knotc conf\-read server -.ft P -.fi -.UNINDENT -.UNINDENT -.SS Get the list of the current zones -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ knotc conf\-read zone.domain -.ft P -.fi -.UNINDENT -.UNINDENT -.SS Get the primary servers for the example.com zone -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ knotc conf\-read \(aqzone[example.com].master\(aq -.ft P -.fi -.UNINDENT -.UNINDENT -.SS Add example.org zone with a zonefile location -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ knotc conf\-begin -$ knotc conf\-set \(aqzone[example.org]\(aq -$ knotc conf\-set \(aqzone[example.org].file\(aq \(aq/var/zones/example.org.zone\(aq -$ knotc conf\-commit -.ft P -.fi -.UNINDENT -.UNINDENT -.SS Get the SOA record for each configured zone -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ knotc zone\-read \-\- @ SOA -.ft P -.fi -.UNINDENT -.UNINDENT -.SH SEE ALSO -.sp -\fBknotd(8)\fP, \fBknot.conf(5)\fP, \fBeditrc(5)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/knotd.8 b/doc/man/knotd.8 new file mode 100644 index 0000000..bbeb6a4 --- /dev/null +++ b/doc/man/knotd.8 @@ -0,0 +1,94 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KNOTD" "8" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +knotd \- Knot DNS server daemon +.SH SYNOPSIS +.sp +\fBknotd\fP [\fIconfig_option\fP] [\fIoptions\fP] +.SH DESCRIPTION +.sp +Knot DNS is a high\-performance authoritative DNS server. The \fIknotd\fP program is +the DNS server daemon. +.SS Config options +.INDENT 0.0 +.TP +\fB\-c\fP, \fB\-\-config\fP \fIfile\fP +Use a textual configuration file (default is \fB/usr/local/etc/knot/knot.conf\fP). +.TP +\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP +Use a binary configuration database directory (default is \fB/usr/local/var/lib/knot/confdb\fP). +The default configuration database, if exists, has a preference to the default +configuration file. +.UNINDENT +.SS Options +.INDENT 0.0 +.TP +\fB\-m\fP, \fB\-\-max\-conf\-size\fP \fIMiB\fP +Set maximum size of the configuration database +(default is 500 MiB, maximum 10000 MiB). +.TP +\fB\-s\fP, \fB\-\-socket\fP \fIpath\fP +Use a remote control UNIX socket path (default is \fB/usr/local/var/run/knot/knot.sock\fP). +.TP +\fB\-d\fP, \fB\-\-daemonize\fP [\fIdirectory\fP] +Run the server as a daemon. New root directory may be specified +(default is \fB/\fP). +.TP +\fB\-v\fP, \fB\-\-verbose\fP +Enable debug output. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.UNINDENT +.SS Signals +.sp +If the \fIknotd\fP process receives a SIGHUP signal, it reloads its configuration and +reopens the log files, if they are configured. When \fIknotd\fP receives a SIGUSR1 +signal, it reloads all configured zones. Upon receiving a SIGINT signal, \fIknotd\fP +exits. +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH SEE ALSO +.sp +\fBknot.conf(5)\fP, \fBknotc(8)\fP, \fBkeymgr(8)\fP, +\fBkjournalprint(8)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/knotd.8in b/doc/man/knotd.8in deleted file mode 100644 index 1d02cc8..0000000 --- a/doc/man/knotd.8in +++ /dev/null @@ -1,93 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KNOTD" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -knotd \- Knot DNS server daemon -.SH SYNOPSIS -.sp -\fBknotd\fP [\fIconfig_option\fP] [\fIoptions\fP] -.SH DESCRIPTION -.sp -Knot DNS is a high\-performance authoritative DNS server. The \fIknotd\fP program is -the DNS server daemon. -.SS Config options -.INDENT 0.0 -.TP -\fB\-c\fP, \fB\-\-config\fP \fIfile\fP -Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP). -.TP -\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP -Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP). -The default configuration database, if exists, has a preference to the default -configuration file. -.UNINDENT -.SS Options -.INDENT 0.0 -.TP -\fB\-m\fP, \fB\-\-max\-conf\-size\fP \fIMiB\fP -Set maximum size of the configuration database -(default is @conf_mapsize@ MiB, maximum 10000 MiB). -.TP -\fB\-s\fP, \fB\-\-socket\fP \fIpath\fP -Use a remote control UNIX socket path (default is \fB@run_dir@/knot.sock\fP). -.TP -\fB\-d\fP, \fB\-\-daemonize\fP [\fIdirectory\fP] -Run the server as a daemon. New root directory may be specified -(default is \fB/\fP). -.TP -\fB\-v\fP, \fB\-\-verbose\fP -Enable debug output. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print the program help. -.TP -\fB\-V\fP, \fB\-\-version\fP -Print the program version. -.UNINDENT -.SS Signals -.sp -If the \fIknotd\fP process receives a SIGHUP signal, it reloads its configuration and -reopens the log files, if they are configured. When \fIknotd\fP receives a SIGUSR1 -signal, it reloads all configured zones. Upon receiving a SIGINT signal, \fIknotd\fP -exits. -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH SEE ALSO -.sp -\fBknot.conf(5)\fP, \fBknotc(8)\fP, \fBkeymgr(8)\fP, -\fBkjournalprint(8)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/knsec3hash.1 b/doc/man/knsec3hash.1 new file mode 100644 index 0000000..3bb9766 --- /dev/null +++ b/doc/man/knsec3hash.1 @@ -0,0 +1,108 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KNSEC3HASH" "1" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +knsec3hash \- Simple utility to compute NSEC3 hash +.SH SYNOPSIS +.sp +\fBknsec3hash\fP \fIsalt\fP \fIalgorithm\fP \fIiterations\fP \fIname\fP +.sp +\fBknsec3hash\fP \fIalgorithm\fP \fIflags\fP \fIiterations\fP \fIsalt\fP \fIname\fP +.sp +\fBknsec3hash\fP [\fI\-h\fP] [\fI\-V\fP] +.SH DESCRIPTION +.sp +This utility generates a NSEC3 hash for a given domain name and parameters of NSEC3 hash. +.SS Parameters +.INDENT 0.0 +.TP +.B \fIsalt\fP +Specifies a binary salt encoded as a hexadecimal string. +.TP +.B \fIalgorithm\fP +Specifies a hashing algorithm by number. Currently, the only supported algorithm is SHA\-1 (number 1). +.TP +.B \fIiterations\fP +Specifies the number of additional iterations of the hashing algorithm. +.TP +.B \fIname\fP +Specifies the domain name to be hashed. +.TP +.B \fIflags\fP +Specifies NSEC3 flags as an unsigned integer. +.UNINDENT +.SS Options +.INDENT 0.0 +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.UNINDENT +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH EXAMPLES +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ knsec3hash 1 0 10 c01dcafe knot\-dns.cz +7PTVGE7QV67EM61ROS9238P5RAKR2DM7 (salt=c01dcafe, hash=1, iterations=10) +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ knsec3hash \- 1 0 net +A1RT98BS5QGC9NFI51S9HCI47ULJG6JH (salt=\-, hash=1, iterations=0) +.ft P +.fi +.UNINDENT +.UNINDENT +.SH SEE ALSO +.sp +\fI\%RFC 5155\fP – DNS Security (DNSSEC) Hashed Authenticated Denial of Existence. +.sp +\fBknotc(8)\fP, \fBknotd(8)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/knsec3hash.1in b/doc/man/knsec3hash.1in deleted file mode 100644 index d9fa4a3..0000000 --- a/doc/man/knsec3hash.1in +++ /dev/null @@ -1,96 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KNSEC3HASH" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -knsec3hash \- Simple utility to compute NSEC3 hash -.SH SYNOPSIS -.sp -\fBknsec3hash\fP \fIsalt\fP \fIalgorithm\fP \fIiterations\fP \fIname\fP -.sp -\fBknsec3hash\fP \fIalgorithm\fP \fIflags\fP \fIiterations\fP \fIsalt\fP \fIname\fP -.SH DESCRIPTION -.sp -This utility generates a NSEC3 hash for a given domain name and parameters of NSEC3 hash. -.SS Parameters -.INDENT 0.0 -.TP -\fIsalt\fP -Specifies a binary salt encoded as a hexadecimal string. -.TP -\fIalgorithm\fP -Specifies a hashing algorithm by number. Currently, the only supported algorithm is SHA\-1 (number 1). -.TP -\fIiterations\fP -Specifies the number of additional iterations of the hashing algorithm. -.TP -\fIname\fP -Specifies the domain name to be hashed. -.TP -\fIflags\fP -Specifies NSEC3 flags as an unsigned integer. -.UNINDENT -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH EXAMPLES -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ knsec3hash 1 0 10 c01dcafe knot\-dns.cz -7PTVGE7QV67EM61ROS9238P5RAKR2DM7 (salt=c01dcafe, hash=1, iterations=10) -.ft P -.fi -.UNINDENT -.UNINDENT -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ knsec3hash \- 1 0 net -A1RT98BS5QGC9NFI51S9HCI47ULJG6JH (salt=\-, hash=1, iterations=0) -.ft P -.fi -.UNINDENT -.UNINDENT -.SH SEE ALSO -.sp -\fI\%RFC 5155\fP – DNS Security (DNSSEC) Hashed Authenticated Denial of Existence. -.sp -\fBknotc(8)\fP, \fBknotd(8)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/knsupdate.1 b/doc/man/knsupdate.1 new file mode 100644 index 0000000..58220a0 --- /dev/null +++ b/doc/man/knsupdate.1 @@ -0,0 +1,252 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KNSUPDATE" "1" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +knsupdate \- Dynamic DNS update utility +.SH SYNOPSIS +.sp +\fBknsupdate\fP [\fB\-v\fP] [\fIoptions\fP] [\fIfilename\fP] +.sp +\fBknsupdate\fP [\fB\-q\fP] [\fIquic_options\fP] [\fIoptions\fP] [\fIfilename\fP] +.SH DESCRIPTION +.sp +This utility sends Dynamic DNS update messages to a DNS server. Update content +is read from a file (if the parameter \fIfilename\fP is given) or from the standard +input. +.sp +The format of updates is textual and is made up of commands. Every command is +placed on the separate line of the input. Lines starting with a semicolon are +comments and are not processed. +.SS Parameters +.INDENT 0.0 +.TP +.B \fIfilename\fP +Path to the file with knsupdate commands. +.UNINDENT +.SS Options +.INDENT 0.0 +.TP +\fB\-T\fP, \fB\-\-tcp\fP +Use a TCP connection. (\fB\-v\fP can be used for compatibility with nsupdate). +.TP +\fB\-S\fP, \fB\-\-tls\fP +Use a TLS connection. +.TP +\fB\-Q\fP, \fB\-\-quic\fP +Use a QUIC connection. +.TP +\fB\-p\fP, \fB\-\-port\fP \fInumber\fP +Set the port to use for connections to the server (if not explicitly specified +in the update). The default is 53 for UDP/TCP or 853 for QUIC. +.TP +\fB\-r\fP, \fB\-\-retry\fP \fIcount\fP +The number of retries for UDP requests. The default is 3. +.TP +\fB\-t\fP, \fB\-\-timeout\fP \fIseconds\fP +The total timeout (for all UDP update tries) of the update request in seconds. +The default is 12. If set to zero, the timeout is infinite. +.TP +\fB\-y\fP, \fB\-\-tsig\fP [\fIalg\fP:]\fIname\fP:\fIkey\fP +Use the TSIG key with a name \fIname\fP to authenticate the request. The \fIalg\fP +part specifies the algorithm (the default is hmac\-sha256) and \fIkey\fP specifies +the shared secret encoded in Base64. +.TP +\fB\-k\fP, \fB\-\-tsigfile\fP \fIpath\fP +Use the TSIG key stored in a file \fIkeyfile\fP to authenticate the request. The +file should contain the key in the same format, which is accepted by the +\fB\-y\fP option. +.TP +\fB\-d\fP, \fB\-\-debug\fP +Enable debug messages. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.UNINDENT +.SS QUIC/TLS options +.INDENT 0.0 +.TP +\fB\-H\fP, \fB\-\-hostname\fP \fIstring\fP +Enable remote server hostname validation. +.TP +\fB\-P\fP, \fB\-\-pin\fP \fIbase64\fP +Use Out\-of\-Band key\-pinned privacy profile +(RFC 7858#section\-4.2). The PIN must be a Base64 encoded SHA\-256 hash of the +X.509 SubjectPublicKeyInfo. Can be specified multiple times. +.TP +\fB\-A\fP, \fB\-\-ca\fP [\fIpath\fP] +Enable certificate validation. Certification authority certificates +are loaded from the specified PEM file (default is system certificate storage +if no argument is provided). Can be specified multiple times. +.TP +\fB\-E\fP, \fB\-\-certfile\fP \fIpath\fP +Path to a client certificate file. +.TP +\fB\-K\fP, \fB\-\-keyfile\fP \fIpath\fP +Path to a client key file. +.TP +\fB\-s\fP, \fB\-\-sni\fP \fIstring\fP +Use specified Server Name Indication. +.UNINDENT +.SS Commands +.INDENT 0.0 +.TP +\fBserver\fP \fIname\fP [\fIport\fP] +Specifies a receiving server of the dynamic update message. The \fIname\fP parameter +can be either a host name or an IP address. If the \fIport\fP is not specified, +the default port is used. The default port value can be controlled using +the \fB\-p\fP program option. +.TP +\fBlocal\fP \fIaddress\fP [\fIport\fP] +Specifies outgoing \fIaddress\fP and \fIport\fP\&. If no local is specified, the +address and port are set by the system automatically. The default port number +is 0. +.TP +\fBzone\fP \fIname\fP +Specifies that all updates are done within a zone \fIname\fP\&. The zone name doesn\(aqt +have a default and must be set explicitly. +.TP +\fBorigin\fP \fIname\fP +Specifies fully qualified domain name suffix which is appended to non\-fqd +owners in update commands. The default is the terminal label (\fB\&.\fP). +.TP +\fBclass\fP \fIname\fP +Sets \fIname\fP as the default class for all updates. If not used, the default +class is IN. +.TP +\fBttl\fP \fIvalue\fP +Sets \fIvalue\fP as the default TTL (in seconds). If not used, the default value +is 3600. +.TP +\fBkey\fP [\fIalg\fP:]\fIname\fP \fIkey\fP +Specifies the TSIG \fIkey\fP named \fIname\fP to authenticate the request. An optional +\fIalg\fP algorithm can be specified. This command has the same effect as +the program option \fB\-y\fP\&. +.TP +[\fBprereq\fP] \fBnxdomain\fP \fIname\fP +Adds a prerequisite for a non\-existing record owned by \fIname\fP\&. +.TP +[\fBprereq\fP] \fByxdomain\fP \fIname\fP +Adds a prerequisite for an existing record owned by \fIname\fP\&. +.TP +[\fBprereq\fP] \fBnxrrset\fP \fIname\fP [\fIclass\fP] \fItype\fP +Adds a prerequisite for a non\-existing record of the \fItype\fP owned by \fIname\fP\&. +Internet \fIclass\fP is expected. +.TP +[\fBprereq\fP] \fByxrrset\fP \fIname\fP [\fIclass\fP] \fItype\fP [\fIdata\fP] +Adds a prerequisite for an existing record of the \fItype\fP owned by \fIname\fP +with optional \fIdata\fP\&. Internet \fIclass\fP is expected. +.TP +[\fBupdate\fP] \fBadd\fP \fIname\fP [\fIttl\fP] [\fIclass\fP] \fItype\fP \fIdata\fP +Adds a request to add a new resource record into the zone. +Please note that if the \fIname\fP is not fully qualified domain name, the +current origin name is appended to it. +.TP +[\fBupdate\fP] \fBdel\fP[\fBete\fP] \fIname\fP [\fIttl\fP] [\fIclass\fP] [\fItype\fP] [\fIdata\fP] +Adds a request to remove all (or matching \fIclass\fP, \fItype\fP or \fIdata\fP) +resource records from the zone. There is the same requirement for the \fIname\fP +parameter as in \fBupdate add\fP command. The \fIttl\fP item is ignored. +.TP +\fBshow\fP +Displays current content of the update message. +.TP +\fBsend\fP +Sends the current update message and cleans the list of updates. +.TP +\fBanswer\fP +Displays the last answer from the server. +.TP +\fBdebug\fP +Enable debugging. This command has the same meaning as the \fB\-d\fP program option. +.TP +\fBexit\fP +End the program. +.UNINDENT +.SH NOTES +.sp +Options \fB\-k\fP and \fB\-y\fP can not be used simultaneously. +.sp +Neither \fItsig\-keygen(8)\fP nor \fIdnssec\-keygen(1)\fP keyfile formats are supported. +Use \fBkeymgr(8)\fP to construct a string for \fB\-y\fP or the file passed to \fB\-k\fP\&. +.sp +Zone name/server guessing is not supported if the zone name/server is not specified. +.sp +An empty line doesn\(aqt send the update. +.SS Interactive mode +.sp +The utility provides interactive mode with basic line editing functionality, +command completion, and command history. +.sp +Interactive mode behavior can be customized in \fI~/.editrc\fP\&. Refer to +\fBeditrc(5)\fP for details. +.sp +Command history is saved in \fI~/.knsupdate_history\fP\&. +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH EXAMPLES +.INDENT 0.0 +.IP 1. 3 +Send one update of the zone example.com to the server 192.168.1.1. The update +contains two new records: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +$ knsupdate +knsupdate> server 192.168.1.1 +knsupdate> zone example.com. +knsupdate> origin example.com. +knsupdate> ttl 3600 +knsupdate> add test1.example.com. 7200 A 192.168.2.2 +knsupdate> add test2 TXT \(dqhello\(dq +knsupdate> show +knsupdate> send +knsupdate> answer +knsupdate> exit +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.SH SEE ALSO +.sp +\fBkdig(1)\fP, \fBkhost(1)\fP, \fBkeymgr(8)\fP, \fBeditrc(5)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/knsupdate.1in b/doc/man/knsupdate.1in deleted file mode 100644 index ed34dd2..0000000 --- a/doc/man/knsupdate.1in +++ /dev/null @@ -1,218 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KNSUPDATE" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -knsupdate \- Dynamic DNS update utility -.SH SYNOPSIS -.sp -\fBknsupdate\fP [\fIoptions\fP] [\fIfilename\fP] -.SH DESCRIPTION -.sp -This utility sends Dynamic DNS update messages to a DNS server. Update content -is read from a file (if the parameter \fIfilename\fP is given) or from the standard -input. -.sp -The format of updates is textual and is made up of commands. Every command is -placed on the separate line of the input. Lines starting with a semicolon are -comments and are not processed. -.SS Parameters -.INDENT 0.0 -.TP -\fIfilename\fP -Path to the file with knsupdate commands. -.UNINDENT -.SS Options -.INDENT 0.0 -.TP -\fB\-d\fP -Enable debug messages. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print the program help. -.TP -\fB\-k\fP \fIkeyfile\fP -Use the TSIG key stored in a file \fIkeyfile\fP to authenticate the request. The -file should contain the key in the same format, which is accepted by the -\fB\-y\fP option. -.TP -\fB\-p\fP \fIport\fP -Set the port to use for connections to the server (if not explicitly specified -in the update). The default is 53. -.TP -\fB\-r\fP \fIretries\fP -The number of retries for UDP requests. The default is 3. -.TP -\fB\-t\fP \fItimeout\fP -The total timeout (for all UDP update tries) of the update request in seconds. -The default is 12. If set to zero, the timeout is infinite. -.TP -\fB\-v\fP -Use a TCP connection. -.TP -\fB\-V\fP, \fB\-\-version\fP -Print the program version. -.TP -\fB\-y\fP [\fIalg\fP:]\fIname\fP:\fIkey\fP -Use the TSIG key with a name \fIname\fP to authenticate the request. The \fIalg\fP -part specifies the algorithm (the default is hmac\-sha256) and \fIkey\fP specifies -the shared secret encoded in Base64. -.UNINDENT -.SS Commands -.INDENT 0.0 -.TP -\fBserver\fP \fIname\fP [\fIport\fP] -Specifies a receiving server of the dynamic update message. The \fIname\fP parameter -can be either a host name or an IP address. If the \fIport\fP is not specified, -the default port is used. The default port value can be controlled using -the \fB\-p\fP program option. -.TP -\fBlocal\fP \fIaddress\fP [\fIport\fP] -Specifies outgoing \fIaddress\fP and \fIport\fP\&. If no local is specified, the -address and port are set by the system automatically. The default port number -is 0. -.TP -\fBzone\fP \fIname\fP -Specifies that all updates are done within a zone \fIname\fP\&. The zone name doesn\(aqt -have a default and must be set explicitly. -.TP -\fBorigin\fP \fIname\fP -Specifies fully qualified domain name suffix which is appended to non\-fqd -owners in update commands. The default is the terminal label (\fB\&.\fP). -.TP -\fBclass\fP \fIname\fP -Sets \fIname\fP as the default class for all updates. If not used, the default -class is IN. -.TP -\fBttl\fP \fIvalue\fP -Sets \fIvalue\fP as the default TTL (in seconds). If not used, the default value -is 3600. -.TP -\fBkey\fP [\fIalg\fP:]\fIname\fP \fIkey\fP -Specifies the TSIG \fIkey\fP named \fIname\fP to authenticate the request. An optional -\fIalg\fP algorithm can be specified. This command has the same effect as -the program option \fB\-y\fP\&. -.TP -[\fBprereq\fP] \fBnxdomain\fP \fIname\fP -Adds a prerequisite for a non\-existing record owned by \fIname\fP\&. -.TP -[\fBprereq\fP] \fByxdomain\fP \fIname\fP -Adds a prerequisite for an existing record owned by \fIname\fP\&. -.TP -[\fBprereq\fP] \fBnxrrset\fP \fIname\fP [\fIclass\fP] \fItype\fP -Adds a prerequisite for a non\-existing record of the \fItype\fP owned by \fIname\fP\&. -Internet \fIclass\fP is expected. -.TP -[\fBprereq\fP] \fByxrrset\fP \fIname\fP [\fIclass\fP] \fItype\fP [\fIdata\fP] -Adds a prerequisite for an existing record of the \fItype\fP owned by \fIname\fP -with optional \fIdata\fP\&. Internet \fIclass\fP is expected. -.TP -[\fBupdate\fP] \fBadd\fP \fIname\fP [\fIttl\fP] [\fIclass\fP] \fItype\fP \fIdata\fP -Adds a request to add a new resource record into the zone. -Please note that if the \fIname\fP is not fully qualified domain name, the -current origin name is appended to it. -.TP -[\fBupdate\fP] \fBdel\fP[\fBete\fP] \fIname\fP [\fIttl\fP] [\fIclass\fP] [\fItype\fP] [\fIdata\fP] -Adds a request to remove all (or matching \fIclass\fP, \fItype\fP or \fIdata\fP) -resource records from the zone. There is the same requirement for the \fIname\fP -parameter as in \fBupdate add\fP command. The \fIttl\fP item is ignored. -.TP -\fBshow\fP -Displays current content of the update message. -.TP -\fBsend\fP -Sends the current update message and cleans the list of updates. -.TP -\fBanswer\fP -Displays the last answer from the server. -.TP -\fBdebug\fP -Enable debugging. This command has the same meaning as the \fB\-d\fP program option. -.TP -\fBexit\fP -End the program. -.UNINDENT -.SH NOTES -.sp -Options \fB\-k\fP and \fB\-y\fP can not be used simultaneously. -.sp -Neither \fItsig\-keygen(8)\fP nor \fIdnssec\-keygen(1)\fP keyfile formats are supported. -Use \fBkeymgr(8)\fP to construct a string for \fB\-y\fP or the file passed to \fB\-k\fP\&. -.sp -Zone name/server guessing is not supported if the zone name/server is not specified. -.sp -An empty line doesn\(aqt send the update. -.SS Interactive mode -.sp -The utility provides interactive mode with basic line editing functionality, -command completion, and command history. -.sp -Interactive mode behavior can be customized in \fI~/.editrc\fP\&. Refer to -\fBeditrc(5)\fP for details. -.sp -Command history is saved in \fI~/.knsupdate_history\fP\&. -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH EXAMPLES -.INDENT 0.0 -.IP 1. 3 -Send one update of the zone example.com to the server 192.168.1.1. The update -contains two new records: -.INDENT 3.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ knsupdate -knsupdate> server 192.168.1.1 -knsupdate> zone example.com. -knsupdate> origin example.com. -knsupdate> ttl 3600 -knsupdate> add test1.example.com. 7200 A 192.168.2.2 -knsupdate> add test2 TXT \(dqhello\(dq -knsupdate> show -knsupdate> send -knsupdate> answer -knsupdate> exit -.ft P -.fi -.UNINDENT -.UNINDENT -.UNINDENT -.SH SEE ALSO -.sp -\fBkdig(1)\fP, \fBkhost(1)\fP, \fBkeymgr(8)\fP, \fBeditrc(5)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/kxdpgun.8 b/doc/man/kxdpgun.8 new file mode 100644 index 0000000..d7892eb --- /dev/null +++ b/doc/man/kxdpgun.8 @@ -0,0 +1,299 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KXDPGUN" "8" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +kxdpgun \- XDP-powered DNS benchmarking tool +.SH SYNOPSIS +.sp +\fBkxdpgun\fP [\fIoptions\fP] \fB\-i\fP \fIfilename\fP \fItarget\fP +.SH DESCRIPTION +.sp +Powerful generator of DNS traffic, sending and receiving packets through XDP. +.sp +Queries are generated according to a textual file which is read sequentially +in a loop until a configured duration elapses. The order of queries is not +guaranteed. Responses are received (unless disabled) and counted, but not +checked against queries. +.sp +The number of parallel threads is autodetected according to the number of queues +configured for the network interface. +.SS Parameters +.INDENT 0.0 +.TP +.B \fIfilename\fP +Path to the queries file. See the description below regarding the file format. +.TP +.B \fItarget\fP +Either the domain name, IPv4 or IPv6 address of a remote target. +.UNINDENT +.SS Options +.INDENT 0.0 +.TP +\fB\-t\fP, \fB\-\-duration\fP \fIseconds\fP +Duration of traffic generation, specified as a decimal number in seconds +(default is 5.0). +.TP +\fB\-T\fP, \fB\-\-tcp\fP[\fB=\fP\fIdebug_mode\fP] +Send queries over TCP. See the list of optional debug modes below. +.TP +\fB\-U\fP, \fB\-\-quic\fP[\fB=\fP\fIdebug_mode\fP] +Send queries over QUIC. See the list of optional debug modes below. +.TP +\fB\-Q\fP, \fB\-\-qps\fP \fIqueries\fP +Number of queries\-per\-second (approximately) to be sent (default is 1000). +The program is not optimized for low speeds at which it may lose +communication packets. The recommended minimum speed is 2 packets per thread +(Rx/Tx queue). +.TP +\fB\-b\fP, \fB\-\-batch\fP \fIsize\fP +Send more queries in a batch. Improves QPS but may affect the counterpart\(aqs +packet loss (default is 10 for UDP and 1 for TCP/QUIC). +.TP +\fB\-r\fP, \fB\-\-drop\fP +Drop incoming responses. Improves QPS, but disables response statistics. +.TP +\fB\-p\fP, \fB\-\-port\fP \fInumber\fP +Remote destination port (default is 53 for UDP/TCP, 853 for QUIC). +.TP +\fB\-F\fP, \fB\-\-affinity\fP \fIcpu_spec\fP +CPU affinity for all threads specified in the format [][s], +where is the CPU ID for the first thread and is the +CPU ID increment for next thread (default is 0s1). +.TP +\fB\-i\fP, \fB\-\-infile\fP \fIfilename\fP +Path to a file with query templates. +.TP +\fB\-B\fP, \fB\-\-binary\fP +Specify that input file is in binary format. This format is similar to the +TCP DNS message format. The file contains records formated as 2\-octet length +(network order) followed by a message in DNS wire format. +.TP +\fB\-I\fP, \fB\-\-interface\fP \fIinterface\fP +Network interface for outgoing communication. This can be useful in situations +when the interfaces are in a bond for example. +.TP +\fB\-l\fP, \fB\-\-local\fP \fIlocalIP\fP[\fB/\fP\fIprefix\fP] +Override the auto\-detected source IP address. If an address range is specified +instead, various IPs from the range will be used for different queries uniformly +(address range not supported in the QUIC mode). +.TP +\fB\-L\fP, \fB\-\-mac\-local\fP +Override auto\-detected local MAC address. +.TP +\fB\-R\fP, \fB\-\-mac\-remote\fP +Override auto\-detected remote MAC address. +.TP +\fB\-v\fP, \fB\-\-vlan\fP \fIid\fP +Add VLAN 802.1Q header with the given id. VLAN offloading should be disabled. +.TP +\fB\-e\fP, \fB\-\-edns\-size\fP \fIsize\fP +EDNS UDP payload size, range 512\-4096 (default is 1232). Note that over XDP +the maximum supported MTU is 1790. +.TP +\fB\-m\fP, \fB\-\-mode\fP \fImode\fP +Set the XDP mode. Supported values are: +.INDENT 7.0 +.IP \(bu 2 +\fBauto\fP (default) – the XDP mode is selected automatically to achieve +the best performance, which means that native driver support is preferred +over the generic one, and zero\-copy is used if available. +.IP \(bu 2 +\fBcopy\fP – the XDP socket copy mode is forced even if zero\-copy +is available. This can resolve various driver issues, but at the cost +of lower performance. +.IP \(bu 2 +\fBgeneric\fP – the generic XDP implementation is forced even if native +implementation is available. This mode doesn\(aqt require support from the +driver nor hardware, but offers the worst performance. +.UNINDENT +.TP +\fB\-G\fP, \fB\-\-qlog\fP \fIpath\fP +Generate qlog files in the directory specified by \fIpath\fP\&. The directory +has to exist. +.sp +This option is ignored if not in the QUIC mode. The recommended usage is +with \fB\-\-quic=R\fP or with low QPS. Otherwise, too many files are generated. +.TP +\fB\-j\fP, \fB\-\-json\fP +Print statistics formatted as json. +.TP +\fB\-S\fP, \fB\-\-stats\-period\fP \fIperiod\fP +Report statistics automatically every \fIperiod\fP milliseconds. +.sp +These reports contain only metrics collected in the given period. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.UNINDENT +.SS Queries file format +.sp +Each line describes a query in the form: +.sp +\fIquery_name\fP \fIquery_type\fP [\fIflags\fP] +.sp +Where \fIquery_name\fP is a domain name to be queried, \fIquery_type\fP is a record type +name, and \fIflags\fP is a single character: +.sp +\fBE\fP Send query with EDNS. +.sp +\fBD\fP Request DNSSEC (EDNS + DO flag). +.SS TCP/QUIC debug modes +.INDENT 0.0 +.TP +\fB0\fP +Perform full handshake for all connections (QUIC only). +.TP +\fB1\fP +Just send SYN (Initial) and receive SYN\-ACK (Handshake). +.TP +\fB2\fP +Perform TCP/QUIC handshake and don\(aqt send anything, allow close initiated by counterpart. +.TP +\fB3\fP +Perform TCP/QUIC handshake and don\(aqt react further. +.TP +\fB5\fP +Send incomplete query (N\-1 bytes) and don\(aqt react further. +.TP +\fB7\fP +Send query and don\(aqt ACK the response or anything further. +.TP +\fB8\fP +Don\(aqt close the connection and ignore close by counterpart. +.TP +\fB9\fP +Operate normally except for not ACKing the final FIN+ACK (TCP only). +.TP +\fBR\fP +Instead of opening a connection for each query, reuse connections. +.UNINDENT +.SS Signals +.sp +Sending USR1 signal to a running process triggers current statistics dump +to the standard output. In combination with \fB\-S\fP may cause erratic printout +timing. +.SH NOTES +.sp +Linux kernel 4.18+ is required. +.sp +The utility has to be executed under root or with these capabilities: +CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_ADMIN, CAP_IPC_LOCK, and CAP_SYS_RESOURCE +(Linux < 5.11). +.sp +The utility allocates source UDP/TCP ports from the range 2000\-65535. +.sp +Due to the multi\-threaded program structure there are slight discrepancies in +the timespan during which metrics are collected for any given thread. The +statistics printouts ignore this and are thus ever\-so\-slightly inaccurate. The +error margin decreases proportionally to the volume of data & timespan over +which they are collected. +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH EXAMPLES +.sp +Manually created queries file: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +abc6.example.com. AAAA +nxdomain.example.com. A +notzone. A +a.example.com. NS E +ab.example.com. A D +abcd.example.com. DS D +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Queries file generated from a zone file (Knot DNS format): +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +cat ZONE_FILE | awk \(dq{print \e$1,\e$3}\(dq | grep \-E \(dq(NS|DS|A|AAAA|PTR|MX|SOA)$\(dq | sort \-u \-R > queries.txt +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Basic usage: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +# kxdpgun \-i ~/queries.txt 2001:DB8::1 +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fIUsing UDP with increased batch size\fP: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +# kxdpgun \-t 20 \-Q 1000000 \-i ~/queries.txt \-b 20 \-p 8853 192.0.2.1 +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fIUsing TCP\fP: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +# kxdpgun \-t 20 \-Q 100000 \-i ~/queries.txt \-T \-p 8853 192.0.2.1 +.ft P +.fi +.UNINDENT +.UNINDENT +.SH SEE ALSO +.sp +\fBkdig(1)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/kxdpgun.8in b/doc/man/kxdpgun.8in deleted file mode 100644 index f93872b..0000000 --- a/doc/man/kxdpgun.8in +++ /dev/null @@ -1,278 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KXDPGUN" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -kxdpgun \- XDP-powered DNS benchmarking tool -.SH SYNOPSIS -.sp -\fBkxdpgun\fP [\fIoptions\fP] \fB\-i\fP \fIfilename\fP \fItarget\fP -.SH DESCRIPTION -.sp -Powerful generator of DNS traffic, sending and receiving packets through XDP. -.sp -Queries are generated according to a textual file which is read sequentially -in a loop until a configured duration elapses. The order of queries is not -guaranteed. Responses are received (unless disabled) and counted, but not -checked against queries. -.sp -The number of parallel threads is autodetected according to the number of queues -configured for the network interface. -.SS Parameters -.INDENT 0.0 -.TP -\fIfilename\fP -Path to the queries file. See the description below regarding the file format. -.TP -\fItarget\fP -Either the domain name, IPv4 or IPv6 address of a remote target. -.UNINDENT -.SS Options -.INDENT 0.0 -.TP -\fB\-t\fP, \fB\-\-duration\fP \fIseconds\fP -Duration of traffic generation, specified as a decimal number in seconds -(default is 5.0). -.TP -\fB\-T\fP, \fB\-\-tcp\fP[\fB=\fP\fIdebug_mode\fP] -Send queries over TCP. See the list of optional debug modes below. -.TP -\fB\-U\fP, \fB\-\-quic\fP[\fB=\fP\fIdebug_mode\fP] -Send queries over QUIC. See the list of optional debug modes below. -.TP -\fB\-Q\fP, \fB\-\-qps\fP \fIqueries\fP -Number of queries\-per\-second (approximately) to be sent (default is 1000). -The program is not optimized for low speeds at which it may lose -communication packets. The recommended minimum speed is 2 packets per thread -(Rx/Tx queue). -.TP -\fB\-b\fP, \fB\-\-batch\fP \fIsize\fP -Send more queries in a batch. Improves QPS but may affect the counterpart\(aqs -packet loss (default is 10 for UDP and 1 for TCP/QUIC). -.TP -\fB\-r\fP, \fB\-\-drop\fP -Drop incoming responses. Improves QPS, but disables response statistics. -.TP -\fB\-p\fP, \fB\-\-port\fP \fInumber\fP -Remote destination port (default is 53 for UDP/TCP, 853 for QUIC). -.TP -\fB\-F\fP, \fB\-\-affinity\fP \fIcpu_spec\fP -CPU affinity for all threads specified in the format [][s], -where is the CPU ID for the first thread and is the -CPU ID increment for next thread (default is 0s1). -.TP -\fB\-i\fP, \fB\-\-infile\fP \fIfilename\fP -Path to a file with query templates. -.TP -\fB\-I\fP, \fB\-\-interface\fP \fIinterface\fP -Network interface for outgoing communication. This can be useful in situations -when the interfaces are in a bond for example. -.TP -\fB\-l\fP, \fB\-\-local\fP \fIlocalIP\fP[\fB/\fP\fIprefix\fP] -Override the auto\-detected source IP address. If an address range is specified -instead, various IPs from the range will be used for different queries uniformly -(address range not supported in the QUIC mode). -.TP -\fB\-L\fP, \fB\-\-mac\-local\fP -Override auto\-detected local MAC address. -.TP -\fB\-R\fP, \fB\-\-mac\-remote\fP -Override auto\-detected remote MAC address. -.TP -\fB\-v\fP, \fB\-\-vlan\fP \fIid\fP -Add VLAN 802.1Q header with the given id. VLAN offloading should be disabled. -.TP -\fB\-e\fP, \fB\-\-edns\-size\fP \fIsize\fP -EDNS UDP payload size, range 512\-4096 (default is 1232). Note that over XDP -the maximum supported MTU is 1790. -.TP -\fB\-m\fP, \fB\-\-mode\fP \fImode\fP -Set the XDP mode. Supported values are: -.INDENT 7.0 -.IP \(bu 2 -\fBauto\fP (default) – the XDP mode is selected automatically to achieve -the best performance, which means that native driver support is preferred -over the generic one, and zero\-copy is used if available. -.IP \(bu 2 -\fBcopy\fP – the XDP socket copy mode is forced even if zero\-copy -is available. This can resolve various driver issues, but at the cost -of lower performance. -.IP \(bu 2 -\fBgeneric\fP – the generic XDP implementation is forced even if native -implementation is available. This mode doesn\(aqt require support from the -driver nor hardware, but offers the worst performance. -.UNINDENT -.TP -\fB\-G\fP, \fB\-\-qlog\fP \fIpath\fP -Generate qlog files in the directory specified by \fIpath\fP\&. The directory -has to exist. -.sp -This option is ignored if not in the QUIC mode. The recommended usage is -with \fB\-\-quic=R\fP or with low QPS. Otherwise, too many files are generated. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print the program help. -.TP -\fB\-V\fP, \fB\-\-version\fP -Print the program version. -.UNINDENT -.SS Queries file format -.sp -Each line describes a query in the form: -.sp -\fIquery_name\fP \fIquery_type\fP [\fIflags\fP] -.sp -Where \fIquery_name\fP is a domain name to be queried, \fIquery_type\fP is a record type -name, and \fIflags\fP is a single character: -.sp -\fBE\fP Send query with EDNS. -.sp -\fBD\fP Request DNSSEC (EDNS + DO flag). -.SS TCP/QUIC debug modes -.INDENT 0.0 -.TP -\fB0\fP -Perform full handshake for all connections (QUIC only). -.TP -\fB1\fP -Just send SYN (Initial) and receive SYN\-ACK (Handshake). -.TP -\fB2\fP -Perform TCP/QUIC handshake and don\(aqt send anything, allow close initiated by counterpart. -.TP -\fB3\fP -Perform TCP/QUIC handshake and don\(aqt react further. -.TP -\fB5\fP -Send incomplete query (N\-1 bytes) and don\(aqt react further. -.TP -\fB7\fP -Send query and don\(aqt ACK the response or anything further. -.TP -\fB8\fP -Don\(aqt close the connection and ignore close by counterpart. -.TP -\fB9\fP -Operate normally except for not ACKing the final FIN+ACK (TCP only). -.TP -\fBR\fP -Instead of opening a connection for each query, reuse connections. -.UNINDENT -.SS Signals -.sp -Sending USR1 signal to a running process triggers current statistics dump -to the standard output. -.SH NOTES -.sp -Linux kernel 4.18+ is required. -.sp -The utility has to be executed under root or with these capabilities: -CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_ADMIN, CAP_IPC_LOCK, and CAP_SYS_RESOURCE -(Linux < 5.11). -.sp -The utility allocates source UDP/TCP ports from the range 2000\-65535. -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH EXAMPLES -.sp -Manually created queries file: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -abc6.example.com. AAAA -nxdomain.example.com. A -notzone. A -a.example.com. NS E -ab.example.com. A D -abcd.example.com. DS D -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -Queries file generated from a zone file (Knot DNS format): -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -cat ZONE_FILE | awk \(dq{print \e$1,\e$3}\(dq | grep \-E \(dq(NS|DS|A|AAAA|PTR|MX|SOA)$\(dq | sort \-u \-R > queries.txt -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -Basic usage: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -# kxdpgun \-i ~/queries.txt 2001:DB8::1 -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -\fIUsing UDP with increased batch size\fP: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -# kxdpgun \-t 20 \-Q 1000000 \-i ~/queries.txt \-b 20 \-p 8853 192.0.2.1 -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -\fIUsing TCP\fP: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -# kxdpgun \-t 20 \-Q 100000 \-i ~/queries.txt \-T \-p 8853 192.0.2.1 -.ft P -.fi -.UNINDENT -.UNINDENT -.SH SEE ALSO -.sp -\fBkdig(1)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/kzonecheck.1 b/doc/man/kzonecheck.1 new file mode 100644 index 0000000..22ebe47 --- /dev/null +++ b/doc/man/kzonecheck.1 @@ -0,0 +1,95 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KZONECHECK" "1" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +kzonecheck \- Knot DNS zone check tool +.SH SYNOPSIS +.sp +\fBkzonecheck\fP [\fIoptions\fP] \fIfilename\fP +.SH DESCRIPTION +.sp +The utility checks zone file syntax and runs semantic checks on the zone +content. The executed checks are the same as the checks run by the Knot +DNS server. +.sp +Please, refer to the \fBsemantic\-checks\fP configuration option in +\fBknot.conf(5)\fP for the full list of available semantic checks. +.SS Parameters +.INDENT 0.0 +.TP +.B \fIfilename\fP +Path to the zone file to be checked. For reading from \fBstdin\fP use \fB/dev/stdin\fP +or just \fB\-\fP\&. +.UNINDENT +.SS Options +.INDENT 0.0 +.TP +\fB\-o\fP, \fB\-\-origin\fP \fIorigin\fP +Zone origin. If not specified, the origin is determined from the file name +(possibly removing the \fB\&.zone\fP suffix). +.TP +\fB\-d\fP, \fB\-\-dnssec\fP \fBon\fP|\fBoff\fP +Also check DNSSEC\-related records. The default is to decide based on the +existence of a RRSIG for SOA. +.TP +\fB\-z\fP, \fB\-\-zonemd\fP +Also check the zone hash against a ZONEMD record, which is required to exist. +.TP +\fB\-t\fP, \fB\-\-time\fP \fItime\fP +Current time specification. Use UNIX timestamp, YYYYMMDDHHmmSS +format, or [+/\-]\fItime\fP[unit] format, where unit can be \fBY\fP, \fBM\fP, +\fBD\fP, \fBh\fP, \fBm\fP, or \fBs\fP\&. Default is current UNIX timestamp. +.TP +\fB\-p\fP, \fB\-\-print\fP +Print the zone on stdout. +.TP +\fB\-v\fP, \fB\-\-verbose\fP +Enable debug output. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.UNINDENT +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH SEE ALSO +.sp +\fBknotd(8)\fP, \fBknot.conf(5)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/kzonecheck.1in b/doc/man/kzonecheck.1in deleted file mode 100644 index a73b66e..0000000 --- a/doc/man/kzonecheck.1in +++ /dev/null @@ -1,94 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KZONECHECK" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -kzonecheck \- Knot DNS zone check tool -.SH SYNOPSIS -.sp -\fBkzonecheck\fP [\fIoptions\fP] \fIfilename\fP -.SH DESCRIPTION -.sp -The utility checks zone file syntax and runs semantic checks on the zone -content. The executed checks are the same as the checks run by the Knot -DNS server. -.sp -Please, refer to the \fBsemantic\-checks\fP configuration option in -\fBknot.conf(5)\fP for the full list of available semantic checks. -.SS Parameters -.INDENT 0.0 -.TP -\fIfilename\fP -Path to the zone file to be checked. For reading from \fBstdin\fP use \fB/dev/stdin\fP -or just \fB\-\fP\&. -.UNINDENT -.SS Options -.INDENT 0.0 -.TP -\fB\-o\fP, \fB\-\-origin\fP \fIorigin\fP -Zone origin. If not specified, the origin is determined from the file name -(possibly removing the \fB\&.zone\fP suffix). -.TP -\fB\-d\fP, \fB\-\-dnssec\fP \fBon\fP|\fBoff\fP -Also check DNSSEC\-related records. The default is to decide based on the -existence of a RRSIG for SOA. -.TP -\fB\-z\fP, \fB\-\-zonemd\fP -Also check the zone hash against a ZONEMD record, which is required to exist. -.TP -\fB\-t\fP, \fB\-\-time\fP \fItime\fP -Current time specification. Use UNIX timestamp, YYYYMMDDHHmmSS -format, or [+/\-]\fItime\fP[unit] format, where unit can be \fBY\fP, \fBM\fP, -\fBD\fP, \fBh\fP, \fBm\fP, or \fBs\fP\&. Default is current UNIX timestamp. -.TP -\fB\-p\fP, \fB\-\-print\fP -Print the zone on stdout. -.TP -\fB\-v\fP, \fB\-\-verbose\fP -Enable debug output. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print the program help. -.TP -\fB\-V\fP, \fB\-\-version\fP -Print the program version. -.UNINDENT -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH SEE ALSO -.sp -\fBknotd(8)\fP, \fBknot.conf(5)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man/kzonesign.1 b/doc/man/kzonesign.1 new file mode 100644 index 0000000..558c95b --- /dev/null +++ b/doc/man/kzonesign.1 @@ -0,0 +1,96 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "KZONESIGN" "1" "2024-09-02" "3.4.0" "Knot DNS" +.SH NAME +kzonesign \- DNSSEC signing utility +.SH SYNOPSIS +.sp +\fBkzonesign\fP [\fIconfig_option\fP] [\fIoptions\fP] \fIzone_name\fP +.SH DESCRIPTION +.sp +This utility reads the zone\(aqs zone file, signs the zone according to given +configuration, and writes the signed zone file back. An alternative mode +is DNSSEC validation of the given zone. The signing or validation +can run in parallel if enabled in the configuration (see policy.signing\-threads +and zone.adjust\-threads). +.SS Parameters +.INDENT 0.0 +.TP +.B \fIzone_name\fP +A name of the zone to be signed. +.UNINDENT +.SS Config options +.INDENT 0.0 +.TP +\fB\-c\fP, \fB\-\-config\fP \fIfile\fP +Use a textual configuration file (default is \fB/usr/local/etc/knot/knot.conf\fP). +.TP +\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP +Use a binary configuration database directory (default is \fB/usr/local/var/lib/knot/confdb\fP). +The default configuration database, if exists, has a preference to the default +configuration file. +.UNINDENT +.SS Options +.INDENT 0.0 +.TP +\fB\-o\fP, \fB\-\-outdir\fP \fIdir_name\fP +Write the output zone file to the specified directory instead of the configured one. +.TP +\fB\-r\fP, \fB\-\-rollover\fP +Allow key roll\-overs and NSEC3 re\-salt. In order to finish possible KSK submission, +set the KSK\(aqs \fBactive\fP timestamp to now (\fB+0\fP) using \fI\%keymgr\fP\&. +.TP +\fB\-v\fP, \fB\-\-verify\fP +Instead of (re\-)signing the zone, just verify that the zone is correctly signed. +.TP +\fB\-t\fP, \fB\-\-time\fP \fItimestamp\fP +Sign/verify the zone (and roll the keys if necessary) as if it was at the time +specified by timestamp. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. +.TP +\fB\-V\fP, \fB\-\-version\fP +Print the program version. The option \fB\-VV\fP makes the program +print the compile time configuration summary. +.UNINDENT +.SH EXIT VALUES +.sp +Exit status of 0 means successful operation. Any other exit status indicates +an error. +.SH SEE ALSO +.sp +\fBknot.conf(5)\fP, \fBkeymgr(8)\fP\&. +.SH AUTHOR +CZ.NIC Labs +.SH COPYRIGHT +Copyright 2010–2024, CZ.NIC, z.s.p.o. +.\" Generated by docutils manpage writer. +. diff --git a/doc/man/kzonesign.1in b/doc/man/kzonesign.1in deleted file mode 100644 index 147e112..0000000 --- a/doc/man/kzonesign.1in +++ /dev/null @@ -1,95 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "KZONESIGN" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS" -.SH NAME -kzonesign \- DNSSEC signing utility -.SH SYNOPSIS -.sp -\fBkzonesign\fP [\fIconfig_option\fP] [\fIoptions\fP] \fIzone_name\fP -.SH DESCRIPTION -.sp -This utility reads the zone\(aqs zone file, signs the zone according to given -configuration, and writes the signed zone file back. An alternative mode -is DNSSEC validation of the given zone. The signing or validation -can run in parallel if enabled in the configuration (see policy.signing\-threads -and zone.adjust\-threads). -.SS Parameters -.INDENT 0.0 -.TP -\fIzone_name\fP -A name of the zone to be signed. -.UNINDENT -.SS Config options -.INDENT 0.0 -.TP -\fB\-c\fP, \fB\-\-config\fP \fIfile\fP -Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP). -.TP -\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP -Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP). -The default configuration database, if exists, has a preference to the default -configuration file. -.UNINDENT -.SS Options -.INDENT 0.0 -.TP -\fB\-o\fP, \fB\-\-outdir\fP \fIdir_name\fP -Write the output zone file to the specified directory instead of the configured one. -.TP -\fB\-r\fP, \fB\-\-rollover\fP -Allow key roll\-overs and NSEC3 re\-salt. In order to finish possible KSK submission, -set the KSK\(aqs \fBactive\fP timestamp to now (\fB+0\fP) using \fI\%keymgr\fP\&. -.TP -\fB\-v\fP, \fB\-\-verify\fP -Instead of (re\-)signing the zone, just verify that the zone is correctly signed. -.TP -\fB\-t\fP, \fB\-\-time\fP \fItimestamp\fP -Sign/verify the zone (and roll the keys if necessary) as if it was at the time -specified by timestamp. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print the program help. -.TP -\fB\-V\fP, \fB\-\-version\fP -Print the program version. -.UNINDENT -.SH EXIT VALUES -.sp -Exit status of 0 means successful operation. Any other exit status indicates -an error. -.SH SEE ALSO -.sp -\fBknot.conf(5)\fP, \fBkeymgr(8)\fP\&. -.SH AUTHOR -CZ.NIC Labs -.SH COPYRIGHT -Copyright 2010–2024, CZ.NIC, z.s.p.o. -.\" Generated by docutils manpage writer. -. diff --git a/doc/man_kcatalogprint.rst b/doc/man_kcatalogprint.rst index cccc641..da2ed97 100644 --- a/doc/man_kcatalogprint.rst +++ b/doc/man_kcatalogprint.rst @@ -40,7 +40,8 @@ Options Print the program help. **-V**, **--version** - Print the program version. + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. Exit values ----------- diff --git a/doc/man_kdig.rst b/doc/man_kdig.rst index 4457b68..cda3303 100644 --- a/doc/man_kdig.rst +++ b/doc/man_kdig.rst @@ -111,7 +111,8 @@ Options An explicit *query_type* specification. See possible values above. **-V**, **--version** - Print the program version. + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. **-x** *address* Send a reverse (PTR) query for IPv4 or IPv6 *address*. The correct name, class @@ -281,7 +282,7 @@ Options Request the nameserver identifier (NSID). **+**\ [\ **no**\ ]\ **bufsize**\ =\ *B* - Set EDNS buffer size in bytes (default is 4096 bytes). + Set EDNS buffer size in bytes (default is 1232 bytes). **+**\ [\ **no**\ ]\ **padding**\[\ =\ *B*\] Use EDNS(0) padding option to pad queries, optionally to a specific @@ -298,7 +299,7 @@ Options Set EDNS(0) client subnet SUBN=addr/prefix. **+**\ [\ **no**\ ]\ **edns**\[\ =\ *N*\] - Use EDNS version (default is 0). + Use EDNS version (default is 0). EDNS(0) is enabled by default. **+**\ [\ **no**\ ]\ **timeout**\ =\ *T* Set the wait-for-reply interval in seconds (default is 5 seconds). This timeout @@ -333,7 +334,7 @@ Options **+noidn** Disable the IDN transformation to ASCII and vice versa. IDN support depends - on libidn availability during project building! If used in *common-settings*, + on libidn2 availability during project building! If used in *common-settings*, all IDN transformations are disabled. If used in the individual query *settings*, transformation from ASCII is disabled on output for the particular query. Note that IDN transformation does not preserve domain name letter case. diff --git a/doc/man_keymgr.rst b/doc/man_keymgr.rst index 136a92c..a0001fe 100644 --- a/doc/man_keymgr.rst +++ b/doc/man_keymgr.rst @@ -75,7 +75,8 @@ Options Print the program help. **-V**, **--version** - Print the program version. + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. .. NOTE:: Keymgr runs with the same user privileges as configured for :doc:`knotd`. diff --git a/doc/man_khost.rst b/doc/man_khost.rst index 1fcc0bf..9447856 100644 --- a/doc/man_khost.rst +++ b/doc/man_khost.rst @@ -57,7 +57,8 @@ Options Enable verbose output. **-V**, **--version** - Print the program version. + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. **-w** Wait forever for the reply. diff --git a/doc/man_kjournalprint.rst b/doc/man_kjournalprint.rst index f83a137..3b2d024 100644 --- a/doc/man_kjournalprint.rst +++ b/doc/man_kjournalprint.rst @@ -57,9 +57,6 @@ Options **-x**, **--mono** Don't generate colorized output. -**-n**, **--no-color** - An alias for **-x**. Use of this option is deprecated, it will be removed in the future. - **-X**, **--color** Force colorized output. @@ -67,7 +64,8 @@ Options Print the program help. **-V**, **--version** - Print the program version. + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. Exit values ----------- diff --git a/doc/man_knotc.rst b/doc/man_knotc.rst index d03bc77..4755a6a 100644 --- a/doc/man_knotc.rst +++ b/doc/man_knotc.rst @@ -65,7 +65,8 @@ Options Print the program help. **-V**, **--version** - Print the program version. + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. Actions ....... @@ -150,8 +151,9 @@ Actions explicitly. If zone flushing is disabled, the original zone file is backed up instead of writing out zone contents to a file. When backing-up a catalog zone, it is recommended to prevent ongoing changes to it by use of - **zone-freeze**. - See :ref:`Notes` below about the directory permissions. (#) + **zone-freeze**. The force option allows an already existing backupdir to + be overwritten. See :ref:`Notes` below about the directory permissions. + (#) **zone-restore** [*zone*...] **+backupdir** *directory* [*filter*...] Trigger a zone data and metadata restore from a specified backup directory. @@ -164,6 +166,10 @@ Actions Trigger a DNSSEC re-sign of the zone. Existing signatures will be dropped. This command is valid for zones with DNSSEC signing enabled. (#) +**zone-validate** [*zone*...] + Trigger a DNSSEC validation of the zone. If the validation fails and the + zone is secondary, the zone expires immediately! (#) + **zone-keys-load** [*zone*...] Trigger a load of DNSSEC keys and other signing material from KASP database (which might have been altered manually). If suitable, re-sign the zone @@ -184,7 +190,8 @@ Actions **zone-freeze** [*zone*...] Trigger a zone freeze. All running events will be finished and all new and pending (planned) zone-changing events (load, refresh, update, flush, and DNSSEC signing) - will be held up until the zone is thawed. (#) + will be held up until the zone is thawed. Up to 8 (this limit is hardcoded) DDNS + updates per zone will be queued, subsequent updates will be refused. (#) **zone-thaw** [*zone*...] Trigger dismissal of zone freeze. (#) diff --git a/doc/man_knotd.rst b/doc/man_knotd.rst index d0fe83b..9f3193f 100644 --- a/doc/man_knotd.rst +++ b/doc/man_knotd.rst @@ -46,7 +46,8 @@ Options Print the program help. **-V**, **--version** - Print the program version. + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. Signals ....... diff --git a/doc/man_knsec3hash.rst b/doc/man_knsec3hash.rst index bf0688c..b3367fe 100644 --- a/doc/man_knsec3hash.rst +++ b/doc/man_knsec3hash.rst @@ -10,6 +10,8 @@ Synopsis :program:`knsec3hash` *algorithm* *flags* *iterations* *salt* *name* +:program:`knsec3hash` [*-h*] [*-V*] + Description ----------- @@ -33,6 +35,16 @@ Parameters *flags* Specifies NSEC3 flags as an unsigned integer. +Options +....... + +**-h**, **--help** + Print the program help. + +**-V**, **--version** + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. + Exit values ----------- diff --git a/doc/man_knsupdate.rst b/doc/man_knsupdate.rst index 40a419b..e2d71f9 100644 --- a/doc/man_knsupdate.rst +++ b/doc/man_knsupdate.rst @@ -6,7 +6,9 @@ Synopsis -------- -:program:`knsupdate` [*options*] [*filename*] +:program:`knsupdate` [**-v**] [*options*] [*filename*] + +:program:`knsupdate` [**-q**] [*quic_options*] [*options*] [*filename*] Description ----------- @@ -28,39 +30,71 @@ Parameters Options ....... -**-d** - Enable debug messages. +**-T**, **--tcp** + Use a TCP connection. (**-v** can be used for compatibility with nsupdate). -**-h**, **--help** - Print the program help. +**-S**, **--tls** + Use a TLS connection. -**-k** *keyfile* - Use the TSIG key stored in a file *keyfile* to authenticate the request. The - file should contain the key in the same format, which is accepted by the - **-y** option. +**-Q**, **--quic** + Use a QUIC connection. -**-p** *port* +**-p**, **--port** *number* Set the port to use for connections to the server (if not explicitly specified - in the update). The default is 53. + in the update). The default is 53 for UDP/TCP or 853 for QUIC. -**-r** *retries* +**-r**, **--retry** *count* The number of retries for UDP requests. The default is 3. -**-t** *timeout* +**-t**, **--timeout** *seconds* The total timeout (for all UDP update tries) of the update request in seconds. The default is 12. If set to zero, the timeout is infinite. -**-v** - Use a TCP connection. - -**-V**, **--version** - Print the program version. - -**-y** [*alg*:]\ *name*:*key* +**-y**, **--tsig** [*alg*:]\ *name*:*key* Use the TSIG key with a name *name* to authenticate the request. The *alg* part specifies the algorithm (the default is hmac-sha256) and *key* specifies the shared secret encoded in Base64. +**-k**, **--tsigfile** *path* + Use the TSIG key stored in a file *keyfile* to authenticate the request. The + file should contain the key in the same format, which is accepted by the + **-y** option. + +**-d**, **--debug** + Enable debug messages. + +**-h**, **--help** + Print the program help. + +**-V**, **--version** + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. + +QUIC/TLS options +................ + +**-H**, **--hostname** *string* + Enable remote server hostname validation. + +**-P**, **--pin** *base64* + Use Out-of-Band key-pinned privacy profile + (RFC 7858#section-4.2). The PIN must be a Base64 encoded SHA-256 hash of the + X.509 SubjectPublicKeyInfo. Can be specified multiple times. + +**-A**, **--ca** [*path*] + Enable certificate validation. Certification authority certificates + are loaded from the specified PEM file (default is system certificate storage + if no argument is provided). Can be specified multiple times. + +**-E**, **--certfile** *path* + Path to a client certificate file. + +**-K**, **--keyfile** *path* + Path to a client key file. + +**-s**, **--sni** *string* + Use specified Server Name Indication. + Commands ........ diff --git a/doc/man_kxdpgun.rst b/doc/man_kxdpgun.rst index 28713ba..bc26d12 100644 --- a/doc/man_kxdpgun.rst +++ b/doc/man_kxdpgun.rst @@ -67,6 +67,11 @@ Options **-i**, **--infile** *filename* Path to a file with query templates. +**-B**, **--binary** + Specify that input file is in binary format. This format is similar to the + TCP DNS message format. The file contains records formated as 2-octet length + (network order) followed by a message in DNS wire format. + **-I**, **--interface** *interface* Network interface for outgoing communication. This can be useful in situations when the interfaces are in a bond for example. @@ -111,11 +116,20 @@ Options This option is ignored if not in the QUIC mode. The recommended usage is with **--quic=R** or with low QPS. Otherwise, too many files are generated. +**-j**, **--json** + Print statistics formatted as json. + +**-S**, **--stats-period** *period* + Report statistics automatically every *period* milliseconds. + + These reports contain only metrics collected in the given period. + **-h**, **--help** Print the program help. **-V**, **--version** - Print the program version. + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. Queries file format ................... @@ -165,7 +179,8 @@ Signals ....... Sending USR1 signal to a running process triggers current statistics dump -to the standard output. +to the standard output. In combination with **-S** may cause erratic printout +timing. Notes ----- @@ -178,6 +193,12 @@ CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_ADMIN, CAP_IPC_LOCK, and CAP_SYS_RESOURCE The utility allocates source UDP/TCP ports from the range 2000-65535. +Due to the multi-threaded program structure there are slight discrepancies in +the timespan during which metrics are collected for any given thread. The +statistics printouts ignore this and are thus ever-so-slightly inaccurate. The +error margin decreases proportionally to the volume of data & timespan over +which they are collected. + Exit values ----------- diff --git a/doc/man_kzonecheck.rst b/doc/man_kzonecheck.rst index 3a10863..c0dae37 100644 --- a/doc/man_kzonecheck.rst +++ b/doc/man_kzonecheck.rst @@ -54,7 +54,8 @@ Options Print the program help. **-V**, **--version** - Print the program version. + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. Exit values ----------- diff --git a/doc/man_kzonesign.rst b/doc/man_kzonesign.rst index c759c57..a1981ee 100644 --- a/doc/man_kzonesign.rst +++ b/doc/man_kzonesign.rst @@ -55,7 +55,8 @@ Options Print the program help. **-V**, **--version** - Print the program version. + Print the program version. The option **-VV** makes the program + print the compile time configuration summary. Exit values ----------- diff --git a/doc/migration.rst b/doc/migration.rst index f79539c..7c4a279 100644 --- a/doc/migration.rst +++ b/doc/migration.rst @@ -249,19 +249,19 @@ Configuration changes - Ignored obsolete options (with a notice log): - - ``server.max-journal-depth`` - - ``server.max-journal-usage`` - - ``server.max-refresh-interval`` - - ``server.min-refresh-interval`` - ``server.max-ipv4-udp-payload`` - ``server.max-ipv6-udp-payload`` - ``server.max-udp-payload`` - ``server.max-tcp-clients`` - ``server.tcp-reply-timeout`` + - ``zone.max-journal-depth`` + - ``zone.max-journal-usage`` + - ``zone.max-refresh-interval`` + - ``zone.min-refresh-interval`` + - ``zone.max-zone-size`` - ``template.journal-db`` - ``template.kasp-db`` - ``template.timer-db`` - - ``template.max-zone-size`` - ``template.max-journal-db-size`` - ``template.max-timer-db-size`` - ``template.max-kasp-db-size`` @@ -393,6 +393,86 @@ Query module API change The function ``knotd_qdata_local_addr()`` only takes one parameter. +.. _Upgrade 3.3.x to 3.4.x: + +Upgrade 3.3.x to 3.4.x +====================== + +There are the following changes between Knot DNS versions 3.4.x and 3.3.x. + +DNSSEC +------ + +- DNSSEC validation fails if the remaining RRSIG validity is shorter than + the corresponding :ref:`policy_rrsig-refresh` value. +- SKR verification fails if the end of a DNSKEY RRSIG validity period doesn't + cover the next DNSKEY snapshot. +- If DNSSEC signing is enabled, the outbound request's EDNS expire value is + lowered to the earliest RRSIG expiration if it is higher. + +Semantic checks +--------------- + +- Just one SOA record is required. +- Unified DNAME and CNAME semantic checks (see :ref:`Handling CNAME and DNAME-related updates`). + +Configuration changes +--------------------- + +- The server no longer allows concurrent control zone and configuration transactions. +- The server no longer allows opening a zone transaction when a blocking command is running. +- Removed already ignored obsolete options: + + - ``server.max-ipv4-udp-payload`` + - ``server.max-ipv6-udp-payload`` + - ``server.max-udp-payload`` + - ``server.max-tcp-clients`` + - ``server.tcp-handshake-timeout`` + - ``server.tcp-reply-timeout`` + - ``server.listen-xdp`` + - ``xdp.quic-log`` + - ``zone.max-journal-depth`` + - ``zone.max-journal-usage`` + - ``zone.max-refresh-interval`` + - ``zone.min-refresh-interval`` + - ``zone.max-zone-size`` + - ``zone.disable-any`` + - ``template.journal-db`` + - ``template.kasp-db`` + - ``template.timer-db`` + - ``template.max-journal-db-size`` + - ``template.max-timer-db-size`` + - ``template.max-kasp-db-size`` + - ``template.journal-db-mode`` + +Utilities +--------- + +- Changed defaults: + + - :doc:`kdig`: enabled ``+edns`` and ``+bufsize=1232`` + +- Removed legacy parameters: + + - :doc:`keymgr`: ``--brief`` + - :doc:`kjournalprint`: ``--no-color`` + - :doc:`kjournalprint`: database specification without ``--dir`` + - :doc:`kjournalprint`: database specification without ``--dir`` + +Documentation +------------- + +- Info pages are no longer supported. + +Building notes +-------------- + +- A GCC or LLVM Clang compiler with C11 support is required. +- Minimum required *GnuTLS* version is 3.6.10. +- *Libidn* version 1 is no longer supported. +- *Liburcu* must be available via pkg-config. +- Linux distributions CentOS 7, Debian 10, and Ubuntu 18.04 are no longer supported. + .. _Knot DNS for BIND users: Knot DNS for BIND users diff --git a/doc/operation.rst b/doc/operation.rst index 5754147..5c2bdf2 100644 --- a/doc/operation.rst +++ b/doc/operation.rst @@ -632,7 +632,7 @@ continues along the lines of :rfc:`6781#section-4.1.2`:: 2024-02-14T15:20:00+0100 info: [example.com.] DNSSEC, key, tag 36185, algorithm ECDSAP256SHA256, public, active 2024-02-14T15:20:00+0100 info: [example.com.] DNSSEC, key, tag 3375, algorithm ECDSAP256SHA256, KSK, public, active+ 2024-02-14T15:20:00+0100 info: [example.com.] DNSSEC, signing started - 2024-02-14T15:20:00+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111204 + 2024-02-14T15:20:00+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111204, new RRSIGs 3 2024-02-14T15:20:00+0100 info: [example.com.] DNSSEC, next signing at 2024-02-14T15:20:12+0100 ... (propagation-delay + dnskey-ttl) ... @@ -643,7 +643,7 @@ continues along the lines of :rfc:`6781#section-4.1.2`:: 2024-02-14T15:20:12+0100 info: [example.com.] DNSSEC, key, tag 36185, algorithm ECDSAP256SHA256, public, active 2024-02-14T15:20:12+0100 info: [example.com.] DNSSEC, key, tag 3375, algorithm ECDSAP256SHA256, KSK, public, ready, active+ 2024-02-14T15:20:12+0100 info: [example.com.] DNSSEC, signing started - 2024-02-14T15:20:12+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111205 + 2024-02-14T15:20:12+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111205, new RRSIGs 6 2024-02-14T15:20:12+0100 info: [example.com.] DNSSEC, next signing at 2024-02-28T15:19:37+0100 At this point the new KSK has to be submitted to the parent zone. Knot detects the updated parent's DS @@ -660,7 +660,7 @@ operator must confirm it manually (using ``knotc zone-ksk-submitted``):: 2024-02-14T15:20:16+0100 info: [example.com.] DNSSEC, key, tag 36185, algorithm ECDSAP256SHA256, public, active 2024-02-14T15:20:16+0100 info: [example.com.] DNSSEC, key, tag 3375, algorithm ECDSAP256SHA256, KSK, public, active 2024-02-14T15:20:16+0100 info: [example.com.] DNSSEC, signing started - 2024-02-14T15:20:16+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111206 + 2024-02-14T15:20:16+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111206, new RRSIGs 2 2024-02-14T15:20:16+0100 info: [example.com.] DNSSEC, next signing at 2024-02-14T15:20:23+0100 ... (parent's DS TTL is 7 seconds) ... @@ -670,7 +670,7 @@ operator must confirm it manually (using ``knotc zone-ksk-submitted``):: 2024-02-14T15:20:23+0100 info: [example.com.] DNSSEC, key, tag 36185, algorithm ECDSAP256SHA256, public, active 2024-02-14T15:20:23+0100 info: [example.com.] DNSSEC, key, tag 3375, algorithm ECDSAP256SHA256, KSK, public, active 2024-02-14T15:20:23+0100 info: [example.com.] DNSSEC, signing started - 2024-02-14T15:20:23+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111207 + 2024-02-14T15:20:23+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111207, new RRSIGs 2 2024-02-14T15:20:23+0100 info: [example.com.] DNSSEC, next signing at 2024-02-14T15:21:54+0100 Upon the zone's ZSK lifetime expiration, a new ZSK is generated and the rollover @@ -685,7 +685,7 @@ continues along the lines of :rfc:`6781#section-4.1.1`:: 2024-02-14T15:21:54+0100 info: [example.com.] DNSSEC, key, tag 3375, algorithm ECDSAP256SHA256, KSK, public, active 2024-02-14T15:21:54+0100 info: [example.com.] DNSSEC, key, tag 38559, algorithm ECDSAP256SHA256, public 2024-02-14T15:21:54+0100 info: [example.com.] DNSSEC, signing started - 2024-02-14T15:21:54+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111208 + 2024-02-14T15:21:54+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111208, new RRSIGs 2 2024-02-14T15:21:54+0100 info: [example.com.] DNSSEC, next signing at 2024-02-14T15:22:06+0100 ... (propagation-delay + dnskey-ttl) ... @@ -696,7 +696,7 @@ continues along the lines of :rfc:`6781#section-4.1.1`:: 2024-02-14T15:22:06+0100 info: [example.com.] DNSSEC, key, tag 3375, algorithm ECDSAP256SHA256, KSK, public, active 2024-02-14T15:22:06+0100 info: [example.com.] DNSSEC, key, tag 38559, algorithm ECDSAP256SHA256, public, active 2024-02-14T15:22:06+0100 info: [example.com.] DNSSEC, signing started - 2024-02-14T15:22:06+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111209 + 2024-02-14T15:22:06+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111209, new RRSIGs 14 2024-02-14T15:22:06+0100 info: [example.com.] DNSSEC, next signing at 2024-02-14T15:22:23+0100 ... (propagation-delay + zone-max-ttl) ... @@ -706,7 +706,7 @@ continues along the lines of :rfc:`6781#section-4.1.1`:: 2024-02-14T15:22:23+0100 info: [example.com.] DNSSEC, key, tag 3375, algorithm ECDSAP256SHA256, KSK, public, active 2024-02-14T15:22:23+0100 info: [example.com.] DNSSEC, key, tag 38559, algorithm ECDSAP256SHA256, public, active 2024-02-14T15:22:23+0100 info: [example.com.] DNSSEC, signing started - 2024-02-14T15:22:23+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111210 + 2024-02-14T15:22:23+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111210, new RRSIGs 2 2024-02-14T15:22:23+0100 info: [example.com.] DNSSEC, next signing at 2024-02-14T15:24:06+0100 Further rollovers:: @@ -722,7 +722,7 @@ Further rollovers:: 2024-02-14T15:24:06+0100 info: [example.com.] DNSSEC, key, tag 38559, algorithm ECDSAP256SHA256, public, active 2024-02-14T15:24:06+0100 info: [example.com.] DNSSEC, key, tag 59825, algorithm ECDSAP256SHA256, public 2024-02-14T15:24:06+0100 info: [example.com.] DNSSEC, signing started - 2024-02-14T15:24:06+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111211 + 2024-02-14T15:24:06+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111211, new RRSIGs 2 2024-02-14T15:24:06+0100 info: [example.com.] DNSSEC, next signing at 2024-02-14T15:24:18+0100 ... @@ -736,7 +736,7 @@ Further rollovers:: 2024-02-14T15:25:00+0100 info: [example.com.] DNSSEC, key, tag 59825, algorithm ECDSAP256SHA256, public, active 2024-02-14T15:25:00+0100 info: [example.com.] DNSSEC, key, tag 50822, algorithm ECDSAP256SHA256, KSK, public, active+ 2024-02-14T15:25:00+0100 info: [example.com.] DNSSEC, signing started - 2024-02-14T15:25:00+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111214 + 2024-02-14T15:25:00+0100 info: [example.com.] DNSSEC, successfully signed, serial 2010111214, new RRSIGs 3 2024-02-14T15:25:00+0100 info: [example.com.] DNSSEC, next signing at 2024-02-14T15:25:12+0100 ... @@ -1282,12 +1282,12 @@ if the backup was created for only a subset of zones. turns off some verification checks, it shouldn't be used in other cases. .. NOTE:: - For QUIC, only the auto-generated key is restored. The ``zone-restore`` - command doesn't restore a user-defined QUIC key and certificate so as to + For QUIC/TLS, only the auto-generated key is restored. The ``zone-restore`` + command doesn't restore a user-defined QUIC/TLS key and certificate so as to avoid possible configuration management conflicts and they must be restored from the backup (its subdirectory ``quic``) manually. In all cases, restart of the Knot server after the restore is necessary for the restored - QUIC key/certificate to take effect. + QUIC/TLS key/certificate to take effect. Limitations ----------- @@ -1375,9 +1375,15 @@ Pre-requisites * A multiqueue network card, which offers enough Combined RX/TX channels, with native XDP support is highly recommended. Successfully tested cards: + * NVIDIA (Mellanox) ConnectX-6 Dx (driver `mlx5_core`), maximum number of channels + per interface is 63. Official drivers are recommended. * Intel series 700 (driver `i40e`), maximum number of channels per interface is 64. - * Intel series 500 (driver `ixgbe`), maximum number of channels per interface is 64. - The number of CPUs available has to be at most 64! + Linux kernel drivers are recommended. + + Cards with known instability issues: + + * Intel series E810 (driver `ice`). + * Intel series 500 (driver `ixgbe`). * If the `knotd` service is not directly executed in the privileged mode, some additional Linux capabilities have to be set: diff --git a/doc/reference.rst b/doc/reference.rst index 6cb42f3..1aefc57 100644 --- a/doc/reference.rst +++ b/doc/reference.rst @@ -20,9 +20,10 @@ the following symbols: - ``STR`` – Textual string - ``HEXSTR`` – Hexadecimal string (with ``0x`` prefix) - ``BOOL`` – Boolean value (``on``/``off`` or ``true``/``false``) -- ``TIME`` – Number of seconds, an integer with possible time multiplier suffix - (``s`` ~ 1, ``m`` ~ 60, ``h`` ~ 3600 or ``d`` ~ 24 * 3600) -- ``SIZE`` – Number of bytes, an integer with possible size multiplier suffix +- ``TIME`` – Number of seconds, an integer with a possible time multiplier suffix + (``s`` ~ 1, ``m`` ~ 60, ``h`` ~ 3600, ``d`` ~ 24 * 3600, ``w`` ~ 7 * 24 * 3600, + ``M`` ~ 30 * 24 * 3600, ``y`` ~ 365 * 24 * 3600) +- ``SIZE`` – Number of bytes, an integer with a possible size multiplier suffix (``B`` ~ 1, ``K`` ~ 1024, ``M`` ~ 1024^2 or ``G`` ~ 1024^3) - ``BASE64`` – Base64 encoded string - ``ADDR`` – IPv4 or IPv6 address @@ -217,6 +218,7 @@ General options related to the server. dbus-init-delay: TIME listen: ADDR[@INT] | STR ... listen-quic: ADDR[@INT] ... + listen-tls: ADDR[@INT] ... .. CAUTION:: When you change configuration parameters dynamically or via configuration file @@ -561,12 +563,10 @@ Maximum EDNS0 UDP payload size for IPv6. key-file -------- -Path to a server key PEM file which is used for DNS over QUIC communication. +Path to a server key PEM file which is used for DNS over QUIC/TLS communication. A non-absolute path of a user specified key file is relative to the :file:`@config_dir@` directory. -Change of this parameter requires restart of the Knot server to take effect. - *Default:* auto-generated key .. _server_cert-file: @@ -574,11 +574,9 @@ Change of this parameter requires restart of the Knot server to take effect. cert-file --------- -Path to a server certificate PEM file which is used for DNS over QUIC communication. +Path to a server certificate PEM file which is used for DNS over QUIC/TLS communication. A non-absolute path is relative to the :file:`@config_dir@` directory. -Change of this parameter requires restart of the Knot server to take effect. - *Default:* one-time in-memory certificate .. _server_edns-client-subnet: @@ -646,16 +644,17 @@ Possible values: - ``stopped`` when the server shutdown sequence is initiated. - ``zone-updated`` – The signal ``zone_updated`` is emitted when a zone has been updated; the signal parameters are `zone name` and `zone SOA serial`. -- ``keys-updated`` - The signal ``keys_updated`` is emitted when a DNSSEC key set - of this zone is updated. +- ``keys-updated`` - The signal ``keys_updated`` is emitted when a DNSSEC key set + is updated; the signal parameter is `zone name`. - ``ksk-submission`` – The signal ``zone_ksk_submission`` is emitted if there is a ready KSK present when the zone is signed; the signal parameters are `zone name`, `KSK keytag`, and `KSK KASP id`. - ``dnssec-invalid`` – The signal ``zone_dnssec_invalid`` is emitted when DNSSEC - validation fails; the signal parameter is `zone name`. + validation fails; the signal parameters are `zone name`, and `remaining seconds` + until an RRSIG expires. .. NOTE:: - This function requires systemd version at least 221. + This function requires systemd version at least 221 or libdbus. Change of this parameter requires restart of the Knot server to take effect. @@ -704,9 +703,17 @@ Change of this parameter requires restart of the Knot server to take effect. *Default:* not set -.. NOTE:: - Incoming :ref:`DDNS` over QUIC isn't supported. - The server always responds with SERVFAIL. +.. _server_listen-tls: + +listen-tls +---------- + +One or more IP addresses (and optionally ports) where the server listens +for incoming queries over TLS protocol (DoT). + +Change of this parameter requires restart of the Knot server to take effect. + +*Default:* not set .. _xdp section: @@ -730,6 +737,9 @@ Various options related to XDP listening, especially TCP. tcp-idle-reset-timeout: TIME tcp-resend-timeout: TIME route-check: BOOL + ring-size: INT + busypoll-budget: INT + busypoll-timeout: INT .. CAUTION:: When you change configuration parameters dynamically or via configuration file @@ -912,6 +922,57 @@ Change of this parameter requires restart of the Knot server to take effect. *Default:* ``off`` +.. _xdp_ring-size: + +ring-size +--------- + +Size of RX, FQ, TX, and CQ rings. + +Change of this parameter requires restart of the Knot server to take effect. + +.. NOTE:: + This value should be at least as high as the configured RX size of the + network device in the XDP mode. + +*Default:* ``2048`` + +.. _xdp_busypoll-budget: + +busypoll-budget +--------------- + +If set to a positive value, preferred busy polling is enabled with the +specified budget. + +Change of this parameter requires restart of the Knot server to take effect. + +.. NOTE:: + + Preferred busy polling also requires setting ``napi_defer_hard_irqs`` and + ``gro_flush_timeout`` for the appropriate network interface. E.g.:: + + echo 2 | sudo tee /sys/class/net//napi_defer_hard_irqs + echo 200000 | sudo tee /sys/class/net//gro_flush_timeout + +.. NOTE:: + + A recommended value is between 8 and 64. + +*Default:* ``0`` (disabled) + +.. _xdp_busypoll-timeout: + +busypoll-timeout +---------------- + +Timeout in microseconds of preferrred busy polling if enabled by +:ref:`xdp_busypoll-budget`. + +Change of this parameter requires restart of the Knot server to take effect. + +*Default:* ``20`` (20 microseconds) + .. _control section: ``control`` section @@ -1378,6 +1439,7 @@ transfer, target for a notification, etc.). address: ADDR[@INT] | STR ... via: ADDR[@INT] ... quic: BOOL + tls: BOOL key: key_id cert-key: BASE64 ... block-notify-after-transfer: BOOL @@ -1459,6 +1521,16 @@ with this remote. *Default:* ``off`` +.. _remote_tls: + +tls +--- + +If this option is set, the TLS (DoT) protocol will be used for outgoing communication +with this remote. + +*Default:* ``off`` + .. _remote_key: key @@ -1955,8 +2027,6 @@ Possible values: - ``ed448`` .. NOTE:: - Ed25519 algorithm is only available if compiled with GnuTLS 3.6.0+. - Ed448 algorithm is only available if compiled with GnuTLS 3.6.12+ and Nettle 3.6+. *Default:* ``ecdsap256sha256`` @@ -2134,6 +2204,10 @@ resolvers' caches. *Default:* 0.1 * :ref:`policy_rrsig-lifetime` + :ref:`policy_propagation-delay` + :ref:`policy_zone-max-ttl` +If :ref:`zone_dnssec-validation` is enabled: + +*Default:* ``1d`` (1 day) + .. _policy_rrsig-pre-refresh: rrsig-pre-refresh @@ -2847,7 +2921,9 @@ List of DNSSEC checks: The validation is not affected by :ref:`zone_dnssec-policy` configuration, except for :ref:`policy_signing-threads` option, which specifies the number -of threads for parallel validation. +of threads for parallel validation, and :ref:`policy_rrsig-refresh`, which +defines minimal allowed remaining RRSIG validity (otherwise a warning is +logged). .. NOTE:: diff --git a/doc/requirements.rst b/doc/requirements.rst index 584afa2..6b25fc1 100644 --- a/doc/requirements.rst +++ b/doc/requirements.rst @@ -60,9 +60,9 @@ Required libraries Knot DNS requires a few libraries to be available: +* gnutls >= 3.6.10 * libedit -* gnutls >= 3.3 -* liburcu >= 0.5.4 +* liburcu * lmdb >= 0.9.15 .. NOTE:: @@ -72,9 +72,9 @@ Knot DNS requires a few libraries to be available: Optional libraries ================== -International Domain Names support (IDNA2008 or IDNA2003) in :doc:`kdig`: +International Domain Names support (IDNA2008) in :doc:`kdig`: -* libidn2 (or libidn) +* libidn2 Systemd's startup notification mechanism and journald logging: diff --git a/python/Makefile.in b/python/Makefile.in index 817d7f7..4e254e1 100644 --- a/python/Makefile.in +++ b/python/Makefile.in @@ -317,6 +317,8 @@ infodir = @infodir@ install_sh = @install_sh@ libbpf_CFLAGS = @libbpf_CFLAGS@ libbpf_LIBS = @libbpf_LIBS@ +libdbus_CFLAGS = @libdbus_CFLAGS@ +libdbus_LIBS = @libdbus_LIBS@ libdir = @libdir@ libdnssec_SONAME = @libdnssec_SONAME@ libdnssec_SOVERSION = @libdnssec_SOVERSION@ @@ -328,8 +330,6 @@ libfstrm_CFLAGS = @libfstrm_CFLAGS@ libfstrm_LIBS = @libfstrm_LIBS@ libidn2_CFLAGS = @libidn2_CFLAGS@ libidn2_LIBS = @libidn2_LIBS@ -libidn_CFLAGS = @libidn_CFLAGS@ -libidn_LIBS = @libidn_LIBS@ libknot_SONAME = @libknot_SONAME@ libknot_SOVERSION = @libknot_SOVERSION@ libknot_VERSION_INFO = @libknot_VERSION_INFO@ @@ -347,7 +347,6 @@ libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@ libprotobuf_c_LIBS = @libprotobuf_c_LIBS@ liburcu_CFLAGS = @liburcu_CFLAGS@ liburcu_LIBS = @liburcu_LIBS@ -liburcu_PKGCONFIG = @liburcu_PKGCONFIG@ libxdp_CFLAGS = @libxdp_CFLAGS@ libxdp_LIBS = @libxdp_LIBS@ libzscanner_SONAME = @libzscanner_SONAME@ diff --git a/python/knot_exporter/Makefile.in b/python/knot_exporter/Makefile.in index dae875e..3f2824d 100644 --- a/python/knot_exporter/Makefile.in +++ b/python/knot_exporter/Makefile.in @@ -260,6 +260,8 @@ infodir = @infodir@ install_sh = @install_sh@ libbpf_CFLAGS = @libbpf_CFLAGS@ libbpf_LIBS = @libbpf_LIBS@ +libdbus_CFLAGS = @libdbus_CFLAGS@ +libdbus_LIBS = @libdbus_LIBS@ libdir = @libdir@ libdnssec_SONAME = @libdnssec_SONAME@ libdnssec_SOVERSION = @libdnssec_SOVERSION@ @@ -271,8 +273,6 @@ libfstrm_CFLAGS = @libfstrm_CFLAGS@ libfstrm_LIBS = @libfstrm_LIBS@ libidn2_CFLAGS = @libidn2_CFLAGS@ libidn2_LIBS = @libidn2_LIBS@ -libidn_CFLAGS = @libidn_CFLAGS@ -libidn_LIBS = @libidn_LIBS@ libknot_SONAME = @libknot_SONAME@ libknot_SOVERSION = @libknot_SOVERSION@ libknot_VERSION_INFO = @libknot_VERSION_INFO@ @@ -290,7 +290,6 @@ libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@ libprotobuf_c_LIBS = @libprotobuf_c_LIBS@ liburcu_CFLAGS = @liburcu_CFLAGS@ liburcu_LIBS = @liburcu_LIBS@ -liburcu_PKGCONFIG = @liburcu_PKGCONFIG@ libxdp_CFLAGS = @libxdp_CFLAGS@ libxdp_LIBS = @libxdp_LIBS@ libzscanner_SONAME = @libzscanner_SONAME@ diff --git a/python/libknot/Makefile.in b/python/libknot/Makefile.in index 06b1083..c93de6e 100644 --- a/python/libknot/Makefile.in +++ b/python/libknot/Makefile.in @@ -260,6 +260,8 @@ infodir = @infodir@ install_sh = @install_sh@ libbpf_CFLAGS = @libbpf_CFLAGS@ libbpf_LIBS = @libbpf_LIBS@ +libdbus_CFLAGS = @libdbus_CFLAGS@ +libdbus_LIBS = @libdbus_LIBS@ libdir = @libdir@ libdnssec_SONAME = @libdnssec_SONAME@ libdnssec_SOVERSION = @libdnssec_SOVERSION@ @@ -271,8 +273,6 @@ libfstrm_CFLAGS = @libfstrm_CFLAGS@ libfstrm_LIBS = @libfstrm_LIBS@ libidn2_CFLAGS = @libidn2_CFLAGS@ libidn2_LIBS = @libidn2_LIBS@ -libidn_CFLAGS = @libidn_CFLAGS@ -libidn_LIBS = @libidn_LIBS@ libknot_SONAME = @libknot_SONAME@ libknot_SOVERSION = @libknot_SOVERSION@ libknot_VERSION_INFO = @libknot_VERSION_INFO@ @@ -290,7 +290,6 @@ libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@ libprotobuf_c_LIBS = @libprotobuf_c_LIBS@ liburcu_CFLAGS = @liburcu_CFLAGS@ liburcu_LIBS = @liburcu_LIBS@ -liburcu_PKGCONFIG = @liburcu_PKGCONFIG@ libxdp_CFLAGS = @libxdp_CFLAGS@ libxdp_LIBS = @libxdp_LIBS@ libzscanner_SONAME = @libzscanner_SONAME@ diff --git a/python/libknot/libknot/probe.py b/python/libknot/libknot/probe.py index e6f09db..37b2cdf 100644 --- a/python/libknot/libknot/probe.py +++ b/python/libknot/libknot/probe.py @@ -12,9 +12,9 @@ class KnotProbeDataProto(enum.IntEnum): UDP = 0 TCP = 1 - QUIC = 3 - TLS = 4 - HTTPS = 5 + QUIC = 2 + TLS = 3 + HTTPS = 4 class KnotProbeDataDNSHdr(ctypes.BigEndianStructure): @@ -132,8 +132,10 @@ class KnotProbeData(ctypes.Structure): string += COL("UDP", GRN) elif self.proto == KnotProbeDataProto.TCP: string += COL("TCP", RED) - else: + elif self.proto == KnotProbeDataProto.QUIC: string += COL("QUIC", ORG) + else: + string += COL("TLS", YELW) if self.tcp_rtt > 0: string += ", RTT %.2f ms" % (self.tcp_rtt / 1000) string += "\n ID %u, " % self.query_hdr.id diff --git a/samples/Makefile.in b/samples/Makefile.in index cd4bf4b..bb71eec 100644 --- a/samples/Makefile.in +++ b/samples/Makefile.in @@ -259,6 +259,8 @@ infodir = @infodir@ install_sh = @install_sh@ libbpf_CFLAGS = @libbpf_CFLAGS@ libbpf_LIBS = @libbpf_LIBS@ +libdbus_CFLAGS = @libdbus_CFLAGS@ +libdbus_LIBS = @libdbus_LIBS@ libdir = @libdir@ libdnssec_SONAME = @libdnssec_SONAME@ libdnssec_SOVERSION = @libdnssec_SOVERSION@ @@ -270,8 +272,6 @@ libfstrm_CFLAGS = @libfstrm_CFLAGS@ libfstrm_LIBS = @libfstrm_LIBS@ libidn2_CFLAGS = @libidn2_CFLAGS@ libidn2_LIBS = @libidn2_LIBS@ -libidn_CFLAGS = @libidn_CFLAGS@ -libidn_LIBS = @libidn_LIBS@ libknot_SONAME = @libknot_SONAME@ libknot_SOVERSION = @libknot_SOVERSION@ libknot_VERSION_INFO = @libknot_VERSION_INFO@ @@ -289,7 +289,6 @@ libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@ libprotobuf_c_LIBS = @libprotobuf_c_LIBS@ liburcu_CFLAGS = @liburcu_CFLAGS@ liburcu_LIBS = @liburcu_LIBS@ -liburcu_PKGCONFIG = @liburcu_PKGCONFIG@ libxdp_CFLAGS = @libxdp_CFLAGS@ libxdp_LIBS = @libxdp_LIBS@ libzscanner_SONAME = @libzscanner_SONAME@ diff --git a/src/Makefile.in b/src/Makefile.in index 09daaa2..8630517 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -160,28 +160,29 @@ host_triplet = @host@ @STATIC_MODULE_queryacl_TRUE@am__append_41 = $(knot_modules_queryacl_la_SOURCES) @SHARED_MODULE_queryacl_TRUE@am__append_42 = knot/modules/queryacl.la @STATIC_MODULE_rrl_TRUE@am__append_43 = $(knot_modules_rrl_la_SOURCES) -@SHARED_MODULE_rrl_TRUE@am__append_44 = knot/modules/rrl.la -@STATIC_MODULE_stats_TRUE@am__append_45 = $(knot_modules_stats_la_SOURCES) -@SHARED_MODULE_stats_TRUE@am__append_46 = knot/modules/stats.la -@STATIC_MODULE_synthrecord_TRUE@am__append_47 = $(knot_modules_synthrecord_la_SOURCES) -@SHARED_MODULE_synthrecord_TRUE@am__append_48 = knot/modules/synthrecord.la -@STATIC_MODULE_whoami_TRUE@am__append_49 = $(knot_modules_whoami_la_SOURCES) -@SHARED_MODULE_whoami_TRUE@am__append_50 = knot/modules/whoami.la +@STATIC_MODULE_rrl_TRUE@am__append_44 = $(math_LIBS) +@SHARED_MODULE_rrl_TRUE@am__append_45 = knot/modules/rrl.la +@STATIC_MODULE_stats_TRUE@am__append_46 = $(knot_modules_stats_la_SOURCES) +@SHARED_MODULE_stats_TRUE@am__append_47 = knot/modules/stats.la +@STATIC_MODULE_synthrecord_TRUE@am__append_48 = $(knot_modules_synthrecord_la_SOURCES) +@SHARED_MODULE_synthrecord_TRUE@am__append_49 = knot/modules/synthrecord.la +@STATIC_MODULE_whoami_TRUE@am__append_50 = $(knot_modules_whoami_la_SOURCES) +@SHARED_MODULE_whoami_TRUE@am__append_51 = knot/modules/whoami.la bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) sbin_PROGRAMS = $(am__EXEEXT_3) $(am__EXEEXT_4) $(am__EXEEXT_5) -@HAVE_LIBUTILS_TRUE@am__append_51 = libknotus.la -@EMBEDDED_LIBNGTCP2_TRUE@@HAVE_LIBUTILS_TRUE@am__append_52 = $(libembngtcp2_LIBS) -@HAVE_UTILS_TRUE@am__append_53 = kdig khost knsec3hash knsupdate -@HAVE_DNSTAP_TRUE@@HAVE_UTILS_TRUE@am__append_54 = $(DNSTAP_CFLAGS) -@HAVE_DNSTAP_TRUE@@HAVE_UTILS_TRUE@am__append_55 = $(libdnstap_LIBS) -@HAVE_DNSTAP_TRUE@@HAVE_UTILS_TRUE@am__append_56 = $(DNSTAP_CFLAGS) -@HAVE_DNSTAP_TRUE@@HAVE_UTILS_TRUE@am__append_57 = $(libdnstap_LIBS) -@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@am__append_58 = kxdpgun -@ENABLE_QUIC_TRUE@@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@am__append_59 = $(gnutls_CFLAGS) -@ENABLE_QUIC_TRUE@@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@am__append_60 = $(gnutls_LIBS) -@HAVE_DAEMON_TRUE@am__append_61 = knotc knotd -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@am__append_62 = kzonecheck kzonesign -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@am__append_63 = keymgr kjournalprint kcatalogprint +@HAVE_LIBUTILS_TRUE@am__append_52 = libknotus.la +@EMBEDDED_LIBNGTCP2_TRUE@@HAVE_LIBUTILS_TRUE@am__append_53 = $(libembngtcp2_LIBS) +@HAVE_UTILS_TRUE@am__append_54 = kdig khost knsec3hash knsupdate +@HAVE_DNSTAP_TRUE@@HAVE_UTILS_TRUE@am__append_55 = $(DNSTAP_CFLAGS) +@HAVE_DNSTAP_TRUE@@HAVE_UTILS_TRUE@am__append_56 = $(libdnstap_LIBS) +@HAVE_DNSTAP_TRUE@@HAVE_UTILS_TRUE@am__append_57 = $(DNSTAP_CFLAGS) +@HAVE_DNSTAP_TRUE@@HAVE_UTILS_TRUE@am__append_58 = $(libdnstap_LIBS) +@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@am__append_59 = kxdpgun +@ENABLE_QUIC_TRUE@@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@am__append_60 = $(gnutls_CFLAGS) +@ENABLE_QUIC_TRUE@@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@am__append_61 = $(gnutls_LIBS) +@HAVE_DAEMON_TRUE@am__append_62 = knotc knotd +@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@am__append_63 = kzonecheck kzonesign +@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@am__append_64 = keymgr kjournalprint kcatalogprint subdir = src SUBDIRS = ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -198,7 +199,8 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(include_libdnssec_HEADERS) \ $(include_libknotd_HEADERS) $(include_libzscanner_HEADERS) \ - $(am__nobase_include_libknot_HEADERS_DIST) $(am__DIST_COMMON) + $(am__nobase_include_libknot_HEADERS_DIST) $(noinst_HEADERS) \ + $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = knotd.pc libknot.pc libdnssec.pc libzscanner.pc @@ -359,9 +361,12 @@ knot_modules_queryacl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ @SHARED_MODULE_queryacl_TRUE@am_knot_modules_queryacl_la_rpath = \ @SHARED_MODULE_queryacl_TRUE@ -rpath $(pkglibdir) @SHARED_MODULE_rrl_TRUE@knot_modules_rrl_la_DEPENDENCIES = \ -@SHARED_MODULE_rrl_TRUE@ $(am__DEPENDENCIES_3) +@SHARED_MODULE_rrl_TRUE@ $(am__DEPENDENCIES_3) \ +@SHARED_MODULE_rrl_TRUE@ $(am__DEPENDENCIES_1) am_knot_modules_rrl_la_OBJECTS = knot/modules/rrl/la-rrl.lo \ - knot/modules/rrl/la-functions.lo + knot/modules/rrl/la-functions.lo \ + knot/modules/rrl/la-kru-generic.lo \ + knot/modules/rrl/la-kru-avx2.lo knot_modules_rrl_la_OBJECTS = $(am_knot_modules_rrl_la_OBJECTS) knot_modules_rrl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ @@ -627,17 +632,19 @@ am__libknot_la_SOURCES_DIST = libknot/codes.c \ libknot/descriptor.c libknot/dname.c libknot/error.c \ libknot/db/db_lmdb.c libknot/db/db_trie.c libknot/packet/pkt.c \ libknot/packet/rrset-wire.c libknot/probe/data.c \ - libknot/probe/probe.c libknot/rdataset.c libknot/rrset-dump.c \ - libknot/rrset.c libknot/rrtype/naptr.c libknot/rrtype/opt.c \ - libknot/rrtype/tsig.c libknot/tsig-op.c libknot/tsig.c \ - libknot/yparser/yparser.c libknot/yparser/ypbody.c \ - libknot/yparser/ypformat.c libknot/yparser/ypschema.c \ - libknot/yparser/yptrafo.c libknot/xdp/tcp_iobuf.c \ - libknot/xdp/bpf-kernel-obj.c libknot/xdp/bpf-kernel-obj.h \ - libknot/xdp/bpf-user.c libknot/xdp/bpf-user.h \ - libknot/xdp/eth.c libknot/xdp/msg_init.h \ - libknot/xdp/protocols.h libknot/xdp/tcp.c libknot/xdp/xdp.c \ - libknot/quic/quic.c libknot/quic/quic_conn.c + libknot/probe/probe.c libknot/quic/tls.c \ + libknot/quic/tls_common.c libknot/rdataset.c \ + libknot/rrset-dump.c libknot/rrset.c libknot/rrtype/naptr.c \ + libknot/rrtype/opt.c libknot/rrtype/tsig.c libknot/tsig-op.c \ + libknot/tsig.c libknot/yparser/yparser.c \ + libknot/yparser/ypbody.c libknot/yparser/ypformat.c \ + libknot/yparser/ypschema.c libknot/yparser/yptrafo.c \ + libknot/xdp/tcp_iobuf.c libknot/xdp/bpf-kernel-obj.c \ + libknot/xdp/bpf-kernel-obj.h libknot/xdp/bpf-user.c \ + libknot/xdp/bpf-user.h libknot/xdp/eth.c \ + libknot/xdp/msg_init.h libknot/xdp/protocols.h \ + libknot/xdp/tcp.c libknot/xdp/xdp.c libknot/quic/quic.c \ + libknot/quic/quic_conn.c @ENABLE_XDP_TRUE@am__objects_1 = libknot/xdp/la-bpf-kernel-obj.lo \ @ENABLE_XDP_TRUE@ libknot/xdp/la-bpf-user.lo \ @ENABLE_XDP_TRUE@ libknot/xdp/la-eth.lo libknot/xdp/la-tcp.lo \ @@ -650,7 +657,8 @@ am_libknot_la_OBJECTS = libknot/la-codes.lo \ libknot/la-error.lo libknot/db/la-db_lmdb.lo \ libknot/db/la-db_trie.lo libknot/packet/la-pkt.lo \ libknot/packet/la-rrset-wire.lo libknot/probe/la-data.lo \ - libknot/probe/la-probe.lo libknot/la-rdataset.lo \ + libknot/probe/la-probe.lo libknot/quic/la-tls.lo \ + libknot/quic/la-tls_common.lo libknot/la-rdataset.lo \ libknot/la-rrset-dump.lo libknot/la-rrset.lo \ libknot/rrtype/la-naptr.lo libknot/rrtype/la-opt.lo \ libknot/rrtype/la-tsig.lo libknot/la-tsig-op.lo \ @@ -665,10 +673,11 @@ libknot_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ @STATIC_MODULE_dnstap_TRUE@am__DEPENDENCIES_10 = \ @STATIC_MODULE_dnstap_TRUE@ $(am__DEPENDENCIES_4) @STATIC_MODULE_geoip_TRUE@am__DEPENDENCIES_11 = $(am__DEPENDENCIES_1) +@STATIC_MODULE_rrl_TRUE@am__DEPENDENCIES_12 = $(am__DEPENDENCIES_1) libknotd_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_7) $(am__DEPENDENCIES_10) \ - $(am__DEPENDENCIES_11) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_7) \ + $(am__DEPENDENCIES_10) $(am__DEPENDENCIES_11) \ + $(am__DEPENDENCIES_12) am__libknotd_la_SOURCES_DIST = knot/catalog/catalog_db.c \ knot/catalog/catalog_db.h knot/catalog/catalog_update.c \ knot/catalog/catalog_update.h knot/catalog/generate.c \ @@ -705,15 +714,15 @@ am__libknotd_la_SOURCES_DIST = knot/catalog/catalog_db.c \ knot/events/handlers/flush.c \ knot/events/handlers/freeze_thaw.c knot/events/handlers/load.c \ knot/events/handlers/notify.c knot/events/handlers/refresh.c \ - knot/events/handlers/update.c knot/events/replan.c \ - knot/events/replan.h knot/nameserver/axfr.c \ - knot/nameserver/axfr.h knot/nameserver/chaos.c \ - knot/nameserver/chaos.h knot/nameserver/internet.c \ - knot/nameserver/internet.h knot/nameserver/ixfr.c \ - knot/nameserver/ixfr.h knot/nameserver/log.h \ - knot/nameserver/notify.c knot/nameserver/notify.h \ - knot/nameserver/nsec_proofs.c knot/nameserver/nsec_proofs.h \ - knot/nameserver/process_query.c \ + knot/events/handlers/update.c knot/events/handlers/validate.c \ + knot/events/replan.c knot/events/replan.h \ + knot/nameserver/axfr.c knot/nameserver/axfr.h \ + knot/nameserver/chaos.c knot/nameserver/chaos.h \ + knot/nameserver/internet.c knot/nameserver/internet.h \ + knot/nameserver/ixfr.c knot/nameserver/ixfr.h \ + knot/nameserver/log.h knot/nameserver/notify.c \ + knot/nameserver/notify.h knot/nameserver/nsec_proofs.c \ + knot/nameserver/nsec_proofs.h knot/nameserver/process_query.c \ knot/nameserver/process_query.h knot/nameserver/query_module.c \ knot/nameserver/query_module.h knot/nameserver/tsig_ctx.c \ knot/nameserver/tsig_ctx.h knot/nameserver/update.c \ @@ -721,14 +730,15 @@ am__libknotd_la_SOURCES_DIST = knot/catalog/catalog_db.c \ knot/nameserver/xfr.h knot/query/capture.c \ knot/query/capture.h knot/query/layer.h knot/query/query.c \ knot/query/query.h knot/query/requestor.c \ - knot/query/requestor.h knot/common/evsched.c \ - knot/common/evsched.h knot/common/fdset.c knot/common/fdset.h \ - knot/common/log.c knot/common/log.h knot/common/process.c \ - knot/common/process.h knot/common/stats.c knot/common/stats.h \ - knot/common/systemd.c knot/common/systemd.h \ - knot/common/unreachable.c knot/common/unreachable.h \ - knot/journal/journal_basic.c knot/journal/journal_basic.h \ - knot/journal/journal_metadata.c \ + knot/query/requestor.h knot/query/tls-requestor.c \ + knot/query/tls-requestor.h knot/common/dbus.c \ + knot/common/dbus.h knot/common/evsched.c knot/common/evsched.h \ + knot/common/fdset.c knot/common/fdset.h knot/common/log.c \ + knot/common/log.h knot/common/process.c knot/common/process.h \ + knot/common/stats.c knot/common/stats.h knot/common/systemd.c \ + knot/common/systemd.h knot/common/unreachable.c \ + knot/common/unreachable.h knot/journal/journal_basic.c \ + knot/journal/journal_basic.h knot/journal/journal_metadata.c \ knot/journal/journal_metadata.h knot/journal/journal_read.c \ knot/journal/journal_read.h knot/journal/journal_write.c \ knot/journal/journal_write.h knot/journal/knot_lmdb.c \ @@ -774,7 +784,8 @@ am__libknotd_la_SOURCES_DIST = knot/catalog/catalog_db.c \ knot/modules/onlinesign/nsec_next.h knot/modules/probe/probe.c \ knot/modules/queryacl/queryacl.c knot/modules/rrl/rrl.c \ knot/modules/rrl/functions.c knot/modules/rrl/functions.h \ - knot/modules/stats/stats.c \ + knot/modules/rrl/kru-generic.c knot/modules/rrl/kru-avx2.c \ + knot/modules/rrl/kru.h knot/modules/stats/stats.c \ knot/modules/synthrecord/synthrecord.c \ knot/modules/whoami/whoami.c @ENABLE_QUIC_TRUE@am__objects_3 = \ @@ -801,7 +812,9 @@ am__objects_18 = knot/modules/probe/libknotd_la-probe.lo am__objects_20 = knot/modules/queryacl/libknotd_la-queryacl.lo @STATIC_MODULE_queryacl_TRUE@am__objects_21 = $(am__objects_20) am__objects_22 = knot/modules/rrl/libknotd_la-rrl.lo \ - knot/modules/rrl/libknotd_la-functions.lo + knot/modules/rrl/libknotd_la-functions.lo \ + knot/modules/rrl/libknotd_la-kru-generic.lo \ + knot/modules/rrl/libknotd_la-kru-avx2.lo @STATIC_MODULE_rrl_TRUE@am__objects_23 = $(am__objects_22) am__objects_24 = knot/modules/stats/libknotd_la-stats.lo @STATIC_MODULE_stats_TRUE@am__objects_25 = $(am__objects_24) @@ -850,6 +863,7 @@ am_libknotd_la_OBJECTS = knot/catalog/libknotd_la-catalog_db.lo \ knot/events/handlers/libknotd_la-notify.lo \ knot/events/handlers/libknotd_la-refresh.lo \ knot/events/handlers/libknotd_la-update.lo \ + knot/events/handlers/libknotd_la-validate.lo \ knot/events/libknotd_la-replan.lo \ knot/nameserver/libknotd_la-axfr.lo \ knot/nameserver/libknotd_la-chaos.lo \ @@ -865,6 +879,8 @@ am_libknotd_la_OBJECTS = knot/catalog/libknotd_la-catalog_db.lo \ knot/query/libknotd_la-capture.lo \ knot/query/libknotd_la-query.lo \ knot/query/libknotd_la-requestor.lo \ + knot/query/libknotd_la-tls-requestor.lo \ + knot/common/libknotd_la-dbus.lo \ knot/common/libknotd_la-evsched.lo \ knot/common/libknotd_la-fdset.lo \ knot/common/libknotd_la-log.lo \ @@ -921,12 +937,11 @@ libknotd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libknotd_la_LDFLAGS) $(LDFLAGS) -o $@ @HAVE_DAEMON_TRUE@am_libknotd_la_rpath = -@EMBEDDED_LIBNGTCP2_TRUE@@HAVE_LIBUTILS_TRUE@am__DEPENDENCIES_12 = $(am__DEPENDENCIES_6) +@EMBEDDED_LIBNGTCP2_TRUE@@HAVE_LIBUTILS_TRUE@am__DEPENDENCIES_13 = $(am__DEPENDENCIES_6) @HAVE_LIBUTILS_TRUE@libknotus_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ @HAVE_LIBUTILS_TRUE@ $(am__DEPENDENCIES_1) \ @HAVE_LIBUTILS_TRUE@ $(am__DEPENDENCIES_1) \ -@HAVE_LIBUTILS_TRUE@ $(am__DEPENDENCIES_1) \ -@HAVE_LIBUTILS_TRUE@ $(am__DEPENDENCIES_12) +@HAVE_LIBUTILS_TRUE@ $(am__DEPENDENCIES_13) am__libknotus_la_SOURCES_DIST = utils/common/exec.c \ utils/common/exec.h utils/common/hex.c utils/common/hex.h \ utils/common/https.c utils/common/https.h \ @@ -972,17 +987,17 @@ libzscanner_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ am__kcatalogprint_SOURCES_DIST = utils/kcatalogprint/main.c @HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@am_kcatalogprint_OBJECTS = utils/kcatalogprint/kcatalogprint-main.$(OBJEXT) kcatalogprint_OBJECTS = $(am_kcatalogprint_OBJECTS) -am__DEPENDENCIES_13 = libknotd.la libknot.la libdnssec.la \ +am__DEPENDENCIES_14 = libknotd.la libknot.la libdnssec.la \ libzscanner.la $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) -@HAVE_LIBUTILS_TRUE@am__DEPENDENCIES_14 = libknotus.la libknot.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +@HAVE_LIBUTILS_TRUE@am__DEPENDENCIES_15 = libknotus.la libknot.la \ @HAVE_LIBUTILS_TRUE@ libdnssec.la $(am__DEPENDENCIES_3) \ @HAVE_LIBUTILS_TRUE@ $(am__DEPENDENCIES_1) \ @HAVE_LIBUTILS_TRUE@ $(am__DEPENDENCIES_1) @HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@kcatalogprint_DEPENDENCIES = \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_13) \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_14) +@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_14) \ +@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_15) kcatalogprint_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(kcatalogprint_LDFLAGS) $(LDFLAGS) -o $@ @@ -994,10 +1009,10 @@ am__kdig_SOURCES_DIST = utils/kdig/kdig_exec.c utils/kdig/kdig_exec.h \ @HAVE_UTILS_TRUE@ utils/kdig/kdig-kdig_main.$(OBJEXT) \ @HAVE_UTILS_TRUE@ utils/kdig/kdig-kdig_params.$(OBJEXT) kdig_OBJECTS = $(am_kdig_OBJECTS) -@HAVE_DNSTAP_TRUE@@HAVE_UTILS_TRUE@am__DEPENDENCIES_15 = \ +@HAVE_DNSTAP_TRUE@@HAVE_UTILS_TRUE@am__DEPENDENCIES_16 = \ @HAVE_DNSTAP_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_4) -@HAVE_UTILS_TRUE@kdig_DEPENDENCIES = $(am__DEPENDENCIES_14) \ -@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_15) +@HAVE_UTILS_TRUE@kdig_DEPENDENCIES = $(am__DEPENDENCIES_15) \ +@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_16) am__keymgr_SOURCES_DIST = utils/keymgr/bind_privkey.c \ utils/keymgr/bind_privkey.h utils/keymgr/functions.c \ utils/keymgr/functions.h utils/keymgr/keystore.c \ @@ -1010,8 +1025,8 @@ am__keymgr_SOURCES_DIST = utils/keymgr/bind_privkey.c \ @HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ utils/keymgr/keymgr-main.$(OBJEXT) keymgr_OBJECTS = $(am_keymgr_OBJECTS) @HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@keymgr_DEPENDENCIES = \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_13) \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_14) +@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_14) \ +@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_15) keymgr_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(keymgr_LDFLAGS) $(LDFLAGS) -o $@ @@ -1025,14 +1040,14 @@ am__khost_SOURCES_DIST = utils/kdig/kdig_exec.c utils/kdig/kdig_exec.h \ @HAVE_UTILS_TRUE@ utils/khost/khost-khost_main.$(OBJEXT) \ @HAVE_UTILS_TRUE@ utils/khost/khost-khost_params.$(OBJEXT) khost_OBJECTS = $(am_khost_OBJECTS) -@HAVE_UTILS_TRUE@khost_DEPENDENCIES = $(am__DEPENDENCIES_14) \ -@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_15) +@HAVE_UTILS_TRUE@khost_DEPENDENCIES = $(am__DEPENDENCIES_15) \ +@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_16) am__kjournalprint_SOURCES_DIST = utils/kjournalprint/main.c @HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@am_kjournalprint_OBJECTS = utils/kjournalprint/kjournalprint-main.$(OBJEXT) kjournalprint_OBJECTS = $(am_kjournalprint_OBJECTS) @HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@kjournalprint_DEPENDENCIES = \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_13) \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_14) +@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_14) \ +@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_15) kjournalprint_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(kjournalprint_LDFLAGS) $(LDFLAGS) -o $@ @@ -1045,8 +1060,8 @@ am__knotc_SOURCES_DIST = utils/knotc/commands.c utils/knotc/commands.h \ @HAVE_DAEMON_TRUE@ utils/knotc/knotc-process.$(OBJEXT) \ @HAVE_DAEMON_TRUE@ utils/knotc/knotc-main.$(OBJEXT) knotc_OBJECTS = $(am_knotc_OBJECTS) -@HAVE_DAEMON_TRUE@knotc_DEPENDENCIES = $(am__DEPENDENCIES_13) \ -@HAVE_DAEMON_TRUE@ $(am__DEPENDENCIES_14) +@HAVE_DAEMON_TRUE@knotc_DEPENDENCIES = $(am__DEPENDENCIES_14) \ +@HAVE_DAEMON_TRUE@ $(am__DEPENDENCIES_15) knotc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(knotc_LDFLAGS) $(LDFLAGS) -o $@ @@ -1054,7 +1069,7 @@ am__knotd_SOURCES_DIST = utils/knotd/main.c @HAVE_DAEMON_TRUE@am_knotd_OBJECTS = utils/knotd/knotd-main.$(OBJEXT) knotd_OBJECTS = $(am_knotd_OBJECTS) @HAVE_DAEMON_TRUE@knotd_DEPENDENCIES = $(am__DEPENDENCIES_1) \ -@HAVE_DAEMON_TRUE@ $(am__DEPENDENCIES_13) $(am__DEPENDENCIES_1) +@HAVE_DAEMON_TRUE@ $(am__DEPENDENCIES_14) $(am__DEPENDENCIES_1) knotd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(knotd_LDFLAGS) $(LDFLAGS) -o $@ @@ -1075,28 +1090,31 @@ am__knsupdate_SOURCES_DIST = utils/knsupdate/knsupdate_exec.c \ @HAVE_UTILS_TRUE@ utils/knsupdate/knsupdate-knsupdate_main.$(OBJEXT) \ @HAVE_UTILS_TRUE@ utils/knsupdate/knsupdate-knsupdate_params.$(OBJEXT) knsupdate_OBJECTS = $(am_knsupdate_OBJECTS) -@HAVE_UTILS_TRUE@knsupdate_DEPENDENCIES = $(am__DEPENDENCIES_14) \ +@HAVE_UTILS_TRUE@knsupdate_DEPENDENCIES = $(am__DEPENDENCIES_15) \ @HAVE_UTILS_TRUE@ libzscanner.la am__kxdpgun_SOURCES_DIST = utils/kxdpgun/ip_route.c \ utils/kxdpgun/ip_route.h utils/kxdpgun/load_queries.c \ - utils/kxdpgun/load_queries.h utils/kxdpgun/main.c + utils/kxdpgun/load_queries.h utils/kxdpgun/main.c \ + utils/kxdpgun/main.h utils/kxdpgun/stats.c \ + utils/kxdpgun/stats.h @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@am_kxdpgun_OBJECTS = utils/kxdpgun/kxdpgun-ip_route.$(OBJEXT) \ @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/kxdpgun-load_queries.$(OBJEXT) \ -@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/kxdpgun-main.$(OBJEXT) +@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/kxdpgun-main.$(OBJEXT) \ +@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/kxdpgun-stats.$(OBJEXT) kxdpgun_OBJECTS = $(am_kxdpgun_OBJECTS) -@ENABLE_QUIC_TRUE@@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@am__DEPENDENCIES_16 = $(am__DEPENDENCIES_1) +@ENABLE_QUIC_TRUE@@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@am__DEPENDENCIES_17 = $(am__DEPENDENCIES_1) @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@kxdpgun_DEPENDENCIES = libknot.la \ @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_3) \ @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_1) \ -@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_16) +@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_17) am__kzonecheck_SOURCES_DIST = utils/kzonecheck/main.c \ utils/kzonecheck/zone_check.c utils/kzonecheck/zone_check.h @HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@am_kzonecheck_OBJECTS = utils/kzonecheck/kzonecheck-main.$(OBJEXT) \ @HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ utils/kzonecheck/kzonecheck-zone_check.$(OBJEXT) kzonecheck_OBJECTS = $(am_kzonecheck_OBJECTS) @HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@kzonecheck_DEPENDENCIES = \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_13) +@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_14) kzonecheck_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(kzonecheck_LDFLAGS) $(LDFLAGS) -o $@ @@ -1104,8 +1122,8 @@ am__kzonesign_SOURCES_DIST = utils/kzonesign/main.c @HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@am_kzonesign_OBJECTS = utils/kzonesign/kzonesign-main.$(OBJEXT) kzonesign_OBJECTS = $(am_kzonesign_OBJECTS) @HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@kzonesign_DEPENDENCIES = \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_13) \ -@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_14) +@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_14) \ +@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ $(am__DEPENDENCIES_15) kzonesign_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(kzonesign_LDFLAGS) $(LDFLAGS) -o $@ @@ -1200,6 +1218,7 @@ am__depfiles_remade = contrib/$(DEPDIR)/libcontrib_la-base32hex.Plo \ knot/catalog/$(DEPDIR)/libknotd_la-catalog_update.Plo \ knot/catalog/$(DEPDIR)/libknotd_la-generate.Plo \ knot/catalog/$(DEPDIR)/libknotd_la-interpret.Plo \ + knot/common/$(DEPDIR)/libknotd_la-dbus.Plo \ knot/common/$(DEPDIR)/libknotd_la-evsched.Plo \ knot/common/$(DEPDIR)/libknotd_la-fdset.Plo \ knot/common/$(DEPDIR)/libknotd_la-log.Plo \ @@ -1247,6 +1266,7 @@ am__depfiles_remade = contrib/$(DEPDIR)/libcontrib_la-base32hex.Plo \ knot/events/handlers/$(DEPDIR)/libknotd_la-notify.Plo \ knot/events/handlers/$(DEPDIR)/libknotd_la-refresh.Plo \ knot/events/handlers/$(DEPDIR)/libknotd_la-update.Plo \ + knot/events/handlers/$(DEPDIR)/libknotd_la-validate.Plo \ knot/journal/$(DEPDIR)/libknotd_la-journal_basic.Plo \ knot/journal/$(DEPDIR)/libknotd_la-journal_metadata.Plo \ knot/journal/$(DEPDIR)/libknotd_la-journal_read.Plo \ @@ -1276,8 +1296,12 @@ am__depfiles_remade = contrib/$(DEPDIR)/libcontrib_la-base32hex.Plo \ knot/modules/queryacl/$(DEPDIR)/la-queryacl.Plo \ knot/modules/queryacl/$(DEPDIR)/libknotd_la-queryacl.Plo \ knot/modules/rrl/$(DEPDIR)/la-functions.Plo \ + knot/modules/rrl/$(DEPDIR)/la-kru-avx2.Plo \ + knot/modules/rrl/$(DEPDIR)/la-kru-generic.Plo \ knot/modules/rrl/$(DEPDIR)/la-rrl.Plo \ knot/modules/rrl/$(DEPDIR)/libknotd_la-functions.Plo \ + knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-avx2.Plo \ + knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-generic.Plo \ knot/modules/rrl/$(DEPDIR)/libknotd_la-rrl.Plo \ knot/modules/stats/$(DEPDIR)/la-stats.Plo \ knot/modules/stats/$(DEPDIR)/libknotd_la-stats.Plo \ @@ -1300,6 +1324,7 @@ am__depfiles_remade = contrib/$(DEPDIR)/libcontrib_la-base32hex.Plo \ knot/query/$(DEPDIR)/libknotd_la-query.Plo \ knot/query/$(DEPDIR)/libknotd_la-quic-requestor.Plo \ knot/query/$(DEPDIR)/libknotd_la-requestor.Plo \ + knot/query/$(DEPDIR)/libknotd_la-tls-requestor.Plo \ knot/server/$(DEPDIR)/libknotd_la-dthreads.Plo \ knot/server/$(DEPDIR)/libknotd_la-handler.Plo \ knot/server/$(DEPDIR)/libknotd_la-proxyv2.Plo \ @@ -1380,6 +1405,8 @@ am__depfiles_remade = contrib/$(DEPDIR)/libcontrib_la-base32hex.Plo \ libknot/probe/$(DEPDIR)/la-probe.Plo \ libknot/quic/$(DEPDIR)/la-quic.Plo \ libknot/quic/$(DEPDIR)/la-quic_conn.Plo \ + libknot/quic/$(DEPDIR)/la-tls.Plo \ + libknot/quic/$(DEPDIR)/la-tls_common.Plo \ libknot/rrtype/$(DEPDIR)/la-naptr.Plo \ libknot/rrtype/$(DEPDIR)/la-opt.Plo \ libknot/rrtype/$(DEPDIR)/la-tsig.Plo \ @@ -1438,6 +1465,7 @@ am__depfiles_remade = contrib/$(DEPDIR)/libcontrib_la-base32hex.Plo \ utils/kxdpgun/$(DEPDIR)/kxdpgun-ip_route.Po \ utils/kxdpgun/$(DEPDIR)/kxdpgun-load_queries.Po \ utils/kxdpgun/$(DEPDIR)/kxdpgun-main.Po \ + utils/kxdpgun/$(DEPDIR)/kxdpgun-stats.Po \ utils/kzonecheck/$(DEPDIR)/kzonecheck-main.Po \ utils/kzonecheck/$(DEPDIR)/kzonecheck-zone_check.Po \ utils/kzonesign/$(DEPDIR)/kzonesign-main.Po @@ -1528,7 +1556,8 @@ am__nobase_include_libknot_HEADERS_DIST = libknot/attribute.h \ libknot/db/db_trie.h libknot/packet/compr.h \ libknot/packet/pkt.h libknot/packet/rrset-wire.h \ libknot/packet/wire.h libknot/probe/data.h \ - libknot/probe/probe.h libknot/rdata.h libknot/rdataset.h \ + libknot/probe/probe.h libknot/quic/tls.h \ + libknot/quic/tls_common.h libknot/rdata.h libknot/rdataset.h \ libknot/rrset-dump.h libknot/rrset.h libknot/rrtype/dnskey.h \ libknot/rrtype/ds.h libknot/rrtype/naptr.h \ libknot/rrtype/nsec.h libknot/rrtype/nsec3.h \ @@ -1545,7 +1574,7 @@ am__nobase_include_libknot_HEADERS_DIST = libknot/attribute.h \ libknot/quic/quic_conn.h HEADERS = $(include_libdnssec_HEADERS) $(include_libknotd_HEADERS) \ $(include_libzscanner_HEADERS) \ - $(nobase_include_libknot_HEADERS) + $(nobase_include_libknot_HEADERS) $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ @@ -1751,6 +1780,8 @@ infodir = @infodir@ install_sh = @install_sh@ libbpf_CFLAGS = @libbpf_CFLAGS@ libbpf_LIBS = @libbpf_LIBS@ +libdbus_CFLAGS = @libdbus_CFLAGS@ +libdbus_LIBS = @libdbus_LIBS@ libdir = @libdir@ libdnssec_SONAME = @libdnssec_SONAME@ libdnssec_SOVERSION = @libdnssec_SOVERSION@ @@ -1762,8 +1793,6 @@ libfstrm_CFLAGS = @libfstrm_CFLAGS@ libfstrm_LIBS = @libfstrm_LIBS@ libidn2_CFLAGS = @libidn2_CFLAGS@ libidn2_LIBS = @libidn2_LIBS@ -libidn_CFLAGS = @libidn_CFLAGS@ -libidn_LIBS = @libidn_LIBS@ libknot_SONAME = @libknot_SONAME@ libknot_SOVERSION = @libknot_SOVERSION@ libknot_VERSION_INFO = @libknot_VERSION_INFO@ @@ -1781,7 +1810,6 @@ libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@ libprotobuf_c_LIBS = @libprotobuf_c_LIBS@ liburcu_CFLAGS = @liburcu_CFLAGS@ liburcu_LIBS = @liburcu_LIBS@ -liburcu_PKGCONFIG = @liburcu_PKGCONFIG@ libxdp_CFLAGS = @libxdp_CFLAGS@ libxdp_LIBS = @libxdp_LIBS@ libzscanner_SONAME = @libzscanner_SONAME@ @@ -1849,7 +1877,7 @@ CLEANFILES = $(am__append_5) libzscanner/scanner.c BUILT_SOURCES = $(am__append_4) libzscanner/scanner.c lib_LTLIBRARIES = libdnssec.la libknot.la libzscanner.la noinst_LTLIBRARIES = libcontrib.la $(am__append_3) $(am__append_6) \ - $(am__append_19) $(am__append_51) + $(am__append_19) $(am__append_52) pkgconfig_DATA = libdnssec.pc libknot.pc libzscanner.pc \ $(am__append_20) libcontrib_la_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAG_VISIBILITY) \ @@ -1859,6 +1887,7 @@ libcontrib_la_LIBADD = $(pthread_LIBS) libcontrib_LIBS = libcontrib.la $(am__append_2) libcontrib_la_SOURCES = \ contrib/asan.h \ + contrib/atomic.h \ contrib/base32hex.c \ contrib/base32hex.h \ contrib/base64.c \ @@ -2121,25 +2150,26 @@ nobase_include_libknot_HEADERS = libknot/attribute.h libknot/codes.h \ libknot/db/db.h libknot/db/db_lmdb.h libknot/db/db_trie.h \ libknot/packet/compr.h libknot/packet/pkt.h \ libknot/packet/rrset-wire.h libknot/packet/wire.h \ - libknot/probe/data.h libknot/probe/probe.h libknot/rdata.h \ - libknot/rdataset.h libknot/rrset-dump.h libknot/rrset.h \ - libknot/rrtype/dnskey.h libknot/rrtype/ds.h \ - libknot/rrtype/naptr.h libknot/rrtype/nsec.h \ - libknot/rrtype/nsec3.h libknot/rrtype/nsec3param.h \ - libknot/rrtype/opt.h libknot/rrtype/rdname.h \ - libknot/rrtype/rrsig.h libknot/rrtype/soa.h \ - libknot/rrtype/svcb.h libknot/rrtype/tsig.h \ - libknot/rrtype/zonemd.h libknot/tsig-op.h libknot/tsig.h \ - libknot/wire.h libknot/yparser/yparser.h \ - libknot/yparser/ypformat.h libknot/yparser/ypschema.h \ - libknot/yparser/yptrafo.h libknot/version.h \ - libknot/xdp/tcp_iobuf.h libknot/xdp.h $(am__append_11) \ - $(am__append_15) + libknot/probe/data.h libknot/probe/probe.h libknot/quic/tls.h \ + libknot/quic/tls_common.h libknot/rdata.h libknot/rdataset.h \ + libknot/rrset-dump.h libknot/rrset.h libknot/rrtype/dnskey.h \ + libknot/rrtype/ds.h libknot/rrtype/naptr.h \ + libknot/rrtype/nsec.h libknot/rrtype/nsec3.h \ + libknot/rrtype/nsec3param.h libknot/rrtype/opt.h \ + libknot/rrtype/rdname.h libknot/rrtype/rrsig.h \ + libknot/rrtype/soa.h libknot/rrtype/svcb.h \ + libknot/rrtype/tsig.h libknot/rrtype/zonemd.h \ + libknot/tsig-op.h libknot/tsig.h libknot/wire.h \ + libknot/yparser/yparser.h libknot/yparser/ypformat.h \ + libknot/yparser/ypschema.h libknot/yparser/yptrafo.h \ + libknot/version.h libknot/xdp/tcp_iobuf.h libknot/xdp.h \ + $(am__append_11) $(am__append_15) libknot_la_SOURCES = libknot/codes.c libknot/control/control.c \ libknot/cookies.c libknot/descriptor.c libknot/dname.c \ libknot/error.c libknot/db/db_lmdb.c libknot/db/db_trie.c \ libknot/packet/pkt.c libknot/packet/rrset-wire.c \ - libknot/probe/data.c libknot/probe/probe.c libknot/rdataset.c \ + libknot/probe/data.c libknot/probe/probe.c libknot/quic/tls.c \ + libknot/quic/tls_common.c libknot/rdataset.c \ libknot/rrset-dump.c libknot/rrset.c libknot/rrtype/naptr.c \ libknot/rrtype/opt.c libknot/rrtype/tsig.c libknot/tsig-op.c \ libknot/tsig.c libknot/yparser/yparser.c \ @@ -2169,15 +2199,15 @@ nodist_libzscanner_la_SOURCES = \ libknotd_la_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAG_VISIBILITY) \ $(libkqueue_CFLAGS) $(liburcu_CFLAGS) $(lmdb_CFLAGS) \ - $(systemd_CFLAGS) $(gnutls_CFLAGS) $(libngtcp2_CFLAGS) \ + $(systemd_CFLAGS) $(libdbus_CFLAGS) $(gnutls_CFLAGS) \ -DKNOTD_MOD_STATIC $(am__append_28) $(am__append_32) libknotd_la_LDFLAGS = $(AM_LDFLAGS) -export-symbols-regex '^knotd_' libknotd_la_LIBADD = $(dlopen_LIBS) $(libkqueue_LIBS) $(pthread_LIBS) \ - $(libngtcp2_LIBS) $(am__append_17) $(am__append_29) \ - $(am__append_33) + $(am__append_17) $(am__append_29) $(am__append_33) \ + $(am__append_44) libknotd_LIBS = libknotd.la libknot.la libdnssec.la libzscanner.la \ $(libcontrib_LIBS) $(liburcu_LIBS) $(lmdb_LIBS) \ - $(systemd_LIBS) $(gnutls_LIBS) + $(systemd_LIBS) $(libdbus_LIBS) $(gnutls_LIBS) include_libknotddir = $(includedir)/knot include_libknotd_HEADERS = \ @@ -2219,15 +2249,15 @@ libknotd_la_SOURCES = knot/catalog/catalog_db.c \ knot/events/handlers/flush.c \ knot/events/handlers/freeze_thaw.c knot/events/handlers/load.c \ knot/events/handlers/notify.c knot/events/handlers/refresh.c \ - knot/events/handlers/update.c knot/events/replan.c \ - knot/events/replan.h knot/nameserver/axfr.c \ - knot/nameserver/axfr.h knot/nameserver/chaos.c \ - knot/nameserver/chaos.h knot/nameserver/internet.c \ - knot/nameserver/internet.h knot/nameserver/ixfr.c \ - knot/nameserver/ixfr.h knot/nameserver/log.h \ - knot/nameserver/notify.c knot/nameserver/notify.h \ - knot/nameserver/nsec_proofs.c knot/nameserver/nsec_proofs.h \ - knot/nameserver/process_query.c \ + knot/events/handlers/update.c knot/events/handlers/validate.c \ + knot/events/replan.c knot/events/replan.h \ + knot/nameserver/axfr.c knot/nameserver/axfr.h \ + knot/nameserver/chaos.c knot/nameserver/chaos.h \ + knot/nameserver/internet.c knot/nameserver/internet.h \ + knot/nameserver/ixfr.c knot/nameserver/ixfr.h \ + knot/nameserver/log.h knot/nameserver/notify.c \ + knot/nameserver/notify.h knot/nameserver/nsec_proofs.c \ + knot/nameserver/nsec_proofs.h knot/nameserver/process_query.c \ knot/nameserver/process_query.h knot/nameserver/query_module.c \ knot/nameserver/query_module.h knot/nameserver/tsig_ctx.c \ knot/nameserver/tsig_ctx.h knot/nameserver/update.c \ @@ -2235,14 +2265,15 @@ libknotd_la_SOURCES = knot/catalog/catalog_db.c \ knot/nameserver/xfr.h knot/query/capture.c \ knot/query/capture.h knot/query/layer.h knot/query/query.c \ knot/query/query.h knot/query/requestor.c \ - knot/query/requestor.h knot/common/evsched.c \ - knot/common/evsched.h knot/common/fdset.c knot/common/fdset.h \ - knot/common/log.c knot/common/log.h knot/common/process.c \ - knot/common/process.h knot/common/stats.c knot/common/stats.h \ - knot/common/systemd.c knot/common/systemd.h \ - knot/common/unreachable.c knot/common/unreachable.h \ - knot/journal/journal_basic.c knot/journal/journal_basic.h \ - knot/journal/journal_metadata.c \ + knot/query/requestor.h knot/query/tls-requestor.c \ + knot/query/tls-requestor.h knot/common/dbus.c \ + knot/common/dbus.h knot/common/evsched.c knot/common/evsched.h \ + knot/common/fdset.c knot/common/fdset.h knot/common/log.c \ + knot/common/log.h knot/common/process.c knot/common/process.h \ + knot/common/stats.c knot/common/stats.h knot/common/systemd.c \ + knot/common/systemd.h knot/common/unreachable.c \ + knot/common/unreachable.h knot/journal/journal_basic.c \ + knot/journal/journal_basic.h knot/journal/journal_metadata.c \ knot/journal/journal_metadata.h knot/journal/journal_read.c \ knot/journal/journal_read.h knot/journal/journal_write.c \ knot/journal/journal_write.h knot/journal/knot_lmdb.c \ @@ -2279,15 +2310,15 @@ libknotd_la_SOURCES = knot/catalog/catalog_db.c \ $(am__append_21) $(am__append_23) $(am__append_25) \ $(am__append_27) $(am__append_31) $(am__append_35) \ $(am__append_37) $(am__append_39) $(am__append_41) \ - $(am__append_43) $(am__append_45) $(am__append_47) \ - $(am__append_49) + $(am__append_43) $(am__append_46) $(am__append_48) \ + $(am__append_50) KNOTD_MOD_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAG_VISIBILITY) KNOTD_MOD_LDFLAGS = $(AM_LDFLAGS) -module -shared -avoid-version pkglib_LTLIBRARIES = $(am__append_22) $(am__append_24) \ $(am__append_26) $(am__append_30) $(am__append_34) \ $(am__append_36) $(am__append_38) $(am__append_40) \ - $(am__append_42) $(am__append_44) $(am__append_46) \ - $(am__append_48) $(am__append_50) + $(am__append_42) $(am__append_45) $(am__append_47) \ + $(am__append_49) $(am__append_51) knot_modules_authsignal_la_SOURCES = knot/modules/authsignal/authsignal.c @SHARED_MODULE_authsignal_TRUE@knot_modules_authsignal_la_LDFLAGS = $(KNOTD_MOD_LDFLAGS) @SHARED_MODULE_authsignal_TRUE@knot_modules_authsignal_la_CPPFLAGS = $(KNOTD_MOD_CPPFLAGS) @@ -2328,11 +2359,15 @@ knot_modules_queryacl_la_SOURCES = knot/modules/queryacl/queryacl.c @SHARED_MODULE_queryacl_TRUE@knot_modules_queryacl_la_CPPFLAGS = $(KNOTD_MOD_CPPFLAGS) knot_modules_rrl_la_SOURCES = knot/modules/rrl/rrl.c \ knot/modules/rrl/functions.c \ - knot/modules/rrl/functions.h + knot/modules/rrl/functions.h \ + knot/modules/rrl/kru-generic.c \ + knot/modules/rrl/kru-avx2.c \ + knot/modules/rrl/kru.h +noinst_HEADERS = knot/modules/rrl/kru.inc.c @SHARED_MODULE_rrl_TRUE@knot_modules_rrl_la_LDFLAGS = $(KNOTD_MOD_LDFLAGS) @SHARED_MODULE_rrl_TRUE@knot_modules_rrl_la_CPPFLAGS = $(KNOTD_MOD_CPPFLAGS) -@SHARED_MODULE_rrl_TRUE@knot_modules_rrl_la_LIBADD = $(libcontrib_LIBS) +@SHARED_MODULE_rrl_TRUE@knot_modules_rrl_la_LIBADD = $(libcontrib_LIBS) $(math_LIBS) knot_modules_stats_la_SOURCES = knot/modules/stats/stats.c @SHARED_MODULE_stats_TRUE@knot_modules_stats_la_LDFLAGS = $(KNOTD_MOD_LDFLAGS) @SHARED_MODULE_stats_TRUE@knot_modules_stats_la_CPPFLAGS = $(KNOTD_MOD_CPPFLAGS) @@ -2353,7 +2388,7 @@ knot_modules_whoami_la_SOURCES = knot/modules/whoami/whoami.c @HAVE_LIBUTILS_TRUE@libknotus_la_LDFLAGS = $(AM_LDFLAGS) $(LDFLAG_EXCLUDE_LIBS) @HAVE_LIBUTILS_TRUE@libknotus_la_LIBADD = $(libidn2_LIBS) \ @HAVE_LIBUTILS_TRUE@ $(libidn_LIBS) $(libnghttp2_LIBS) \ -@HAVE_LIBUTILS_TRUE@ $(libngtcp2_LIBS) $(am__append_52) +@HAVE_LIBUTILS_TRUE@ $(libngtcp2_LIBS) $(am__append_53) @HAVE_LIBUTILS_TRUE@libknotus_LIBS = libknotus.la libknot.la libdnssec.la $(libcontrib_LIBS) \ @HAVE_LIBUTILS_TRUE@ $(gnutls_LIBS) $(libedit_LIBS) @@ -2416,11 +2451,11 @@ knot_modules_whoami_la_SOURCES = knot/modules/whoami/whoami.c @HAVE_UTILS_TRUE@ utils/knsupdate/knsupdate_params.h @HAVE_UTILS_TRUE@kdig_CPPFLAGS = $(libknotus_la_CPPFLAGS) \ -@HAVE_UTILS_TRUE@ $(am__append_54) -@HAVE_UTILS_TRUE@kdig_LDADD = $(libknotus_LIBS) $(am__append_55) +@HAVE_UTILS_TRUE@ $(am__append_55) +@HAVE_UTILS_TRUE@kdig_LDADD = $(libknotus_LIBS) $(am__append_56) @HAVE_UTILS_TRUE@khost_CPPFLAGS = $(libknotus_la_CPPFLAGS) \ -@HAVE_UTILS_TRUE@ $(am__append_56) -@HAVE_UTILS_TRUE@khost_LDADD = $(libknotus_LIBS) $(am__append_57) +@HAVE_UTILS_TRUE@ $(am__append_57) +@HAVE_UTILS_TRUE@khost_LDADD = $(libknotus_LIBS) $(am__append_58) @HAVE_UTILS_TRUE@knsec3hash_CPPFLAGS = $(libknotus_la_CPPFLAGS) @HAVE_UTILS_TRUE@knsec3hash_LDADD = libknot.la libdnssec.la $(libcontrib_LIBS) @HAVE_UTILS_TRUE@knsupdate_CPPFLAGS = $(libknotus_la_CPPFLAGS) @@ -2430,17 +2465,20 @@ knot_modules_whoami_la_SOURCES = knot/modules/whoami/whoami.c @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/ip_route.h \ @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/load_queries.c \ @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/load_queries.h \ -@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/main.c +@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/main.c \ +@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/main.h \ +@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/stats.c \ +@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ utils/kxdpgun/stats.h @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@kxdpgun_CPPFLAGS = \ @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(libknotus_la_CPPFLAGS) \ @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(libmnl_CFLAGS) \ -@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(am__append_59) +@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(am__append_60) @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@kxdpgun_LDADD = libknot.la \ @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(libcontrib_LIBS) \ @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(libmnl_LIBS) \ @ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(pthread_LIBS) \ -@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(am__append_60) +@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@ $(am__append_61) @HAVE_DAEMON_TRUE@knotc_SOURCES = \ @HAVE_DAEMON_TRUE@ utils/knotc/commands.c \ @HAVE_DAEMON_TRUE@ utils/knotc/commands.h \ @@ -2890,6 +2928,10 @@ knot/modules/rrl/la-rrl.lo: knot/modules/rrl/$(am__dirstamp) \ knot/modules/rrl/$(DEPDIR)/$(am__dirstamp) knot/modules/rrl/la-functions.lo: knot/modules/rrl/$(am__dirstamp) \ knot/modules/rrl/$(DEPDIR)/$(am__dirstamp) +knot/modules/rrl/la-kru-generic.lo: knot/modules/rrl/$(am__dirstamp) \ + knot/modules/rrl/$(DEPDIR)/$(am__dirstamp) +knot/modules/rrl/la-kru-avx2.lo: knot/modules/rrl/$(am__dirstamp) \ + knot/modules/rrl/$(DEPDIR)/$(am__dirstamp) knot/modules/rrl.la: $(knot_modules_rrl_la_OBJECTS) $(knot_modules_rrl_la_DEPENDENCIES) $(EXTRA_knot_modules_rrl_la_DEPENDENCIES) knot/modules/$(am__dirstamp) $(AM_V_CCLD)$(knot_modules_rrl_la_LINK) $(am_knot_modules_rrl_la_rpath) $(knot_modules_rrl_la_OBJECTS) $(knot_modules_rrl_la_LIBADD) $(LIBS) @@ -3352,6 +3394,16 @@ libknot/probe/la-data.lo: libknot/probe/$(am__dirstamp) \ libknot/probe/$(DEPDIR)/$(am__dirstamp) libknot/probe/la-probe.lo: libknot/probe/$(am__dirstamp) \ libknot/probe/$(DEPDIR)/$(am__dirstamp) +libknot/quic/$(am__dirstamp): + @$(MKDIR_P) libknot/quic + @: > libknot/quic/$(am__dirstamp) +libknot/quic/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) libknot/quic/$(DEPDIR) + @: > libknot/quic/$(DEPDIR)/$(am__dirstamp) +libknot/quic/la-tls.lo: libknot/quic/$(am__dirstamp) \ + libknot/quic/$(DEPDIR)/$(am__dirstamp) +libknot/quic/la-tls_common.lo: libknot/quic/$(am__dirstamp) \ + libknot/quic/$(DEPDIR)/$(am__dirstamp) libknot/la-rdataset.lo: libknot/$(am__dirstamp) \ libknot/$(DEPDIR)/$(am__dirstamp) libknot/la-rrset-dump.lo: libknot/$(am__dirstamp) \ @@ -3408,12 +3460,6 @@ libknot/xdp/la-tcp.lo: libknot/xdp/$(am__dirstamp) \ libknot/xdp/$(DEPDIR)/$(am__dirstamp) libknot/xdp/la-xdp.lo: libknot/xdp/$(am__dirstamp) \ libknot/xdp/$(DEPDIR)/$(am__dirstamp) -libknot/quic/$(am__dirstamp): - @$(MKDIR_P) libknot/quic - @: > libknot/quic/$(am__dirstamp) -libknot/quic/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) libknot/quic/$(DEPDIR) - @: > libknot/quic/$(DEPDIR)/$(am__dirstamp) libknot/quic/la-quic.lo: libknot/quic/$(am__dirstamp) \ libknot/quic/$(DEPDIR)/$(am__dirstamp) libknot/quic/la-quic_conn.lo: libknot/quic/$(am__dirstamp) \ @@ -3566,6 +3612,9 @@ knot/events/handlers/libknotd_la-refresh.lo: \ knot/events/handlers/libknotd_la-update.lo: \ knot/events/handlers/$(am__dirstamp) \ knot/events/handlers/$(DEPDIR)/$(am__dirstamp) +knot/events/handlers/libknotd_la-validate.lo: \ + knot/events/handlers/$(am__dirstamp) \ + knot/events/handlers/$(DEPDIR)/$(am__dirstamp) knot/events/libknotd_la-replan.lo: knot/events/$(am__dirstamp) \ knot/events/$(DEPDIR)/$(am__dirstamp) knot/nameserver/$(am__dirstamp): @@ -3615,12 +3664,16 @@ knot/query/libknotd_la-query.lo: knot/query/$(am__dirstamp) \ knot/query/$(DEPDIR)/$(am__dirstamp) knot/query/libknotd_la-requestor.lo: knot/query/$(am__dirstamp) \ knot/query/$(DEPDIR)/$(am__dirstamp) +knot/query/libknotd_la-tls-requestor.lo: knot/query/$(am__dirstamp) \ + knot/query/$(DEPDIR)/$(am__dirstamp) knot/common/$(am__dirstamp): @$(MKDIR_P) knot/common @: > knot/common/$(am__dirstamp) knot/common/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) knot/common/$(DEPDIR) @: > knot/common/$(DEPDIR)/$(am__dirstamp) +knot/common/libknotd_la-dbus.lo: knot/common/$(am__dirstamp) \ + knot/common/$(DEPDIR)/$(am__dirstamp) knot/common/libknotd_la-evsched.lo: knot/common/$(am__dirstamp) \ knot/common/$(DEPDIR)/$(am__dirstamp) knot/common/libknotd_la-fdset.lo: knot/common/$(am__dirstamp) \ @@ -3792,6 +3845,12 @@ knot/modules/rrl/libknotd_la-rrl.lo: knot/modules/rrl/$(am__dirstamp) \ knot/modules/rrl/libknotd_la-functions.lo: \ knot/modules/rrl/$(am__dirstamp) \ knot/modules/rrl/$(DEPDIR)/$(am__dirstamp) +knot/modules/rrl/libknotd_la-kru-generic.lo: \ + knot/modules/rrl/$(am__dirstamp) \ + knot/modules/rrl/$(DEPDIR)/$(am__dirstamp) +knot/modules/rrl/libknotd_la-kru-avx2.lo: \ + knot/modules/rrl/$(am__dirstamp) \ + knot/modules/rrl/$(DEPDIR)/$(am__dirstamp) knot/modules/stats/libknotd_la-stats.lo: \ knot/modules/stats/$(am__dirstamp) \ knot/modules/stats/$(DEPDIR)/$(am__dirstamp) @@ -4017,6 +4076,8 @@ utils/kxdpgun/kxdpgun-load_queries.$(OBJEXT): \ utils/kxdpgun/$(DEPDIR)/$(am__dirstamp) utils/kxdpgun/kxdpgun-main.$(OBJEXT): utils/kxdpgun/$(am__dirstamp) \ utils/kxdpgun/$(DEPDIR)/$(am__dirstamp) +utils/kxdpgun/kxdpgun-stats.$(OBJEXT): utils/kxdpgun/$(am__dirstamp) \ + utils/kxdpgun/$(DEPDIR)/$(am__dirstamp) kxdpgun$(EXEEXT): $(kxdpgun_OBJECTS) $(kxdpgun_DEPENDENCIES) $(EXTRA_kxdpgun_DEPENDENCIES) @rm -f kxdpgun$(EXEEXT) @@ -4259,6 +4320,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@knot/catalog/$(DEPDIR)/libknotd_la-catalog_update.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/catalog/$(DEPDIR)/libknotd_la-generate.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/catalog/$(DEPDIR)/libknotd_la-interpret.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@knot/common/$(DEPDIR)/libknotd_la-dbus.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/common/$(DEPDIR)/libknotd_la-evsched.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/common/$(DEPDIR)/libknotd_la-fdset.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/common/$(DEPDIR)/libknotd_la-log.Plo@am__quote@ # am--include-marker @@ -4306,6 +4368,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@knot/events/handlers/$(DEPDIR)/libknotd_la-notify.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/events/handlers/$(DEPDIR)/libknotd_la-refresh.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/events/handlers/$(DEPDIR)/libknotd_la-update.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@knot/events/handlers/$(DEPDIR)/libknotd_la-validate.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/journal/$(DEPDIR)/libknotd_la-journal_basic.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/journal/$(DEPDIR)/libknotd_la-journal_metadata.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/journal/$(DEPDIR)/libknotd_la-journal_read.Plo@am__quote@ # am--include-marker @@ -4335,8 +4398,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@knot/modules/queryacl/$(DEPDIR)/la-queryacl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/modules/queryacl/$(DEPDIR)/libknotd_la-queryacl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/modules/rrl/$(DEPDIR)/la-functions.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@knot/modules/rrl/$(DEPDIR)/la-kru-avx2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@knot/modules/rrl/$(DEPDIR)/la-kru-generic.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/modules/rrl/$(DEPDIR)/la-rrl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/modules/rrl/$(DEPDIR)/libknotd_la-functions.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-avx2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-generic.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/modules/rrl/$(DEPDIR)/libknotd_la-rrl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/modules/stats/$(DEPDIR)/la-stats.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/modules/stats/$(DEPDIR)/libknotd_la-stats.Plo@am__quote@ # am--include-marker @@ -4359,6 +4426,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@knot/query/$(DEPDIR)/libknotd_la-query.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/query/$(DEPDIR)/libknotd_la-quic-requestor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/query/$(DEPDIR)/libknotd_la-requestor.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@knot/query/$(DEPDIR)/libknotd_la-tls-requestor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/libknotd_la-dthreads.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/libknotd_la-handler.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/libknotd_la-proxyv2.Plo@am__quote@ # am--include-marker @@ -4441,6 +4509,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@libknot/probe/$(DEPDIR)/la-probe.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@libknot/quic/$(DEPDIR)/la-quic.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@libknot/quic/$(DEPDIR)/la-quic_conn.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@libknot/quic/$(DEPDIR)/la-tls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@libknot/quic/$(DEPDIR)/la-tls_common.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@libknot/rrtype/$(DEPDIR)/la-naptr.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@libknot/rrtype/$(DEPDIR)/la-opt.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@libknot/rrtype/$(DEPDIR)/la-tsig.Plo@am__quote@ # am--include-marker @@ -4499,6 +4569,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@utils/kxdpgun/$(DEPDIR)/kxdpgun-ip_route.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/kxdpgun/$(DEPDIR)/kxdpgun-load_queries.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/kxdpgun/$(DEPDIR)/kxdpgun-main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@utils/kxdpgun/$(DEPDIR)/kxdpgun-stats.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/kzonecheck/$(DEPDIR)/kzonecheck-main.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/kzonecheck/$(DEPDIR)/kzonecheck-zone_check.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/kzonesign/$(DEPDIR)/kzonesign-main.Po@am__quote@ # am--include-marker @@ -4624,6 +4695,20 @@ knot/modules/rrl/la-functions.lo: knot/modules/rrl/functions.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(knot_modules_rrl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knot/modules/rrl/la-functions.lo `test -f 'knot/modules/rrl/functions.c' || echo '$(srcdir)/'`knot/modules/rrl/functions.c +knot/modules/rrl/la-kru-generic.lo: knot/modules/rrl/kru-generic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(knot_modules_rrl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knot/modules/rrl/la-kru-generic.lo -MD -MP -MF knot/modules/rrl/$(DEPDIR)/la-kru-generic.Tpo -c -o knot/modules/rrl/la-kru-generic.lo `test -f 'knot/modules/rrl/kru-generic.c' || echo '$(srcdir)/'`knot/modules/rrl/kru-generic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) knot/modules/rrl/$(DEPDIR)/la-kru-generic.Tpo knot/modules/rrl/$(DEPDIR)/la-kru-generic.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='knot/modules/rrl/kru-generic.c' object='knot/modules/rrl/la-kru-generic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(knot_modules_rrl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knot/modules/rrl/la-kru-generic.lo `test -f 'knot/modules/rrl/kru-generic.c' || echo '$(srcdir)/'`knot/modules/rrl/kru-generic.c + +knot/modules/rrl/la-kru-avx2.lo: knot/modules/rrl/kru-avx2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(knot_modules_rrl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knot/modules/rrl/la-kru-avx2.lo -MD -MP -MF knot/modules/rrl/$(DEPDIR)/la-kru-avx2.Tpo -c -o knot/modules/rrl/la-kru-avx2.lo `test -f 'knot/modules/rrl/kru-avx2.c' || echo '$(srcdir)/'`knot/modules/rrl/kru-avx2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) knot/modules/rrl/$(DEPDIR)/la-kru-avx2.Tpo knot/modules/rrl/$(DEPDIR)/la-kru-avx2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='knot/modules/rrl/kru-avx2.c' object='knot/modules/rrl/la-kru-avx2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(knot_modules_rrl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knot/modules/rrl/la-kru-avx2.lo `test -f 'knot/modules/rrl/kru-avx2.c' || echo '$(srcdir)/'`knot/modules/rrl/kru-avx2.c + knot/modules/stats/la-stats.lo: knot/modules/stats/stats.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(knot_modules_stats_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knot/modules/stats/la-stats.lo -MD -MP -MF knot/modules/stats/$(DEPDIR)/la-stats.Tpo -c -o knot/modules/stats/la-stats.lo `test -f 'knot/modules/stats/stats.c' || echo '$(srcdir)/'`knot/modules/stats/stats.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) knot/modules/stats/$(DEPDIR)/la-stats.Tpo knot/modules/stats/$(DEPDIR)/la-stats.Plo @@ -5429,6 +5514,20 @@ libknot/probe/la-probe.lo: libknot/probe/probe.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknot_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libknot/probe/la-probe.lo `test -f 'libknot/probe/probe.c' || echo '$(srcdir)/'`libknot/probe/probe.c +libknot/quic/la-tls.lo: libknot/quic/tls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknot_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libknot/quic/la-tls.lo -MD -MP -MF libknot/quic/$(DEPDIR)/la-tls.Tpo -c -o libknot/quic/la-tls.lo `test -f 'libknot/quic/tls.c' || echo '$(srcdir)/'`libknot/quic/tls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libknot/quic/$(DEPDIR)/la-tls.Tpo libknot/quic/$(DEPDIR)/la-tls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libknot/quic/tls.c' object='libknot/quic/la-tls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknot_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libknot/quic/la-tls.lo `test -f 'libknot/quic/tls.c' || echo '$(srcdir)/'`libknot/quic/tls.c + +libknot/quic/la-tls_common.lo: libknot/quic/tls_common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknot_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libknot/quic/la-tls_common.lo -MD -MP -MF libknot/quic/$(DEPDIR)/la-tls_common.Tpo -c -o libknot/quic/la-tls_common.lo `test -f 'libknot/quic/tls_common.c' || echo '$(srcdir)/'`libknot/quic/tls_common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libknot/quic/$(DEPDIR)/la-tls_common.Tpo libknot/quic/$(DEPDIR)/la-tls_common.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libknot/quic/tls_common.c' object='libknot/quic/la-tls_common.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknot_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libknot/quic/la-tls_common.lo `test -f 'libknot/quic/tls_common.c' || echo '$(srcdir)/'`libknot/quic/tls_common.c + libknot/la-rdataset.lo: libknot/rdataset.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknot_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libknot/la-rdataset.lo -MD -MP -MF libknot/$(DEPDIR)/la-rdataset.Tpo -c -o libknot/la-rdataset.lo `test -f 'libknot/rdataset.c' || echo '$(srcdir)/'`libknot/rdataset.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libknot/$(DEPDIR)/la-rdataset.Tpo libknot/$(DEPDIR)/la-rdataset.Plo @@ -5877,6 +5976,13 @@ knot/events/handlers/libknotd_la-update.lo: knot/events/handlers/update.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knot/events/handlers/libknotd_la-update.lo `test -f 'knot/events/handlers/update.c' || echo '$(srcdir)/'`knot/events/handlers/update.c +knot/events/handlers/libknotd_la-validate.lo: knot/events/handlers/validate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knot/events/handlers/libknotd_la-validate.lo -MD -MP -MF knot/events/handlers/$(DEPDIR)/libknotd_la-validate.Tpo -c -o knot/events/handlers/libknotd_la-validate.lo `test -f 'knot/events/handlers/validate.c' || echo '$(srcdir)/'`knot/events/handlers/validate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) knot/events/handlers/$(DEPDIR)/libknotd_la-validate.Tpo knot/events/handlers/$(DEPDIR)/libknotd_la-validate.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='knot/events/handlers/validate.c' object='knot/events/handlers/libknotd_la-validate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knot/events/handlers/libknotd_la-validate.lo `test -f 'knot/events/handlers/validate.c' || echo '$(srcdir)/'`knot/events/handlers/validate.c + knot/events/libknotd_la-replan.lo: knot/events/replan.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knot/events/libknotd_la-replan.lo -MD -MP -MF knot/events/$(DEPDIR)/libknotd_la-replan.Tpo -c -o knot/events/libknotd_la-replan.lo `test -f 'knot/events/replan.c' || echo '$(srcdir)/'`knot/events/replan.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) knot/events/$(DEPDIR)/libknotd_la-replan.Tpo knot/events/$(DEPDIR)/libknotd_la-replan.Plo @@ -5982,6 +6088,20 @@ knot/query/libknotd_la-requestor.lo: knot/query/requestor.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knot/query/libknotd_la-requestor.lo `test -f 'knot/query/requestor.c' || echo '$(srcdir)/'`knot/query/requestor.c +knot/query/libknotd_la-tls-requestor.lo: knot/query/tls-requestor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knot/query/libknotd_la-tls-requestor.lo -MD -MP -MF knot/query/$(DEPDIR)/libknotd_la-tls-requestor.Tpo -c -o knot/query/libknotd_la-tls-requestor.lo `test -f 'knot/query/tls-requestor.c' || echo '$(srcdir)/'`knot/query/tls-requestor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) knot/query/$(DEPDIR)/libknotd_la-tls-requestor.Tpo knot/query/$(DEPDIR)/libknotd_la-tls-requestor.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='knot/query/tls-requestor.c' object='knot/query/libknotd_la-tls-requestor.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knot/query/libknotd_la-tls-requestor.lo `test -f 'knot/query/tls-requestor.c' || echo '$(srcdir)/'`knot/query/tls-requestor.c + +knot/common/libknotd_la-dbus.lo: knot/common/dbus.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knot/common/libknotd_la-dbus.lo -MD -MP -MF knot/common/$(DEPDIR)/libknotd_la-dbus.Tpo -c -o knot/common/libknotd_la-dbus.lo `test -f 'knot/common/dbus.c' || echo '$(srcdir)/'`knot/common/dbus.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) knot/common/$(DEPDIR)/libknotd_la-dbus.Tpo knot/common/$(DEPDIR)/libknotd_la-dbus.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='knot/common/dbus.c' object='knot/common/libknotd_la-dbus.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knot/common/libknotd_la-dbus.lo `test -f 'knot/common/dbus.c' || echo '$(srcdir)/'`knot/common/dbus.c + knot/common/libknotd_la-evsched.lo: knot/common/evsched.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knot/common/libknotd_la-evsched.lo -MD -MP -MF knot/common/$(DEPDIR)/libknotd_la-evsched.Tpo -c -o knot/common/libknotd_la-evsched.lo `test -f 'knot/common/evsched.c' || echo '$(srcdir)/'`knot/common/evsched.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) knot/common/$(DEPDIR)/libknotd_la-evsched.Tpo knot/common/$(DEPDIR)/libknotd_la-evsched.Plo @@ -6416,6 +6536,20 @@ knot/modules/rrl/libknotd_la-functions.lo: knot/modules/rrl/functions.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knot/modules/rrl/libknotd_la-functions.lo `test -f 'knot/modules/rrl/functions.c' || echo '$(srcdir)/'`knot/modules/rrl/functions.c +knot/modules/rrl/libknotd_la-kru-generic.lo: knot/modules/rrl/kru-generic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knot/modules/rrl/libknotd_la-kru-generic.lo -MD -MP -MF knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-generic.Tpo -c -o knot/modules/rrl/libknotd_la-kru-generic.lo `test -f 'knot/modules/rrl/kru-generic.c' || echo '$(srcdir)/'`knot/modules/rrl/kru-generic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-generic.Tpo knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-generic.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='knot/modules/rrl/kru-generic.c' object='knot/modules/rrl/libknotd_la-kru-generic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knot/modules/rrl/libknotd_la-kru-generic.lo `test -f 'knot/modules/rrl/kru-generic.c' || echo '$(srcdir)/'`knot/modules/rrl/kru-generic.c + +knot/modules/rrl/libknotd_la-kru-avx2.lo: knot/modules/rrl/kru-avx2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knot/modules/rrl/libknotd_la-kru-avx2.lo -MD -MP -MF knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-avx2.Tpo -c -o knot/modules/rrl/libknotd_la-kru-avx2.lo `test -f 'knot/modules/rrl/kru-avx2.c' || echo '$(srcdir)/'`knot/modules/rrl/kru-avx2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-avx2.Tpo knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-avx2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='knot/modules/rrl/kru-avx2.c' object='knot/modules/rrl/libknotd_la-kru-avx2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knot/modules/rrl/libknotd_la-kru-avx2.lo `test -f 'knot/modules/rrl/kru-avx2.c' || echo '$(srcdir)/'`knot/modules/rrl/kru-avx2.c + knot/modules/stats/libknotd_la-stats.lo: knot/modules/stats/stats.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libknotd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knot/modules/stats/libknotd_la-stats.lo -MD -MP -MF knot/modules/stats/$(DEPDIR)/libknotd_la-stats.Tpo -c -o knot/modules/stats/libknotd_la-stats.lo `test -f 'knot/modules/stats/stats.c' || echo '$(srcdir)/'`knot/modules/stats/stats.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) knot/modules/stats/$(DEPDIR)/libknotd_la-stats.Tpo knot/modules/stats/$(DEPDIR)/libknotd_la-stats.Plo @@ -6934,6 +7068,20 @@ utils/kxdpgun/kxdpgun-main.obj: utils/kxdpgun/main.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(kxdpgun_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utils/kxdpgun/kxdpgun-main.obj `if test -f 'utils/kxdpgun/main.c'; then $(CYGPATH_W) 'utils/kxdpgun/main.c'; else $(CYGPATH_W) '$(srcdir)/utils/kxdpgun/main.c'; fi` +utils/kxdpgun/kxdpgun-stats.o: utils/kxdpgun/stats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(kxdpgun_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utils/kxdpgun/kxdpgun-stats.o -MD -MP -MF utils/kxdpgun/$(DEPDIR)/kxdpgun-stats.Tpo -c -o utils/kxdpgun/kxdpgun-stats.o `test -f 'utils/kxdpgun/stats.c' || echo '$(srcdir)/'`utils/kxdpgun/stats.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) utils/kxdpgun/$(DEPDIR)/kxdpgun-stats.Tpo utils/kxdpgun/$(DEPDIR)/kxdpgun-stats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils/kxdpgun/stats.c' object='utils/kxdpgun/kxdpgun-stats.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(kxdpgun_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utils/kxdpgun/kxdpgun-stats.o `test -f 'utils/kxdpgun/stats.c' || echo '$(srcdir)/'`utils/kxdpgun/stats.c + +utils/kxdpgun/kxdpgun-stats.obj: utils/kxdpgun/stats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(kxdpgun_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utils/kxdpgun/kxdpgun-stats.obj -MD -MP -MF utils/kxdpgun/$(DEPDIR)/kxdpgun-stats.Tpo -c -o utils/kxdpgun/kxdpgun-stats.obj `if test -f 'utils/kxdpgun/stats.c'; then $(CYGPATH_W) 'utils/kxdpgun/stats.c'; else $(CYGPATH_W) '$(srcdir)/utils/kxdpgun/stats.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) utils/kxdpgun/$(DEPDIR)/kxdpgun-stats.Tpo utils/kxdpgun/$(DEPDIR)/kxdpgun-stats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils/kxdpgun/stats.c' object='utils/kxdpgun/kxdpgun-stats.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(kxdpgun_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utils/kxdpgun/kxdpgun-stats.obj `if test -f 'utils/kxdpgun/stats.c'; then $(CYGPATH_W) 'utils/kxdpgun/stats.c'; else $(CYGPATH_W) '$(srcdir)/utils/kxdpgun/stats.c'; fi` + utils/kzonecheck/kzonecheck-main.o: utils/kzonecheck/main.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(kzonecheck_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utils/kzonecheck/kzonecheck-main.o -MD -MP -MF utils/kzonecheck/$(DEPDIR)/kzonecheck-main.Tpo -c -o utils/kzonecheck/kzonecheck-main.o `test -f 'utils/kzonecheck/main.c' || echo '$(srcdir)/'`utils/kzonecheck/main.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) utils/kzonecheck/$(DEPDIR)/kzonecheck-main.Tpo utils/kzonecheck/$(DEPDIR)/kzonecheck-main.Po @@ -7577,6 +7725,7 @@ distclean: distclean-recursive -rm -f knot/catalog/$(DEPDIR)/libknotd_la-catalog_update.Plo -rm -f knot/catalog/$(DEPDIR)/libknotd_la-generate.Plo -rm -f knot/catalog/$(DEPDIR)/libknotd_la-interpret.Plo + -rm -f knot/common/$(DEPDIR)/libknotd_la-dbus.Plo -rm -f knot/common/$(DEPDIR)/libknotd_la-evsched.Plo -rm -f knot/common/$(DEPDIR)/libknotd_la-fdset.Plo -rm -f knot/common/$(DEPDIR)/libknotd_la-log.Plo @@ -7624,6 +7773,7 @@ distclean: distclean-recursive -rm -f knot/events/handlers/$(DEPDIR)/libknotd_la-notify.Plo -rm -f knot/events/handlers/$(DEPDIR)/libknotd_la-refresh.Plo -rm -f knot/events/handlers/$(DEPDIR)/libknotd_la-update.Plo + -rm -f knot/events/handlers/$(DEPDIR)/libknotd_la-validate.Plo -rm -f knot/journal/$(DEPDIR)/libknotd_la-journal_basic.Plo -rm -f knot/journal/$(DEPDIR)/libknotd_la-journal_metadata.Plo -rm -f knot/journal/$(DEPDIR)/libknotd_la-journal_read.Plo @@ -7653,8 +7803,12 @@ distclean: distclean-recursive -rm -f knot/modules/queryacl/$(DEPDIR)/la-queryacl.Plo -rm -f knot/modules/queryacl/$(DEPDIR)/libknotd_la-queryacl.Plo -rm -f knot/modules/rrl/$(DEPDIR)/la-functions.Plo + -rm -f knot/modules/rrl/$(DEPDIR)/la-kru-avx2.Plo + -rm -f knot/modules/rrl/$(DEPDIR)/la-kru-generic.Plo -rm -f knot/modules/rrl/$(DEPDIR)/la-rrl.Plo -rm -f knot/modules/rrl/$(DEPDIR)/libknotd_la-functions.Plo + -rm -f knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-avx2.Plo + -rm -f knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-generic.Plo -rm -f knot/modules/rrl/$(DEPDIR)/libknotd_la-rrl.Plo -rm -f knot/modules/stats/$(DEPDIR)/la-stats.Plo -rm -f knot/modules/stats/$(DEPDIR)/libknotd_la-stats.Plo @@ -7677,6 +7831,7 @@ distclean: distclean-recursive -rm -f knot/query/$(DEPDIR)/libknotd_la-query.Plo -rm -f knot/query/$(DEPDIR)/libknotd_la-quic-requestor.Plo -rm -f knot/query/$(DEPDIR)/libknotd_la-requestor.Plo + -rm -f knot/query/$(DEPDIR)/libknotd_la-tls-requestor.Plo -rm -f knot/server/$(DEPDIR)/libknotd_la-dthreads.Plo -rm -f knot/server/$(DEPDIR)/libknotd_la-handler.Plo -rm -f knot/server/$(DEPDIR)/libknotd_la-proxyv2.Plo @@ -7759,6 +7914,8 @@ distclean: distclean-recursive -rm -f libknot/probe/$(DEPDIR)/la-probe.Plo -rm -f libknot/quic/$(DEPDIR)/la-quic.Plo -rm -f libknot/quic/$(DEPDIR)/la-quic_conn.Plo + -rm -f libknot/quic/$(DEPDIR)/la-tls.Plo + -rm -f libknot/quic/$(DEPDIR)/la-tls_common.Plo -rm -f libknot/rrtype/$(DEPDIR)/la-naptr.Plo -rm -f libknot/rrtype/$(DEPDIR)/la-opt.Plo -rm -f libknot/rrtype/$(DEPDIR)/la-tsig.Plo @@ -7817,6 +7974,7 @@ distclean: distclean-recursive -rm -f utils/kxdpgun/$(DEPDIR)/kxdpgun-ip_route.Po -rm -f utils/kxdpgun/$(DEPDIR)/kxdpgun-load_queries.Po -rm -f utils/kxdpgun/$(DEPDIR)/kxdpgun-main.Po + -rm -f utils/kxdpgun/$(DEPDIR)/kxdpgun-stats.Po -rm -f utils/kzonecheck/$(DEPDIR)/kzonecheck-main.Po -rm -f utils/kzonecheck/$(DEPDIR)/kzonecheck-zone_check.Po -rm -f utils/kzonesign/$(DEPDIR)/kzonesign-main.Po @@ -7946,6 +8104,7 @@ maintainer-clean: maintainer-clean-recursive -rm -f knot/catalog/$(DEPDIR)/libknotd_la-catalog_update.Plo -rm -f knot/catalog/$(DEPDIR)/libknotd_la-generate.Plo -rm -f knot/catalog/$(DEPDIR)/libknotd_la-interpret.Plo + -rm -f knot/common/$(DEPDIR)/libknotd_la-dbus.Plo -rm -f knot/common/$(DEPDIR)/libknotd_la-evsched.Plo -rm -f knot/common/$(DEPDIR)/libknotd_la-fdset.Plo -rm -f knot/common/$(DEPDIR)/libknotd_la-log.Plo @@ -7993,6 +8152,7 @@ maintainer-clean: maintainer-clean-recursive -rm -f knot/events/handlers/$(DEPDIR)/libknotd_la-notify.Plo -rm -f knot/events/handlers/$(DEPDIR)/libknotd_la-refresh.Plo -rm -f knot/events/handlers/$(DEPDIR)/libknotd_la-update.Plo + -rm -f knot/events/handlers/$(DEPDIR)/libknotd_la-validate.Plo -rm -f knot/journal/$(DEPDIR)/libknotd_la-journal_basic.Plo -rm -f knot/journal/$(DEPDIR)/libknotd_la-journal_metadata.Plo -rm -f knot/journal/$(DEPDIR)/libknotd_la-journal_read.Plo @@ -8022,8 +8182,12 @@ maintainer-clean: maintainer-clean-recursive -rm -f knot/modules/queryacl/$(DEPDIR)/la-queryacl.Plo -rm -f knot/modules/queryacl/$(DEPDIR)/libknotd_la-queryacl.Plo -rm -f knot/modules/rrl/$(DEPDIR)/la-functions.Plo + -rm -f knot/modules/rrl/$(DEPDIR)/la-kru-avx2.Plo + -rm -f knot/modules/rrl/$(DEPDIR)/la-kru-generic.Plo -rm -f knot/modules/rrl/$(DEPDIR)/la-rrl.Plo -rm -f knot/modules/rrl/$(DEPDIR)/libknotd_la-functions.Plo + -rm -f knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-avx2.Plo + -rm -f knot/modules/rrl/$(DEPDIR)/libknotd_la-kru-generic.Plo -rm -f knot/modules/rrl/$(DEPDIR)/libknotd_la-rrl.Plo -rm -f knot/modules/stats/$(DEPDIR)/la-stats.Plo -rm -f knot/modules/stats/$(DEPDIR)/libknotd_la-stats.Plo @@ -8046,6 +8210,7 @@ maintainer-clean: maintainer-clean-recursive -rm -f knot/query/$(DEPDIR)/libknotd_la-query.Plo -rm -f knot/query/$(DEPDIR)/libknotd_la-quic-requestor.Plo -rm -f knot/query/$(DEPDIR)/libknotd_la-requestor.Plo + -rm -f knot/query/$(DEPDIR)/libknotd_la-tls-requestor.Plo -rm -f knot/server/$(DEPDIR)/libknotd_la-dthreads.Plo -rm -f knot/server/$(DEPDIR)/libknotd_la-handler.Plo -rm -f knot/server/$(DEPDIR)/libknotd_la-proxyv2.Plo @@ -8128,6 +8293,8 @@ maintainer-clean: maintainer-clean-recursive -rm -f libknot/probe/$(DEPDIR)/la-probe.Plo -rm -f libknot/quic/$(DEPDIR)/la-quic.Plo -rm -f libknot/quic/$(DEPDIR)/la-quic_conn.Plo + -rm -f libknot/quic/$(DEPDIR)/la-tls.Plo + -rm -f libknot/quic/$(DEPDIR)/la-tls_common.Plo -rm -f libknot/rrtype/$(DEPDIR)/la-naptr.Plo -rm -f libknot/rrtype/$(DEPDIR)/la-opt.Plo -rm -f libknot/rrtype/$(DEPDIR)/la-tsig.Plo @@ -8186,6 +8353,7 @@ maintainer-clean: maintainer-clean-recursive -rm -f utils/kxdpgun/$(DEPDIR)/kxdpgun-ip_route.Po -rm -f utils/kxdpgun/$(DEPDIR)/kxdpgun-load_queries.Po -rm -f utils/kxdpgun/$(DEPDIR)/kxdpgun-main.Po + -rm -f utils/kxdpgun/$(DEPDIR)/kxdpgun-stats.Po -rm -f utils/kzonecheck/$(DEPDIR)/kzonecheck-main.Po -rm -f utils/kzonecheck/$(DEPDIR)/kzonecheck-zone_check.Po -rm -f utils/kzonesign/$(DEPDIR)/kzonesign-main.Po diff --git a/src/config.h.in b/src/config.h.in index 0be849d..3e82c0d 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -3,12 +3,6 @@ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD -/* Passed CFLAGS from environment */ -#undef CONFIGURE_CFLAGS - -/* Params passed to configure */ -#undef CONFIGURE_PARAMS - /* Configure summary */ #undef CONFIGURE_SUMMARY @@ -18,8 +12,11 @@ /* POSIX capabilities available */ #undef ENABLE_CAP_NG +/* libdbus D-Bus available */ +#undef ENABLE_DBUS_LIBDBUS + /* systemd D-Bus available */ -#undef ENABLE_DBUS +#undef ENABLE_DBUS_SYSTEMD /* PKCS #11 support available */ #undef ENABLE_PKCS11 @@ -48,12 +45,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_NAMESER_H -/* Define to 1 if you have '__atomic' functions. */ -#undef HAVE_ATOMIC - /* Define to 1 if you have the header file. */ #undef HAVE_BSD_STRING_H +/* Define to 1 if you have C11 'atomic' functions. */ +#undef HAVE_C11_ATOMIC + /* Define if FreeBSD-like cpuset_t exists. */ #undef HAVE_CPUSET_BSD @@ -66,9 +63,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H -/* GnuTLS ED25519 support available */ -#undef HAVE_ED25519 - /* GnuTLS ED448 support available */ #undef HAVE_ED448 @@ -84,24 +78,18 @@ /* explicit_memset available */ #undef HAVE_EXPLICIT_MEMSET -/* gnutls_privkey_export_x509 available */ -#undef HAVE_EXPORT_X509 - /* Define to 1 if you have the `fgetln' function. */ #undef HAVE_FGETLN +/* Define to 1 if you have GCC-style '__atomic' functions. */ +#undef HAVE_GCC_ATOMIC + /* Define to 1 if you have the `getline' function. */ #undef HAVE_GETLINE -/* gnutls_memset available */ -#undef HAVE_GNUTLS_MEMSET - /* gnutls_early_cipher_get available */ #undef HAVE_GNUTLS_QUIC -/* GnuTLS reproducible signing available */ -#undef HAVE_GNUTLS_REPRODUCIBLE - /* Define to 1 if you have the `initgroups' function. */ #undef HAVE_INITGROUPS @@ -138,12 +126,6 @@ /* Define to 1 if you have the `setgroups' function. */ #undef HAVE_SETGROUPS -/* gnutls_privkey_sign_data2 available */ -#undef HAVE_SIGN_DATA2 - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDATOMIC_H - /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H @@ -165,9 +147,6 @@ /* Define to 1 if you have the `strlcpy' function. */ #undef HAVE_STRLCPY -/* Define to 1 if you have '__sync' functions. */ -#undef HAVE_SYNC_ATOMIC - /* Define to 1 if you have the `sysctlbyname' function. */ #undef HAVE_SYSCTLBYNAME @@ -193,9 +172,6 @@ /* Define to 1 to enable IDN support */ #undef LIBIDN -/* Define to proper libidn header */ -#undef LIBIDN_HEADER - /* Define to 1 to enable DoH support */ #undef LIBNGHTTP2 diff --git a/src/contrib/Makefile.inc b/src/contrib/Makefile.inc index e1577d5..d64c2eb 100644 --- a/src/contrib/Makefile.inc +++ b/src/contrib/Makefile.inc @@ -24,6 +24,7 @@ EXTRA_DIST += \ libcontrib_la_SOURCES = \ contrib/asan.h \ + contrib/atomic.h \ contrib/base32hex.c \ contrib/base32hex.h \ contrib/base64.c \ diff --git a/src/contrib/asan.h b/src/contrib/asan.h index 5feb2c1..ef6fe66 100644 --- a/src/contrib/asan.h +++ b/src/contrib/asan.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,13 +25,20 @@ #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) void __asan_poison_memory_region(void const volatile *addr, size_t size); void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +#if defined(__GNUC__) && !defined(__clang__) /* A faulty GCC workaround. */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif #define ASAN_POISON_MEMORY_REGION(addr, size) \ __asan_poison_memory_region((addr), (size)) +#if defined(__GNUC__) && !defined(__clang__) /* End of the workaround. */ + #pragma GCC diagnostic pop +#endif #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ __asan_unpoison_memory_region((addr), (size)) -#else +#else /* __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) */ #define ASAN_POISON_MEMORY_REGION(addr, size) \ ((void)(addr), (void)(size)) #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ ((void)(addr), (void)(size)) -#endif +#endif /* __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) */ diff --git a/src/contrib/atomic.h b/src/contrib/atomic.h new file mode 100644 index 0000000..b8dace1 --- /dev/null +++ b/src/contrib/atomic.h @@ -0,0 +1,73 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +/*! + * \brief C11 atomic operations with fallbacks. + */ + +#pragma once + +#ifdef HAVE_C11_ATOMIC /* C11 */ + #define KNOT_HAVE_ATOMIC + + #include + + #define ATOMIC_SET(dst, val) atomic_store_explicit(&(dst), (val), memory_order_relaxed) + #define ATOMIC_GET(src) atomic_load_explicit(&(src), memory_order_relaxed) + #define ATOMIC_ADD(dst, val) (void)atomic_fetch_add_explicit(&(dst), (val), memory_order_relaxed) + #define ATOMIC_SUB(dst, val) (void)atomic_fetch_sub_explicit(&(dst), (val), memory_order_relaxed) + #define ATOMIC_XCHG(dst, val) atomic_exchange_explicit(&(dst), (val), memory_order_relaxed) + + typedef atomic_uint_fast16_t knot_atomic_uint16_t; + typedef atomic_uint_fast64_t knot_atomic_uint64_t; + typedef atomic_size_t knot_atomic_size_t; + typedef _Atomic (void *) knot_atomic_ptr_t; + typedef atomic_bool knot_atomic_bool; +#elif defined(HAVE_GCC_ATOMIC) /* GCC __atomic */ + #define KNOT_HAVE_ATOMIC + + #include + #include + + #define ATOMIC_SET(dst, val) __atomic_store_n(&(dst), (val), __ATOMIC_RELAXED) + #define ATOMIC_GET(src) __atomic_load_n(&(src), __ATOMIC_RELAXED) + #define ATOMIC_ADD(dst, val) __atomic_add_fetch(&(dst), (val), __ATOMIC_RELAXED) + #define ATOMIC_SUB(dst, val) __atomic_sub_fetch(&(dst), (val), __ATOMIC_RELAXED) + #define ATOMIC_XCHG(dst, val) __atomic_exchange_n(&(dst), (val), __ATOMIC_RELAXED) + + typedef uint16_t knot_atomic_uint16_t; + typedef uint64_t knot_atomic_uint64_t; + typedef size_t knot_atomic_size_t; + typedef void* knot_atomic_ptr_t; + typedef bool knot_atomic_bool; +#else /* Fallback, non-atomic. */ + #warning "Atomic operations not availabe, using unreliable replacement." + + #include + #include + + #define ATOMIC_SET(dst, val) ((dst) = (val)) + #define ATOMIC_GET(src) (src) + #define ATOMIC_ADD(dst, val) ((dst) += (val)) + #define ATOMIC_SUB(dst, val) ((dst) -= (val)) + #define ATOMIC_XCHG(dst, val) ({ __typeof__ (dst) _z = (dst); (dst) = (val); _z; }) + + typedef uint16_t knot_atomic_uint16_t; + typedef uint64_t knot_atomic_uint64_t; + typedef size_t knot_atomic_size_t; + typedef void* knot_atomic_ptr_t; + typedef bool knot_atomic_bool; +#endif diff --git a/src/contrib/files.c b/src/contrib/files.c index 5b38469..f3a4b78 100644 --- a/src/contrib/files.c +++ b/src/contrib/files.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -92,16 +92,29 @@ static int remove_file(const char *path, const struct stat *stat, int type, stru { (void)stat; (void)ftw; - if (type == FTW_DP) { + + switch (type) { + case FTW_D: + case FTW_DNR: + case FTW_DP: return rmdir(path); - } else { + default: return unlink(path); } } -bool remove_path(const char *path) +static int remove_in_dir(const char *path, const struct stat *stat, int type, struct FTW *ftw) +{ + return (ftw->level > 0) ? remove_file(path, stat, type, ftw) : 0; +} + +int remove_path(const char *path, bool keep_apex) { - return (0 == nftw(path, remove_file, 1, FTW_DEPTH | FTW_PHYS)); + if (0 != nftw(path, keep_apex ? remove_in_dir : remove_file, + 1, FTW_DEPTH | FTW_PHYS)) { + return knot_map_errno(); + } + return KNOT_EOK; } int make_dir(const char *path, mode_t mode, bool ignore_existing) diff --git a/src/contrib/files.h b/src/contrib/files.h index c505ac8..4250a47 100644 --- a/src/contrib/files.h +++ b/src/contrib/files.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -52,9 +52,12 @@ bool same_path(const char *path1, const char *path2); /*! * \brief Delete file or directory (recursive). * - * \return true on success, false when one or more files failed to be removed. + * \param[in] path Absolute path or a relative path suffix; a string. + * \param[in] keep_apex If true, don't remove the starting point (apex). + * + * \return KNOT_E* */ -bool remove_path(const char *path); +int remove_path(const char *path, bool keep_apex); /*! * Equivalent to mkdir(2), can succeed if the directory already exists. diff --git a/src/contrib/json.c b/src/contrib/json.c index d44da87..5173f90 100644 --- a/src/contrib/json.c +++ b/src/contrib/json.c @@ -217,6 +217,13 @@ void jsonw_int(jsonw_t *w, const char *key, int value) fprintf(w->out, "%d", value); } +void jsonw_double(jsonw_t *w, const char *key, double value) +{ + assert(w); + + align_key(w, key); + fprintf(w->out, "%.4f", value); +} void jsonw_bool(jsonw_t *w, const char *key, bool value) { diff --git a/src/contrib/json.h b/src/contrib/json.h index cf8abe6..17513bc 100644 --- a/src/contrib/json.h +++ b/src/contrib/json.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -81,6 +81,11 @@ void jsonw_ulong(jsonw_t *w, const char *key, unsigned long value); */ void jsonw_int(jsonw_t *w, const char *key, int value); +/*! + * Write double as JSON. + */ +void jsonw_double(jsonw_t *w, const char *key, double value); + /*! * Write boolean value as JSON. */ diff --git a/src/contrib/mempattern.c b/src/contrib/mempattern.c index f57139d..f86f0ac 100644 --- a/src/contrib/mempattern.c +++ b/src/contrib/mempattern.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -114,9 +114,15 @@ void mm_ctx_init(knot_mm_t *mm) mm->free = free; } +// UBSAN type punning workaround +static void *mp_alloc_wrap(void *ctx, size_t size) +{ + return mp_alloc(ctx, size); +} + void mm_ctx_mempool(knot_mm_t *mm, size_t chunk_size) { mm->ctx = mp_new(chunk_size); - mm->alloc = (knot_mm_alloc_t)mp_alloc; + mm->alloc = mp_alloc_wrap; mm->free = mm_nofree; } diff --git a/src/contrib/spinlock.h b/src/contrib/spinlock.h index 837f500..a7ec5ec 100644 --- a/src/contrib/spinlock.h +++ b/src/contrib/spinlock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,48 +15,23 @@ */ /*! - * \brief Multiplatform spinlock. + * \brief A C11 spinlock (POSIX pthread spinlock as a fallback). */ #pragma once #if (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__) -/* Not tested and activated yet. */ -/* #define HAVE_STDATOMIC */ -#endif - -#if defined(__APPLE__) -# if defined(MAC_OS_X_VERSION_10_12) || \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 -# define APPLE_SPIN_NEW -# else -# define APPLE_SPIN_OLD -# endif /* MAC_OS_X_VERSION_10_12 ... */ -#endif /* __APPLE__ */ - -#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) -# include -#elif defined(HAVE_STDATOMIC) -# include -# include -#elif defined(APPLE_SPIN_NEW) -# include -#elif defined(APPLE_SPIN_OLD) -# include + #define HAVE_STDATOMIC + #include + #include #else /* POSIX pthread spinlock. */ -# include + #include #endif /*! \brief Spinlock lock variable type. */ typedef -#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) - bool /*!< Spinlock lock - a simple & fast atomic version. */ -#elif defined(HAVE_STDATOMIC) +#if defined(HAVE_STDATOMIC) atomic_bool /*!< Spinlock lock - a simple & fast atomic version, C11 */ -#elif defined(APPLE_SPIN_NEW) - os_unfair_lock /*!< Spinlock lock - a newer macOS version (macOS >= 10.12). */ -#elif defined(APPLE_SPIN_OLD) - OSSpinLock /*!< Spinlock lock - an older macOS version (macOS < 10.12). */ #else /* POSIX */ pthread_spinlock_t /*!< Spinlock lock - a POSIX pthread version. */ #endif @@ -65,14 +40,8 @@ typedef /*! \brief Initialize the spinlock pointed to by the parameter "lock". */ static inline void knot_spin_init(knot_spin_t *lock) { -#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) - *lock = false; -#elif defined(HAVE_STDATOMIC) +#if defined(HAVE_STDATOMIC) atomic_init(lock, false); -#elif defined(APPLE_SPIN_NEW) - *lock = OS_UNFAIR_LOCK_INIT; -#elif defined(APPLE_SPIN_OLD) - *lock = OS_SPINLOCK_INIT; #else /* POSIX */ pthread_spin_init(lock, PTHREAD_PROCESS_PRIVATE); #endif @@ -81,8 +50,7 @@ static inline void knot_spin_init(knot_spin_t *lock) /*! \brief Destroy the spinlock pointed to by the parameter "lock". */ static inline void knot_spin_destroy(knot_spin_t *lock) { -#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) || defined(HAVE_STDATOMIC) || \ - defined(APPLE_SPIN_NEW) || defined(APPLE_SPIN_OLD) +#if defined(HAVE_STDATOMIC) /* Nothing needed here. */ #else /* POSIX */ pthread_spin_destroy(lock); @@ -92,23 +60,11 @@ static inline void knot_spin_destroy(knot_spin_t *lock) /*! \brief Lock the spinlock pointed to by the parameter "lock". */ static inline void knot_spin_lock(knot_spin_t *lock) { -#if defined(HAVE_SYNC_ATOMIC) - while (__sync_lock_test_and_set(lock, 1)) { - } -#elif defined(HAVE_ATOMIC) - int expected = 0; - while (!__atomic_compare_exchange_n(lock, &expected, 1, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) { - expected = 0; - } -#elif defined(HAVE_STDATOMIC) - int expected = 0; - while (!atomic_compare_exchange_strong(lock, &expected, false)) { - expected = 0; +#if defined(HAVE_STDATOMIC) + bool expected = false; + while (!atomic_compare_exchange_strong(lock, &expected, true)) { + expected = false; } -#elif defined(APPLE_SPIN_NEW) - os_unfair_lock_lock(lock); -#elif defined(APPLE_SPIN_OLD) - OSSpinLockLock(lock); #else /* POSIX */ pthread_spin_lock(lock); #endif @@ -117,16 +73,8 @@ static inline void knot_spin_lock(knot_spin_t *lock) /*! \brief Unlock the spinlock pointed to by the parameter "lock". */ static inline void knot_spin_unlock(knot_spin_t *lock) { -#if defined(HAVE_SYNC_ATOMIC) - __sync_lock_release(lock); -#elif defined(HAVE_ATOMIC) - __atomic_clear(lock, __ATOMIC_RELAXED); -#elif defined(HAVE_STDATOMIC) +#if defined(HAVE_STDATOMIC) atomic_store(lock, false); -#elif defined(APPLE_SPIN_NEW) - os_unfair_lock_unlock(lock); -#elif defined(APPLE_SPIN_OLD) - OSSpinLockUnlock(lock); #else /* POSIX */ pthread_spin_unlock(lock); #endif diff --git a/src/contrib/string.c b/src/contrib/string.c index 272116e..6fa2d0a 100644 --- a/src/contrib/string.c +++ b/src/contrib/string.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,16 +26,16 @@ /* #include is needed. */ #elif defined(HAVE_EXPLICIT_MEMSET) /* #include is needed. */ -#elif defined(HAVE_GNUTLS_MEMSET) - #include #else - #define USE_CUSTOM_MEMSET + #include #endif #include "contrib/string.h" #include "contrib/ctype.h" #include "contrib/tolower.h" +const char *configure_summary = CONFIGURE_SUMMARY; + uint8_t *memdup(const uint8_t *data, size_t data_size) { uint8_t *result = (uint8_t *)malloc(data_size); @@ -137,11 +137,6 @@ int const_time_memcmp(const void *s1, const void *s2, size_t n) return equal; } -#if defined(USE_CUSTOM_MEMSET) -typedef void *(*memset_t)(void *, int, size_t); -static volatile memset_t volatile_memset = memset; -#endif - void *memzero(void *s, size_t n) { #if defined(HAVE_EXPLICIT_BZERO) /* In OpenBSD since 5.5. */ @@ -161,14 +156,9 @@ void *memzero(void *s, size_t n) return s; #elif defined(HAVE_EXPLICIT_MEMSET) /* In NetBSD since 7.0. */ return explicit_memset(s, 0, n); -#elif defined(HAVE_GNUTLS_MEMSET) /* In GnuTLS since 3.4.0. */ +#else gnutls_memset(s, 0, n); return s; -#else /* Knot custom solution as a fallback. */ - /* Warning: the use of the return value is *probably* needed - * so as to avoid the volatile_memset() to be optimized out. - */ - return volatile_memset(s, 0, n); #endif } diff --git a/src/contrib/string.h b/src/contrib/string.h index ad3c990..3e113b1 100644 --- a/src/contrib/string.h +++ b/src/contrib/string.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,8 @@ #include #include +extern const char *configure_summary; + /*! * \brief Create a copy of a binary buffer. * diff --git a/src/contrib/time.h b/src/contrib/time.h index 20d241e..b12b366 100644 --- a/src/contrib/time.h +++ b/src/contrib/time.h @@ -88,6 +88,11 @@ inline static int knot_time_cmp(knot_time_t a, knot_time_t b) { return (a == b ? 0 : 1) * ((a && b) == 0 ? -1 : 1) * (a < b ? -1 : 1); } +inline static bool knot_time_lt (knot_time_t a, knot_time_t b) { return knot_time_cmp(a, b) < 0; } +inline static bool knot_time_leq(knot_time_t a, knot_time_t b) { return knot_time_cmp(a, b) <= 0; } +inline static bool knot_time_eq (knot_time_t a, knot_time_t b) { return knot_time_cmp(a, b) == 0; } +inline static bool knot_time_geq(knot_time_t a, knot_time_t b) { return knot_time_cmp(a, b) >= 0; } +inline static bool knot_time_gt (knot_time_t a, knot_time_t b) { return knot_time_cmp(a, b) > 0; } /*! * \brief Return the smaller (=earlier) from given two timestamps. diff --git a/src/knot/Makefile.inc b/src/knot/Makefile.inc index f67fe7f..0cbc9f3 100644 --- a/src/knot/Makefile.inc +++ b/src/knot/Makefile.inc @@ -1,12 +1,11 @@ libknotd_la_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAG_VISIBILITY) $(libkqueue_CFLAGS) \ $(liburcu_CFLAGS) $(lmdb_CFLAGS) $(systemd_CFLAGS) \ - $(gnutls_CFLAGS) $(libngtcp2_CFLAGS) -DKNOTD_MOD_STATIC + $(libdbus_CFLAGS) $(gnutls_CFLAGS) -DKNOTD_MOD_STATIC libknotd_la_LDFLAGS = $(AM_LDFLAGS) -export-symbols-regex '^knotd_' -libknotd_la_LIBADD = $(dlopen_LIBS) $(libkqueue_LIBS) $(pthread_LIBS) \ - $(libngtcp2_LIBS) +libknotd_la_LIBADD = $(dlopen_LIBS) $(libkqueue_LIBS) $(pthread_LIBS) libknotd_LIBS = libknotd.la libknot.la libdnssec.la libzscanner.la \ $(libcontrib_LIBS) $(liburcu_LIBS) $(lmdb_LIBS) \ - $(systemd_LIBS) $(gnutls_LIBS) + $(systemd_LIBS) $(libdbus_LIBS) $(gnutls_LIBS) if EMBEDDED_LIBNGTCP2 libknotd_la_LIBADD += $(libembngtcp2_LIBS) @@ -93,6 +92,7 @@ libknotd_la_SOURCES = \ knot/events/handlers/notify.c \ knot/events/handlers/refresh.c \ knot/events/handlers/update.c \ + knot/events/handlers/validate.c \ knot/events/replan.c \ knot/events/replan.h \ knot/nameserver/axfr.c \ @@ -125,6 +125,10 @@ libknotd_la_SOURCES = \ knot/query/query.h \ knot/query/requestor.c \ knot/query/requestor.h \ + knot/query/tls-requestor.c \ + knot/query/tls-requestor.h \ + knot/common/dbus.c \ + knot/common/dbus.h \ knot/common/evsched.c \ knot/common/evsched.h \ knot/common/fdset.c \ diff --git a/src/knot/catalog/catalog_db.c b/src/knot/catalog/catalog_db.c index b483f4d..2ea776f 100644 --- a/src/knot/catalog/catalog_db.c +++ b/src/knot/catalog/catalog_db.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,7 +44,7 @@ int catalog_bailiwick_shift(const knot_dname_t *subname, const knot_dname_t *nam if (*res == '\0') { return -1; } - res = knot_wire_next_label(res, NULL); + res = knot_dname_next_label(res); } return res - subname; } diff --git a/src/knot/catalog/catalog_update.c b/src/knot/catalog/catalog_update.c index edfd8c5..71b7dbe 100644 --- a/src/knot/catalog/catalog_update.c +++ b/src/knot/catalog/catalog_update.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -132,7 +132,7 @@ static const knot_dname_t *get_uniq(const knot_dname_t *ptr_owner, int labels = knot_dname_labels(ptr_owner, NULL); labels -= knot_dname_labels(catz, NULL); assert(labels >= 2); - return ptr_owner + knot_dname_prefixlen(ptr_owner, labels - 2, NULL); + return ptr_owner + knot_dname_prefixlen(ptr_owner, labels - 2); } static bool same_uniq(const knot_dname_t *owner1, const knot_dname_t *catz1, diff --git a/src/knot/catalog/interpret.c b/src/knot/catalog/interpret.c index 7337105..3e8e5db 100644 --- a/src/knot/catalog/interpret.c +++ b/src/knot/catalog/interpret.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -105,7 +105,7 @@ static const knot_dname_t *property_get_member(const zone_node_t *prop_node, knot_rdataset_t *ptr = node_rdataset(prop_node->parent, KNOT_RRTYPE_PTR); if (ptr == NULL) { // fallback: search in provided complete zone contents - const knot_dname_t *memb_name = knot_wire_next_label(prop_node->owner, NULL); + const knot_dname_t *memb_name = knot_dname_next_label(prop_node->owner); const zone_node_t *memb_node = zone_contents_find_node(complete_conts, memb_name); ptr = node_rdataset(memb_node, KNOT_RRTYPE_PTR); if (memb_node != NULL) { diff --git a/src/knot/common/dbus.c b/src/knot/common/dbus.c new file mode 100644 index 0000000..38ae5fa --- /dev/null +++ b/src/knot/common/dbus.c @@ -0,0 +1,243 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include + +#include "knot/common/dbus.h" +#include "knot/common/log.h" + +#define ENABLE_DBUS (ENABLE_DBUS_SYSTEMD | ENABLE_DBUS_LIBDBUS) + +#if defined(ENABLE_DBUS_SYSTEMD) + +#include +#define VALUE_OF(x) (x) +typedef sd_bus * dbus_ctx_t; + +#elif defined(ENABLE_DBUS_LIBDBUS) + +#include +#include +#define VALUE_OF(x) (&(x)) +typedef DBusConnection * dbus_ctx_t; + +#else + +typedef struct {} * dbus_ctx_t; // Dummy + +#endif // ENABLE_DBUS_LIBDBUS + +static dbus_ctx_t _dbus = NULL; + +int dbus_open(void) +{ + if (_dbus != NULL) { + return KNOT_EOK; + } +#if defined(ENABLE_DBUS_SYSTEMD) + int ret = sd_bus_open_system(&_dbus); + if (ret < 0) { + goto error_systemd; + } + + /* Take a well-known service name so that clients can find us. */ + ret = sd_bus_request_name(_dbus, KNOT_DBUS_NAME, 0); + if (ret < 0) { + goto error_systemd; + } + + log_info("d-bus: connected to system bus"); + return KNOT_EOK; +error_systemd: + log_error("d-bus: failed to open system bus (%s)", knot_strerror(ret)); + dbus_close(); + return ret; +#elif defined(ENABLE_DBUS_LIBDBUS) + DBusError err; + dbus_error_init(&err); + + _dbus = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + if (dbus_error_is_set(&err) == TRUE) { + goto error_libdbus; + } + + /* Take a well-known service name so that clients can find us. */ + dbus_bus_request_name(_dbus, KNOT_DBUS_NAME, 0, &err); + if (dbus_error_is_set(&err) == TRUE) { + goto error_libdbus; + } + + dbus_error_free(&err); + log_info("d-bus: connected to system bus"); + return KNOT_EOK; +error_libdbus: + log_error("d-bus: failed to open system bus (%s)", err.message); + dbus_error_free(&err); + dbus_close(); + return KNOT_ERROR; +#endif + log_error("d-bus: not supported"); + return KNOT_ENOTSUP; +} + +void dbus_close(void) +{ + if (_dbus == NULL) { + return; + } +#if defined(ENABLE_DBUS_SYSTEMD) + _dbus = sd_bus_unref(_dbus); +#elif defined(ENABLE_DBUS_LIBDBUS) + dbus_connection_unref(_dbus); + _dbus = NULL; +#endif // ENABLE_DBUS_LIBDBUS +} + +#if ENABLE_DBUS +static void emit_event(const char *event, char *first_arg_type, ...) +{ + int ret = KNOT_ENOENT; + if (_dbus == NULL) { + goto failed; + } + +#if defined(ENABLE_DBUS_SYSTEMD) + sd_bus_message *msg = NULL; + ret = sd_bus_message_new_signal(_dbus, &msg, KNOT_DBUS_PATH, + KNOT_DBUS_NAME".events", event); + if (ret < 0) { + goto failed; + } + + va_list args; + va_start(args, first_arg_type); + ret = sd_bus_message_appendv(msg, first_arg_type, args); + if (ret < 0) { + sd_bus_message_unref(msg); + va_end(args); + goto failed; + } + /* + * \note sd_bus_message_send(msg) or even sd_bus_emit_signalv() can + * be used with a newer systemd. + */ + ret = sd_bus_send(sd_bus_message_get_bus(msg), msg, NULL); + if (ret < 0) { + sd_bus_message_unref(msg); + va_end(args); + goto failed; + } + va_end(args); +#elif defined(ENABLE_DBUS_LIBDBUS) + DBusMessage *msg = NULL; + msg = dbus_message_new_signal(KNOT_DBUS_PATH, KNOT_DBUS_NAME".events", + event); + if (msg == NULL) { + ret = KNOT_ENOMEM; + goto failed; + } + + /* + * \note This loop considers only basic data types; composite ones, + * such as arrays, result in undefined behavior. + */ + va_list args; + va_start(args, first_arg_type); + for (const char *type = first_arg_type; *type; ++type) { + dbus_bool_t bret = dbus_message_append_args(msg, *type, + va_arg(args, void *), + DBUS_TYPE_INVALID); + if (bret == FALSE) { + dbus_message_unref(msg); + va_end(args); + assert(0); // Read note + ret = KNOT_EINVAL; + goto failed; + } + } + + if (dbus_connection_send(_dbus, msg, NULL) == 0) { + dbus_message_unref(msg); + va_end(args); + ret = KNOT_NET_ESEND; + goto failed; + } + dbus_message_unref(msg); + va_end(args); +#endif // ENABLE_DBUS_LIBDBUS + return; +failed: + log_error("d-bus: failed to emit signal '%s' (%s)", event, knot_strerror(ret)); +} +#endif // ENABLE_DBUS + +void dbus_emit_running(bool up) +{ +#if ENABLE_DBUS + emit_event(up ? KNOT_BUS_EVENT_STARTED : KNOT_BUS_EVENT_STOPPED, ""); +#endif // ENABLE_DBUS +} + +void dbus_emit_zone_updated(const knot_dname_t *zone_name, uint32_t serial) +{ +#if ENABLE_DBUS + knot_dname_txt_storage_t buff; + char *zone_str = knot_dname_to_str(buff, zone_name, sizeof(buff)); + if (zone_str != NULL) { + emit_event(KNOT_BUS_EVENT_ZONE_UPD, "su", VALUE_OF(zone_str), + VALUE_OF(serial)); + } +#endif // ENABLE_DBUS +} + +void dbus_emit_keys_updated(const knot_dname_t *zone_name) +{ +#if ENABLE_DBUS + knot_dname_txt_storage_t buff; + char *zone_str = knot_dname_to_str(buff, zone_name, sizeof(buff)); + if (zone_str != NULL) { + emit_event(KNOT_BUS_EVENT_ZONE_KEYS_UPD, "s", + VALUE_OF(zone_str)); + } +#endif // ENABLE_DBUS +} + +void dbus_emit_zone_submission(const knot_dname_t *zone_name, uint16_t keytag, + const char *keyid) +{ +#if ENABLE_DBUS + knot_dname_txt_storage_t buff; + char *zone_str = knot_dname_to_str(buff, zone_name, sizeof(buff)); + if (zone_str != NULL) { + emit_event(KNOT_BUS_EVENT_ZONE_KSK_SUBM, "sqs", + VALUE_OF(zone_str), VALUE_OF(keytag), + VALUE_OF(keyid)); + } +#endif // ENABLE_DBUS +} + +void dbus_emit_zone_invalid(const knot_dname_t *zone_name, uint32_t remaining_secs) +{ +#if ENABLE_DBUS + knot_dname_txt_storage_t buff; + char *zone_str = knot_dname_to_str(buff, zone_name, sizeof(buff)); + if (zone_str != NULL) { + emit_event(KNOT_BUS_EVENT_ZONE_INVALID, "su", + VALUE_OF(zone_str), + VALUE_OF(remaining_secs)); + } +#endif // ENABLE_DBUS +} diff --git a/src/knot/common/dbus.h b/src/knot/common/dbus.h new file mode 100644 index 0000000..3a529f3 --- /dev/null +++ b/src/knot/common/dbus.h @@ -0,0 +1,86 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +/*! + * \brief D-Bus API wrappers. + */ + +#pragma once + +#include "libknot/libknot.h" + +#define KNOT_DBUS_NAME "cz.nic.knotd" +#define KNOT_DBUS_PATH "/cz/nic/knotd" + +#define KNOT_BUS_EVENT_STARTED "started" +#define KNOT_BUS_EVENT_STOPPED "stopped" +#define KNOT_BUS_EVENT_ZONE_UPD "zone_updated" +#define KNOT_BUS_EVENT_ZONE_KEYS_UPD "keys_updated" +#define KNOT_BUS_EVENT_ZONE_KSK_SUBM "zone_ksk_submission" +#define KNOT_BUS_EVENT_ZONE_INVALID "zone_dnssec_invalid" + +/*! + * \brief Creates unique D-Bus sender reference (common for whole process). + * + * \retval KNOT_EOK on successful create of reference. + * \retval Negative value on error. + */ +int dbus_open(void); + +/*! + * \brief Closes D-Bus. + */ +void dbus_close(void); + +/*! + * \brief Emit event signal for started daemon. + * + * \param up Indication if the server has been started. + */ +void dbus_emit_running(bool up); + +/*! + * \brief Emit event signal for updated zones. + * + * \param zone_name Zone name. + * \param serial Current zone SOA serial. + */ +void dbus_emit_zone_updated(const knot_dname_t *zone_name, uint32_t serial); + +/*! + * \brief Emit event signal for updated DNSSEC key set. + * + * \param zone_name Zone name. + */ +void dbus_emit_keys_updated(const knot_dname_t *zone_name); + +/*! + * \brief Emit event signal for KSK submission. + * + * \param zone_name Zone name. + * \param keytag Keytag of the ready key. + * \param keyid KASP id of the ready key. + */ +void dbus_emit_zone_submission(const knot_dname_t *zone_name, uint16_t keytag, + const char *keyid); + +/*! + * \brief Emit event signal for failed DNSSEC validation. + * + * \param zone_name Zone name. + * \param remaining_secs Remaining time until a RRSIG expires. + */ +void dbus_emit_zone_invalid(const knot_dname_t *zone_name, uint32_t remaining_secs); diff --git a/src/knot/common/fdset.c b/src/knot/common/fdset.c index a0a0212..2bf4113 100644 --- a/src/knot/common/fdset.c +++ b/src/knot/common/fdset.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,6 +35,7 @@ static int fdset_resize(fdset_t *set, const unsigned size) assert(set); MEM_RESIZE(set->ctx, size); + MEM_RESIZE(set->ctx2, size); MEM_RESIZE(set->timeout, size); #if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE) MEM_RESIZE(set->ev, size); @@ -80,6 +81,7 @@ void fdset_clear(fdset_t *set) } free(set->ctx); + free(set->ctx2); free(set->timeout); #if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE) free(set->ev); @@ -104,6 +106,7 @@ int fdset_add(fdset_t *set, const int fd, const fdset_event_t events, void *ctx) const int idx = set->n++; set->ctx[idx] = ctx; + set->ctx2[idx] = NULL; set->timeout[idx] = 0; #ifdef HAVE_EPOLL set->ev[idx].data.fd = fd; @@ -164,6 +167,7 @@ int fdset_remove(fdset_t *set, const unsigned idx) /* Nothing else if it is the last one. Move last -> i if some remain. */ if (idx < last) { set->ctx[idx] = set->ctx[last]; + set->ctx2[idx] = set->ctx2[last]; set->timeout[idx] = set->timeout[last]; #if defined(HAVE_EPOLL) || defined (HAVE_KQUEUE) set->ev[idx] = set->ev[last]; @@ -326,8 +330,7 @@ void fdset_sweep(fdset_t *set, const fdset_sweep_cb_t cb, void *data) while (idx < set->n) { /* Check sweep state, remove if requested. */ if (set->timeout[idx] > 0 && set->timeout[idx] <= now.tv_sec) { - const int fd = fdset_get_fd(set, idx); - if (cb(set, fd, data) == FDSET_SWEEP) { + if (cb(set, idx, data) == FDSET_SWEEP) { (void)fdset_remove(set, idx); continue; } diff --git a/src/knot/common/fdset.h b/src/knot/common/fdset.h index e0c3dbe..81ec7a8 100644 --- a/src/knot/common/fdset.h +++ b/src/knot/common/fdset.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,6 +45,7 @@ typedef struct { unsigned n; /*!< Active fds. */ unsigned size; /*!< Array size (allocated). */ void **ctx; /*!< Context for each fd. */ + void **ctx2; /*!< Another context for each fd. */ time_t *timeout; /*!< Timeout for each fd (seconds precision). */ #if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE) #ifdef HAVE_EPOLL @@ -270,6 +271,16 @@ inline static void *fdset_it_get_ctx(const fdset_it_t *it) return it->set->ctx[fdset_it_get_idx(it)]; } +/*! + * \brief Get a read/write pointer on (void *) second context. + */ +inline static void **fdset_ctx2(const fdset_t *set, const unsigned idx) +{ + assert(set && idx < set->n); + + return &set->ctx2[idx]; +} + /*! * \brief Move iterator on next received event. * diff --git a/src/knot/common/stats.c b/src/knot/common/stats.c index 79c0f23..da31e3d 100644 --- a/src/knot/common/stats.c +++ b/src/knot/common/stats.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,140 +24,168 @@ #include "knot/common/stats.h" #include "knot/common/log.h" #include "knot/nameserver/query_module.h" +#include "libknot/xdp.h" -struct { - bool active_dumper; - pthread_t dumper; - uint32_t timer; - server_t *server; -} stats = { 0 }; - -typedef struct { - FILE *fd; - const list_t *query_modules; - const knot_dname_t *zone; - unsigned threads; - int level; - bool zone_emitted; - bool zone_name_emitted; - bool module_emitted; -} dump_ctx_t; - -#define DUMP_STR(fd, level, name, ...) do { \ - fprintf(fd, "%-.*s"name":\n", level, " ", ##__VA_ARGS__); \ -} while (0) - -#define DUMP_CTR(fd, level, name, idx, val) do { \ - fprintf(fd, "%-.*s"name": %"PRIu64"\n", level, " ", idx, val); \ -} while (0) - -static uint64_t server_zone_count(server_t *server) +static uint64_t stats_get_counter(knot_atomic_uint64_t **stats_vals, uint32_t offset, + unsigned threads) { - return knot_zonedb_size(server->zone_db); + uint64_t res = 0; + for (unsigned i = 0; i < threads; i++) { + res += ATOMIC_GET(stats_vals[i][offset]); + } + return res; } -const stats_item_t server_stats[] = { - { "zone-count", { .server_val = server_zone_count } }, - { 0 } -}; - -static uint64_t zone_size(zone_t *zone) +int stats_xdp(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx) { - return zone->contents != NULL ? zone->contents->size : 0; +#ifdef ENABLE_XDP +#define DUMP(structure, item_name, avg) { \ + params.item_begin = true; \ + params.item = #item_name; \ + params.id = stats[0].if_name; \ + params.value = 0; \ + for (int j = 0; j < i->fd_xdp_count; j++) { \ + params.value += stats[j].structure.item_name; \ + } \ + if (avg) { \ + params.value /= i->fd_xdp_count; \ + } \ + int ret = fcn(¶ms, ctx); \ + if (ret != KNOT_EOK) { \ + return ret; \ + } \ } + stats_dump_params_t params = { .section = "xdp" }; -static uint64_t zone_max_ttl(zone_t *zone) -{ - return zone->contents != NULL ? zone->contents->max_ttl : 0; + if (ctx->section != NULL && strcasecmp(ctx->section, params.section) != 0) { + return KNOT_EOK; + } + + for (const iface_t *i = ctx->server->ifaces; + i != ctx->server->ifaces + ctx->server->n_ifaces; i++) { + if (i->fd_xdp_count == 0) { + continue; + } + knot_xdp_stats_t stats[i->fd_xdp_count]; + for (int j = 0; j < i->fd_xdp_count; j++) { + knot_xdp_socket_stats(i->xdp_sockets[j], &stats[j]); + } + + DUMP(socket, rx_dropped, false); + DUMP(socket, rx_invalid, false); + DUMP(socket, tx_invalid, false); + DUMP(socket, rx_full, false); + DUMP(socket, fq_empty, false); + DUMP(socket, tx_empty, false); + DUMP(rings, tx_busy, true); + DUMP(rings, fq_fill, true); + DUMP(rings, rx_fill, true); + DUMP(rings, tx_fill, true); + DUMP(rings, cq_fill, true); + } +#undef DUMP +#endif + return KNOT_EOK; } -const stats_item_t zone_contents_stats[] = { - { "size", { .zone_val = zone_size } }, - { "max-ttl", { .zone_val = zone_max_ttl } }, - { 0 } -}; +#define DUMP_VAL(params, it, val) { \ + (params).item = (it); \ + (params).value = (val); \ + int ret = fcn(&(params), ctx); \ + if (ret != KNOT_EOK) { \ + return ret; \ + } \ +} -uint64_t stats_get_counter(uint64_t **stats_vals, uint32_t offset, unsigned threads) +int stats_server(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx) { - uint64_t res = 0; - for (unsigned i = 0; i < threads; i++) { - res += ATOMIC_GET(stats_vals[i][offset]); + stats_dump_params_t params = { .section = "server" }; + + if (ctx->section != NULL && strcasecmp(ctx->section, params.section) != 0) { + return KNOT_EOK; } - return res; + + DUMP_VAL(params, "zone-count", knot_zonedb_size(ctx->server->zone_db)); + + return KNOT_EOK; } -static void dump_common(dump_ctx_t *ctx, knotd_mod_t *mod) +int stats_zone(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx) { - // Dump zone name. - if (ctx->zone != NULL) { - // Prevent from zone section override. - if (!ctx->zone_emitted) { - ctx->level = 0; - DUMP_STR(ctx->fd, ctx->level++, "zone"); - ctx->zone_emitted = true; - } + knot_dname_txt_storage_t zone; + stats_dump_params_t params = { .section = "zone", .zone = zone }; - if (!ctx->zone_name_emitted) { - ctx->level = 1; - knot_dname_txt_storage_t name; - if (knot_dname_to_str(name, ctx->zone, sizeof(name)) == NULL) { - return; - } - DUMP_STR(ctx->fd, ctx->level++, "\"%s\"", name); - ctx->zone_name_emitted = true; - } + if (ctx->section != NULL && strcasecmp(ctx->section, params.section) != 0) { + return KNOT_EOK; } - if (!ctx->module_emitted) { - DUMP_STR(ctx->fd, ctx->level++, "%s", mod->id->name + 1); - ctx->module_emitted = true; + assert(ctx->zone); + zone_contents_t *contents = ctx->zone->contents; + + if (knot_dname_to_str(zone, ctx->zone->name, sizeof(zone)) == NULL) { + return KNOT_EINVAL; } + + DUMP_VAL(params, "size", contents != NULL ? contents->size : 0); + DUMP_VAL(params, "max-ttl", contents != NULL ? contents->max_ttl : 0); + + return KNOT_EOK; } -static void dump_counter(dump_ctx_t *ctx, knotd_mod_t *mod, mod_ctr_t *ctr) +static int stats_counter(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx, + stats_dump_params_t *params, knotd_mod_t *mod, mod_ctr_t *ctr) { - uint64_t counter = stats_get_counter(mod->stats_vals, ctr->offset, ctx->threads); - if (counter == 0) { - // Skip empty counter. - return; - } + params->id = NULL; + params->value_pos = 0; - dump_common(ctx, mod); + uint64_t val = stats_get_counter(mod->stats_vals, ctr->offset, ctx->threads); - DUMP_CTR(ctx->fd, ctx->level, "%s", ctr->name, counter); + DUMP_VAL(*params, ctr->name, val); + + return KNOT_EOK; } -static void dump_counters(dump_ctx_t *ctx, knotd_mod_t *mod, mod_ctr_t *ctr) +static int stats_counters(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx, + stats_dump_params_t *params, knotd_mod_t *mod, mod_ctr_t *ctr) { - bool counter_emitted = false; - for (uint32_t j = 0; j < ctr->count; j++) { - uint64_t counter = stats_get_counter(mod->stats_vals, ctr->offset + j, ctx->threads); - if (counter == 0) { - // Skip empty counter. - continue; - } + char id[64]; + params->id = id; + params->value_pos = 0; + params->item_begin = true; - dump_common(ctx, mod); - - if (!counter_emitted) { - DUMP_STR(ctx->fd, ctx->level, "%s", ctr->name); - counter_emitted = true; - } + for (uint32_t i = 0; i < ctr->count; i++) { + uint64_t val = stats_get_counter(mod->stats_vals, ctr->offset + i, + ctx->threads); if (ctr->idx_to_str != NULL) { - char *str = ctr->idx_to_str(j, ctr->count); - if (str != NULL) { - DUMP_CTR(ctx->fd, ctx->level + 1, "%s", str, counter); - free(str); + char *str = ctr->idx_to_str(i, ctr->count); + if (str == NULL) { + continue; } + (void)snprintf(id, sizeof(id), "%s", str); + free(str); } else { - DUMP_CTR(ctx->fd, ctx->level + 1, "%u", j, counter); + (void)snprintf(id, sizeof(id), "%u", i); } + + DUMP_VAL(*params, ctr->name, val); + params->value_pos++; } + + params->id = NULL; + + return KNOT_EOK; } -static void dump_modules(dump_ctx_t *ctx) +int stats_modules(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx) { + if (ctx->section != NULL && strncasecmp(ctx->section, "mod-", strlen("mod-")) != 0) { + return KNOT_EOK; + } + + knot_dname_txt_storage_t zone; + stats_dump_params_t params = { 0 }; + knotd_mod_t *mod; WALK_LIST(mod, *ctx->query_modules) { // Skip modules without statistics. @@ -169,39 +197,114 @@ static void dump_modules(dump_ctx_t *ctx) ctx->threads = knotd_mod_threads(mod); } + params.section = mod->id->name + 1; + params.module_begin = true; + if (ctx->zone != NULL && params.zone == NULL) { + params.zone = knot_dname_to_str(zone, ctx->zone->name, + sizeof(zone)); + if (params.zone == NULL) { + return KNOT_EINVAL; + } + } + // Dump module counters. - ctx->module_emitted = false; for (int i = 0; i < mod->stats_count; i++) { mod_ctr_t *ctr = mod->stats_info + i; if (ctr->name == NULL) { // Empty counter. continue; } - if (ctr->count == 1) { - // Simple counter. - dump_counter(ctx, mod, ctr); - } else { - // Array of counters. - dump_counters(ctx, mod, ctr); + int ret = (ctr->count == 1) ? + stats_counter(fcn, ctx, ¶ms, mod, ctr) : + stats_counters(fcn, ctx, ¶ms, mod, ctr); + if (ret != KNOT_EOK) { + return ret; } } - if (ctx->module_emitted) { - ctx->level--; + } + + return KNOT_EOK; +} + +struct { + bool active_dumper; + pthread_t dumper; + uint32_t timer; + server_t *server; +} stats = { 0 }; + +typedef struct { + FILE *fd; + bool section_emitted; + bool zone_section_emitted; + bool zone_emitted; + bool id_emitted; +} dump_ctx_t; + +static int dump_ctr(stats_dump_params_t *params, stats_dump_ctx_t *dump_ctx) +{ + dump_ctx_t *ctx = dump_ctx->ctx; + + if (params->value == 0) { + return KNOT_EOK; + } + + const char *INDENT = " "; + unsigned indent = 0; + + if (params->zone != NULL) { + if (!ctx->zone_section_emitted) { + fprintf(ctx->fd, "zone:\n"); + ctx->zone_section_emitted = true; + } + + if (!ctx->zone_emitted) { + fprintf(ctx->fd, " \"%s\":\n", params->zone); + ctx->zone_emitted = true; } + indent += 2; } + + if (!ctx->section_emitted || params->module_begin) { + fprintf(ctx->fd, "%-.*s%s:\n", indent, INDENT, params->section); + ctx->section_emitted = true; + params->module_begin = false; + } + indent++; + + if (params->id != NULL) { + if (params->item_begin) { + fprintf(ctx->fd, "%-.*s%s:\n", indent, INDENT, params->item); + params->item_begin = false; + } + indent++; + fprintf(ctx->fd, "%-.*s%s: %"PRIu64"\n", indent, INDENT, + params->id, params->value); + } else { + fprintf(ctx->fd, "%-.*s%s: %"PRIu64"\n", indent, INDENT, + params->item, params->value); + } + + return KNOT_EOK; } -static void zone_stats_dump(zone_t *zone, dump_ctx_t *ctx) +static void zone_stats_dump(zone_t *zone, stats_dump_ctx_t *dump_ctx) { if (EMPTY_LIST(zone->query_modules)) { return; } - ctx->query_modules = &zone->query_modules; - ctx->zone = zone->name; - ctx->zone_name_emitted = false; + // Reset per-zone context. + dump_ctx_t *ctx = dump_ctx->ctx; + *ctx = (dump_ctx_t){ + .fd = ctx->fd, + .zone_section_emitted = ctx->zone_section_emitted, + }; + + dump_ctx->zone = zone; + dump_ctx->query_modules = &zone->query_modules; - dump_modules(ctx); + (void)stats_modules(dump_ctr, dump_ctx); } static void dump_to_file(conf_t *conf, FILE *fd, server_t *server) @@ -224,22 +327,28 @@ static void dump_to_file(conf_t *conf, FILE *fd, server_t *server) "identity: %s\n", date, ident); - dump_ctx_t ctx = { - .fd = fd, + dump_ctx_t ctx = { .fd = fd }; + + stats_dump_ctx_t dump_ctx = { + .server = server, .query_modules = conf->query_modules, + .ctx = &ctx, }; - // Dump server statistics. - DUMP_STR(ctx.fd, ctx.level, "server"); - for (const stats_item_t *item = server_stats; item->name != NULL; item++) { - DUMP_CTR(ctx.fd, ctx.level + 1, "%s", item->name, item->server_val(server)); - } + // Dump server counters. + (void)stats_server(dump_ctr, &dump_ctx); + + // Dump XDP counters. + ctx = (dump_ctx_t){ .fd = fd }; + (void)stats_xdp(dump_ctr, &dump_ctx); - // Dump global statistics. - dump_modules(&ctx); + // Dump global module counters. + ctx = (dump_ctx_t){ .fd = fd }; + (void)stats_modules(dump_ctr, &dump_ctx); - // Dump zone statistics. - knot_zonedb_foreach(server->zone_db, zone_stats_dump, &ctx); + // Dump per zone module counters (fixed zone counters not included). + ctx = (dump_ctx_t){ .fd = fd }; + knot_zonedb_foreach(server->zone_db, zone_stats_dump, &dump_ctx); } static void dump_stats(server_t *server) @@ -321,7 +430,6 @@ void stats_reconfigure(conf_t *conf, server_t *server) return; } - // Update server context. stats.server = server; conf_val_t val = conf_get(conf, C_STATS, C_TIMER); diff --git a/src/knot/common/stats.h b/src/knot/common/stats.h index 5cb51ca..4391178 100644 --- a/src/knot/common/stats.h +++ b/src/knot/common/stats.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,36 +20,65 @@ #pragma once +#include "contrib/atomic.h" #include "knot/server/server.h" -typedef uint64_t (*stats_server_val_f)(server_t *server); -typedef uint64_t (*stats_zone_val_f)(zone_t *zone); +/*! + * \brief Parameters for a statistic metric dump callback. + */ +typedef struct { + const char *section; + const char *item; + const char *id; + const char *zone; + uint64_t value; + unsigned value_pos; // Counted from 0. + + bool module_begin; // Indication of a new module. + bool item_begin; // Indication of a new item. +} stats_dump_params_t; /*! - * \brief Statistics metrics item. + * \brief Statistic metric context. */ typedef struct { - const char *name; /*!< Metrics name. */ - union { - stats_server_val_f server_val; /*!< Server metrics value getter. */ - stats_zone_val_f zone_val; /*!< Zone metrics value getter. */ - }; -} stats_item_t; + server_t *server; + zone_t *zone; + const list_t *query_modules; + + const char *section; // Optional section specification. + const char *item; // Optional item specification. + bool match; // Indication of non-empty [[section[.item]] selection. + + unsigned threads; // Internal cache for the number of workers. + + void *ctx; +} stats_dump_ctx_t; + +/*! + * \brief Statistic metric dump callback. + */ +typedef int (*stats_dump_ctr_f)(stats_dump_params_t *, stats_dump_ctx_t *); + +/*! + * \brief XDP metrics. + */ +int stats_xdp(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx); /*! - * \brief Basic server metrics. + * \brief Server metrics. */ -extern const stats_item_t server_stats[]; +int stats_server(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx); /*! - * \brief Basic zone metrics. + * \brief Zone metrics. */ -extern const stats_item_t zone_contents_stats[]; +int stats_zone(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx); /*! - * \brief Read out value of single counter summed across threads. + * \brief Modules metrics. */ -uint64_t stats_get_counter(uint64_t **stats_vals, uint32_t offset, unsigned threads); +int stats_modules(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx); /*! * \brief Reconfigures the statistics facility. diff --git a/src/knot/common/systemd.c b/src/knot/common/systemd.c index 5a72fb4..3f9d9a6 100644 --- a/src/knot/common/systemd.c +++ b/src/knot/common/systemd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,8 +14,6 @@ along with this program. If not, see . */ -#include -#include #include #include "knot/common/systemd.h" @@ -43,12 +41,6 @@ static int systemd_zone_load_timeout(void) } #endif -#ifdef ENABLE_DBUS -#include - -static sd_bus *_dbus = NULL; -#endif - void systemd_zone_load_timeout_notify(void) { #ifdef ENABLE_SYSTEMD @@ -92,91 +84,3 @@ void systemd_stopping_notify(void) sd_notify(0, "STOPPING=1\nSTATUS="); #endif } - -int systemd_dbus_open(void) -{ -#ifdef ENABLE_DBUS - if (_dbus != NULL) { - return KNOT_EOK; - } - - int ret = sd_bus_open_system(&_dbus); - if (ret < 0) { - return ret; - } - - /* Take a well-known service name so that clients can find us. */ - ret = sd_bus_request_name(_dbus, KNOT_DBUS_NAME, 0); - if (ret < 0) { - systemd_dbus_close(); - return ret; - } - - return KNOT_EOK; -#else - return KNOT_ENOTSUP; -#endif -} - -void systemd_dbus_close(void) -{ -#ifdef ENABLE_DBUS - _dbus = sd_bus_unref(_dbus); -#endif -} - -#define emit_event(event, ...) \ - sd_bus_emit_signal(_dbus, KNOT_DBUS_PATH, KNOT_DBUS_NAME".events", \ - event, __VA_ARGS__) - -void systemd_emit_running(bool up) -{ -#ifdef ENABLE_DBUS - emit_event(up ? KNOT_BUS_EVENT_STARTED : KNOT_BUS_EVENT_STOPPED, ""); -#endif -} - -void systemd_emit_zone_updated(const knot_dname_t *zone_name, uint32_t serial) -{ -#ifdef ENABLE_DBUS - knot_dname_txt_storage_t buff; - char *zone_str = knot_dname_to_str(buff, zone_name, sizeof(buff)); - if (zone_str != NULL) { - emit_event(KNOT_BUS_EVENT_ZONE_UPD, "su", zone_str, serial); - } -#endif -} - -void systemd_emit_keys_updated(const knot_dname_t *zone_name) -{ -#ifdef ENABLE_DBUS - knot_dname_txt_storage_t buff; - char *zone_str = knot_dname_to_str(buff, zone_name, sizeof(buff)); - if (zone_str != NULL) { - emit_event(KNOT_BUS_EVENT_ZONE_KEYS_UPD, "s", zone_str); - } -#endif -} - -void systemd_emit_zone_submission(const knot_dname_t *zone_name, uint16_t keytag, - const char *keyid) -{ -#ifdef ENABLE_DBUS - knot_dname_txt_storage_t buff; - char *zone_str = knot_dname_to_str(buff, zone_name, sizeof(buff)); - if (zone_str != NULL) { - emit_event(KNOT_BUS_EVENT_ZONE_KSK_SUBM, "sqs", zone_str, keytag, keyid); - } -#endif -} - -void systemd_emit_zone_invalid(const knot_dname_t *zone_name) -{ -#ifdef ENABLE_DBUS - knot_dname_txt_storage_t buff; - char *zone_str = knot_dname_to_str(buff, zone_name, sizeof(buff)); - if (zone_str != NULL) { - emit_event(KNOT_BUS_EVENT_ZONE_INVALID, "s", zone_str); - } -#endif -} diff --git a/src/knot/common/systemd.h b/src/knot/common/systemd.h index c6fe260..2038e94 100644 --- a/src/knot/common/systemd.h +++ b/src/knot/common/systemd.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,18 +20,6 @@ #pragma once -#include "libknot/libknot.h" - -#define KNOT_DBUS_NAME "cz.nic.knotd" -#define KNOT_DBUS_PATH "/cz/nic/knotd" - -#define KNOT_BUS_EVENT_STARTED "started" -#define KNOT_BUS_EVENT_STOPPED "stopped" -#define KNOT_BUS_EVENT_ZONE_UPD "zone_updated" -#define KNOT_BUS_EVENT_ZONE_KEYS_UPD "keys_updated" -#define KNOT_BUS_EVENT_ZONE_KSK_SUBM "zone_ksk_submission" -#define KNOT_BUS_EVENT_ZONE_INVALID "zone_dnssec_invalid" - /*! * \brief Notify systemd about zone loading start. */ @@ -59,55 +47,3 @@ void systemd_reloading_notify(void); * \brief Notify systemd about service is stopping. */ void systemd_stopping_notify(void); - -/*! - * \brief Creates unique D-Bus sender reference (common for whole process). - * - * \retval KNOT_EOK on successful create of reference. - * \retval Negative value on error. - */ -int systemd_dbus_open(void); - -/*! - * \brief Closes D-Bus. - */ -void systemd_dbus_close(void); - -/*! - * \brief Emit event signal for started daemon. - * - * \param up Indication if the server has been started. - */ -void systemd_emit_running(bool up); - -/*! - * \brief Emit event signal for updated zones. - * - * \param zone_name Zone name. - * \param serial Current zone SOA serial. - */ -void systemd_emit_zone_updated(const knot_dname_t *zone_name, uint32_t serial); - -/*! - * \brief Emit event signal for updated DNSSEC key set. - * - * \param zone_name Zone name. - */ -void systemd_emit_keys_updated(const knot_dname_t *zone_name); - -/*! - * \brief Emit event signal for KSK submission. - * - * \param zone_name Zone name. - * \param keytag Keytag of the ready key. - * \param keyid KASP id of the ready key. - */ -void systemd_emit_zone_submission(const knot_dname_t *zone_name, uint16_t keytag, - const char *keyid); - -/*! - * \brief Emit event signal for failed DNSSEC validation. - * - * \param zone_name Zone name. - */ -void systemd_emit_zone_invalid(const knot_dname_t *zone_name); diff --git a/src/knot/conf/base.c b/src/knot/conf/base.c index 51caf10..4683171 100644 --- a/src/knot/conf/base.c +++ b/src/knot/conf/base.c @@ -130,6 +130,9 @@ static void init_cache( static bool running_xdp_tcp; static uint16_t running_xdp_quic; static bool running_route_check; + static uint16_t running_ring_size; + static uint16_t running_busypoll_budget; + static uint16_t running_busypoll_timeout; static size_t running_udp_threads; static size_t running_tcp_threads; static size_t running_xdp_threads; @@ -148,6 +151,9 @@ static void init_cache( running_xdp_quic = conf_get_int(conf, C_XDP, C_QUIC_PORT); } running_route_check = conf_get_bool(conf, C_XDP, C_ROUTE_CHECK); + running_ring_size = conf_get_int(conf, C_XDP, C_RING_SIZE); + running_busypoll_budget = conf_get_int(conf, C_XDP, C_BUSYPOLL_BUDGET); + running_busypoll_timeout = conf_get_int(conf, C_XDP, C_BUSYPOLL_TIMEOUT); running_udp_threads = conf_udp_threads(conf); running_tcp_threads = conf_tcp_threads(conf); running_xdp_threads = conf_xdp_threads(conf); @@ -235,6 +241,12 @@ static void init_cache( conf->cache.xdp_route_check = running_route_check; + conf->cache.xdp_ring_size = running_ring_size; + + conf->cache.xdp_busypoll_budget = running_busypoll_budget; + + conf->cache.xdp_busypoll_timeout = running_busypoll_timeout; + val = conf_get(conf, C_CTL, C_TIMEOUT); conf->cache.ctl_timeout = conf_int(&val) * 1000; /* infinite_adjust() call isn't needed, 0 is adjusted later anyway. */ @@ -335,9 +347,10 @@ int conf_new( ret = out->api->init(&out->db, NULL, &lmdb_opts); // Remove the database to ensure it is temporary. - if (!remove_path(lmdb_opts.path)) { - CONF_LOG(LOG_WARNING, "failed to purge temporary directory '%s'", - lmdb_opts.path); + int ret2 = remove_path(lmdb_opts.path, false); + if (ret2 != KNOT_EOK) { + CONF_LOG(LOG_WARNING, "failed to purge temporary directory '%s' (%s)", + lmdb_opts.path, knot_strerror(ret2)); } } else { // Set the specified database. diff --git a/src/knot/conf/base.h b/src/knot/conf/base.h index 5c77cac..1ac5ef5 100644 --- a/src/knot/conf/base.h +++ b/src/knot/conf/base.h @@ -165,6 +165,9 @@ typedef struct { const char *srv_version; uint32_t srv_quic_idle_close; uint16_t xdp_quic; + uint16_t xdp_ring_size; + uint16_t xdp_busypoll_budget; + uint16_t xdp_busypoll_timeout; int ctl_timeout; bool xdp_udp; bool xdp_tcp; diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c index 55ee971..5e9ed83 100644 --- a/src/knot/conf/conf.c +++ b/src/knot/conf/conf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -606,8 +606,9 @@ void conf_mix_iter_next( } } -int64_t conf_int( - conf_val_t *val) +int64_t conf_int_alt( + conf_val_t *val, + bool alternative) { assert(val != NULL && val->item != NULL); assert(val->item->type == YP_TINT || @@ -618,7 +619,7 @@ int64_t conf_int( conf_val(val); return yp_int(val->data); } else { - return val->item->var.i.dflt; + return alternative ? val->item->var.i.dflt_alt : val->item->var.i.dflt; } } @@ -1063,7 +1064,7 @@ static int str_label( size_t index = labels - right_index - 1; // Create a dname from the single label. - size_t prefix_len = knot_dname_prefixlen(zone, index, NULL); + size_t prefix_len = knot_dname_prefixlen(zone, index); size_t label_len = *(zone + prefix_len); memcpy(label, zone + prefix_len, 1 + label_len); label[1 + label_len] = '\0'; @@ -1379,6 +1380,8 @@ conf_remote_t conf_remote_txn( conf_val_t val = conf_id_get_txn(conf, txn, C_RMT, C_QUIC, id); out.quic = conf_bool(&val); + val = conf_id_get_txn(conf, txn, C_RMT, C_TLS, id); + out.tls = conf_bool(&val); conf_val_t rundir_val = conf_get_txn(conf, txn, C_SRV, C_RUNDIR); char *rundir = conf_abs_path(&rundir_val, NULL); @@ -1398,7 +1401,7 @@ conf_remote_t conf_remote_txn( conf_val_next(&val); } // Index overflow causes empty socket. - out.addr = conf_addr_alt(&val, rundir, out.quic); + out.addr = conf_addr_alt(&val, rundir, out.quic || out.tls); // Get outgoing address if family matches (optional). uint16_t via_pos = 0; diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h index 562722d..f79a284 100644 --- a/src/knot/conf/conf.h +++ b/src/knot/conf/conf.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,6 +44,8 @@ typedef struct { struct sockaddr_storage via; /*! QUIC context. */ bool quic; + /*! TLS context. */ + bool tls; /*! TSIG key. */ knot_tsig_key_t key; /*! Suppress sending NOTIFY after zone transfer from this master. */ @@ -469,13 +471,20 @@ void conf_mix_iter_next( /*! * Gets the numeric value of the item. * - * \param[in] val Item value. + * \param[in] val Item value. + * \param[in] alternative Use alternative default value. * * \return Integer. */ -int64_t conf_int( - conf_val_t *val +int64_t conf_int_alt( + conf_val_t *val, + bool alternative ); +inline static int64_t conf_int( + conf_val_t *val) +{ + return conf_int_alt(val, false); +} /*! * Gets the boolean value of the item. diff --git a/src/knot/conf/schema.c b/src/knot/conf/schema.c index 7b30a2f..fd55fc8 100644 --- a/src/knot/conf/schema.c +++ b/src/knot/conf/schema.c @@ -64,9 +64,7 @@ static const knot_lookup_t dnssec_key_algs[] = { { DNSSEC_KEY_ALGORITHM_RSA_SHA512, "rsasha512" }, { DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256, "ecdsap256sha256" }, { DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384, "ecdsap384sha384" }, -#ifdef HAVE_ED25519 { DNSSEC_KEY_ALGORITHM_ED25519, "ed25519" }, -#endif #ifdef HAVE_ED448 { DNSSEC_KEY_ALGORITHM_ED448, "ed448" }, #endif @@ -249,15 +247,8 @@ static const yp_item_t desc_server[] = { { C_DBUS_INIT_DELAY, YP_TINT, YP_VINT = { 0, INT32_MAX, 1, YP_STIME } }, { C_LISTEN, YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI, { check_listen } }, { C_LISTEN_QUIC, YP_TADDR, YP_VADDR = { 853 }, YP_FMULTI, { check_listen } }, + { C_LISTEN_TLS, YP_TADDR, YP_VADDR = { 853 }, YP_FMULTI, { check_listen } }, { C_COMMENT, YP_TSTR, YP_VNONE }, - // Legacy items. - { C_LISTEN_XDP, YP_TADDR, YP_VADDR = { 0 }, YP_FMULTI, { legacy_item } }, - { C_MAX_TCP_CLIENTS, YP_TINT, YP_VINT = { 0, INT32_MAX, 0 }, YP_FNONE, { legacy_item } }, - { C_TCP_HSHAKE_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX, 0, YP_STIME }, YP_FNONE, { legacy_item } }, - { C_TCP_REPLY_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX, 0, YP_STIME }, YP_FNONE, { legacy_item } }, - { C_MAX_UDP_PAYLOAD, YP_TINT, YP_VINT = { 0, INT32_MAX, 0, YP_SSIZE }, YP_FNONE, { legacy_item } }, - { C_MAX_IPV4_UDP_PAYLOAD, YP_TINT, YP_VINT = { 0, INT32_MAX, 0, YP_SSIZE }, YP_FNONE, { legacy_item } }, - { C_MAX_IPV6_UDP_PAYLOAD, YP_TINT, YP_VINT = { 0, INT32_MAX, 0, YP_SSIZE }, YP_FNONE, { legacy_item } }, { NULL } }; @@ -274,10 +265,10 @@ static const yp_item_t desc_xdp[] = { { C_TCP_IDLE_RESET, YP_TINT, YP_VINT = { 1, INT32_MAX, 20, YP_STIME } }, { C_TCP_RESEND, YP_TINT, YP_VINT = { 1, INT32_MAX, 5, YP_STIME } }, { C_ROUTE_CHECK, YP_TBOOL, YP_VNONE }, - { C_EXTRA_FRAMES, YP_TBOOL, YP_VNONE }, + { C_RING_SIZE, YP_TINT, YP_VINT = { 4, 32768, 2048 } }, + { C_BUSYPOLL_BUDGET, YP_TINT, YP_VINT = { 0, UINT16_MAX, 0 } }, + { C_BUSYPOLL_TIMEOUT, YP_TINT, YP_VINT = { 1, UINT16_MAX, 20 } }, { C_COMMENT, YP_TSTR, YP_VNONE }, - // Legacy items. - { C_QUIC_LOG, YP_TBOOL, YP_VNONE, YP_FNONE, { legacy_item } }, { NULL } }; @@ -350,6 +341,7 @@ static const yp_item_t desc_remote[] = { { C_ADDR, YP_TADDR, YP_VADDR = { 53, 853 }, YP_FMULTI }, { C_VIA, YP_TADDR, YP_VNONE, YP_FMULTI }, { C_QUIC, YP_TBOOL, YP_VNONE }, + { C_TLS, YP_TBOOL, YP_VNONE }, { C_KEY, YP_TREF, YP_VREF = { C_KEY }, YP_FNONE, { check_ref } }, { C_CERT_KEY, YP_TB64, YP_VNONE, YP_FMULTI, { check_cert_pin } }, { C_BLOCK_NOTIFY_XFR, YP_TBOOL, YP_VNONE }, @@ -432,7 +424,7 @@ static const yp_item_t desc_policy[] = { CONF_IO_FRLD_ZONES }, { C_RRSIG_REFRESH, YP_TINT, YP_VINT = { 1, INT32_MAX, YP_NIL, YP_STIME }, CONF_IO_FRLD_ZONES }, - { C_RRSIG_PREREFRESH, YP_TINT, YP_VINT = { 0, INT32_MAX, HOURS(1), YP_STIME }, + { C_RRSIG_PREREFRESH, YP_TINT, YP_VINT = { 0, INT32_MAX, HOURS(1), YP_STIME, DAYS(1) }, CONF_IO_FRLD_ZONES }, { C_REPRO_SIGNING, YP_TBOOL, YP_VNONE, CONF_IO_FRLD_ZONES }, { C_NSEC3, YP_TBOOL, YP_VNONE, CONF_IO_FRLD_ZONES }, @@ -506,27 +498,12 @@ static const yp_item_t desc_policy[] = { { C_MODULE, YP_TDATA, YP_VDATA = { 0, NULL, mod_id_to_bin, mod_id_to_txt }, \ YP_FMULTI | FLAGS, { check_modref } }, \ { C_COMMENT, YP_TSTR, YP_VNONE }, \ - /* Legacy items.*/ \ - { C_DISABLE_ANY, YP_TBOOL, YP_VNONE, YP_FNONE, { legacy_item } }, \ - { C_MAX_ZONE_SIZE, YP_TINT, YP_VINT = { 0, SSIZE_MAX, 0, YP_SSIZE }, YP_FNONE, { legacy_item } }, \ - { C_MAX_JOURNAL_USAGE, YP_TINT, YP_VINT = { 0, SSIZE_MAX, 0, YP_SSIZE }, YP_FNONE, { legacy_item } }, \ - { C_MAX_JOURNAL_DEPTH, YP_TINT, YP_VINT = { 0, SSIZE_MAX, 0 }, YP_FNONE, { legacy_item } }, \ - { C_MAX_REFRESH_INTERVAL,YP_TINT, YP_VINT = { 0, SSIZE_MAX, 0, YP_STIME }, YP_FNONE, { legacy_item } }, \ - { C_MIN_REFRESH_INTERVAL,YP_TINT, YP_VINT = { 0, SSIZE_MAX, 0, YP_STIME }, YP_FNONE, { legacy_item } }, \ static const yp_item_t desc_template[] = { { C_ID, YP_TSTR, YP_VNONE, CONF_IO_FREF }, { C_GLOBAL_MODULE, YP_TDATA, YP_VDATA = { 0, NULL, mod_id_to_bin, mod_id_to_txt }, YP_FMULTI | CONF_IO_FRLD_MOD, { check_modref } }, ZONE_ITEMS(CONF_IO_FRLD_ZONES) - // Legacy items. - { C_TIMER_DB, YP_TSTR, YP_VSTR = { "" }, YP_FNONE, { legacy_item } }, - { C_MAX_TIMER_DB_SIZE, YP_TINT, YP_VINT = { 0, SSIZE_MAX, 0, YP_SSIZE }, YP_FNONE, { legacy_item } }, - { C_JOURNAL_DB, YP_TSTR, YP_VSTR = { "" }, YP_FNONE, { legacy_item } }, - { C_JOURNAL_DB_MODE, YP_TOPT, YP_VOPT = { journal_modes, 0 }, YP_FNONE, { legacy_item } }, - { C_MAX_JOURNAL_DB_SIZE, YP_TINT, YP_VINT = { 0, SSIZE_MAX, 0, YP_SSIZE }, YP_FNONE, { legacy_item } }, - { C_KASP_DB, YP_TSTR, YP_VSTR = { "" }, YP_FNONE, { legacy_item } }, - { C_MAX_KASP_DB_SIZE, YP_TINT, YP_VINT = { 0, SSIZE_MAX, 0, YP_SSIZE }, YP_FNONE, { legacy_item } }, { NULL } }; diff --git a/src/knot/conf/schema.h b/src/knot/conf/schema.h index dc5a04e..d2966e6 100644 --- a/src/knot/conf/schema.h +++ b/src/knot/conf/schema.h @@ -33,6 +33,8 @@ #define C_BACKLOG "\x07""backlog" #define C_BG_WORKERS "\x12""background-workers" #define C_BLOCK_NOTIFY_XFR "\x1B""block-notify-after-transfer" +#define C_BUSYPOLL_BUDGET "\x0F""busypoll-budget" +#define C_BUSYPOLL_TIMEOUT "\x10""busypoll-timeout" #define C_CATALOG_DB "\x0A""catalog-db" #define C_CATALOG_DB_MAX_SIZE "\x13""catalog-db-max-size" #define C_CATALOG_GROUP "\x0D""catalog-group" @@ -65,7 +67,6 @@ #define C_ECS "\x12""edns-client-subnet" #define C_EXPIRE_MAX_INTERVAL "\x13""expire-max-interval" #define C_EXPIRE_MIN_INTERVAL "\x13""expire-min-interval" -#define C_EXTRA_FRAMES "\x0C""extra-frames" #define C_FILE "\x04""file" #define C_GLOBAL_MODULE "\x0D""global-module" #define C_ID "\x02""id" @@ -94,6 +95,7 @@ #define C_KSK_SIZE "\x08""ksk-size" #define C_LISTEN "\x06""listen" #define C_LISTEN_QUIC "\x0B""listen-quic" +#define C_LISTEN_TLS "\x0A""listen-tls" #define C_LOG "\x03""log" #define C_MANUAL "\x06""manual" #define C_MASTER "\x06""master" @@ -117,7 +119,6 @@ #define C_PROXY_ALLOWLIST "\x0F""proxy-allowlist" #define C_QUIC "\x04""quic" #define C_QUIC_IDLE_CLOSE "\x17""quic-idle-close-timeout" -#define C_QUIC_LOG "\x08""quic-log" #define C_QUIC_MAX_CLIENTS "\x10""quic-max-clients" #define C_QUIC_OUTBUF_MAX_SIZE "\x14""quic-outbuf-max-size" #define C_QUIC_PORT "\x09""quic-port" @@ -127,6 +128,7 @@ #define C_RETRY_MAX_INTERVAL "\x12""retry-max-interval" #define C_RETRY_MIN_INTERVAL "\x12""retry-min-interval" #define C_REVERSE_GEN "\x10""reverse-generate" +#define C_RING_SIZE "\x09""ring-size" #define C_RMT "\x06""remote" #define C_RMTS "\x07""remotes" #define C_RMT_POOL_LIMIT "\x11""remote-pool-limit" @@ -167,6 +169,7 @@ #define C_TIMER "\x05""timer" #define C_TIMER_DB "\x08""timer-db" #define C_TIMER_DB_MAX_SIZE "\x11""timer-db-max-size" +#define C_TLS "\x03""tls" #define C_TPL "\x08""template" #define C_UDP "\x03""udp" #define C_UDP_MAX_PAYLOAD "\x0F""udp-max-payload" @@ -192,24 +195,6 @@ #define C_ZSK_LIFETIME "\x0C""zsk-lifetime" #define C_ZSK_SIZE "\x08""zsk-size" -// Legacy items. -#define C_DISABLE_ANY "\x0B""disable-any" -#define C_LISTEN_XDP "\x0A""listen-xdp" -#define C_MAX_TIMER_DB_SIZE "\x11""max-timer-db-size" -#define C_MAX_JOURNAL_DB_SIZE "\x13""max-journal-db-size" -#define C_MAX_KASP_DB_SIZE "\x10""max-kasp-db-size" -#define C_TCP_HSHAKE_TIMEOUT "\x15""tcp-handshake-timeout" -#define C_TCP_REPLY_TIMEOUT "\x11""tcp-reply-timeout" -#define C_MAX_TCP_CLIENTS "\x0F""max-tcp-clients" -#define C_MAX_UDP_PAYLOAD "\x0F""max-udp-payload" -#define C_MAX_IPV4_UDP_PAYLOAD "\x14""max-ipv4-udp-payload" -#define C_MAX_IPV6_UDP_PAYLOAD "\x14""max-ipv6-udp-payload" -#define C_MAX_ZONE_SIZE "\x0D""max-zone-size" -#define C_MAX_REFRESH_INTERVAL "\x14""max-refresh-interval" -#define C_MIN_REFRESH_INTERVAL "\x14""min-refresh-interval" -#define C_MAX_JOURNAL_DEPTH "\x11""max-journal-depth" -#define C_MAX_JOURNAL_USAGE "\x11""max-journal-usage" - enum { KEYSTORE_BACKEND_PEM = 1, KEYSTORE_BACKEND_PKCS11 = 2, diff --git a/src/knot/conf/tools.c b/src/knot/conf/tools.c index e232fba..1ea8446 100644 --- a/src/knot/conf/tools.c +++ b/src/knot/conf/tools.c @@ -43,9 +43,7 @@ #include "knot/updates/acl.h" #include "knot/zone/serial.h" #include "libknot/errcode.h" -#ifdef ENABLE_QUIC -#include "libknot/quic/quic.h" -#endif // ENABLE_QUIC +#include "libknot/quic/tls_common.h" #include "libknot/yparser/yptrafo.h" #include "libknot/xdp.h" #include "contrib/files.h" @@ -345,15 +343,13 @@ int check_xdp_listen( int check_cert_pin( knotd_conf_check_args_t *args) { -#ifdef ENABLE_QUIC - if (args->data_len != sizeof(uint16_t) + KNOT_QUIC_PIN_LEN) { + if (args->data_len != sizeof(uint16_t) + KNOT_TLS_PIN_LEN) { (void)snprintf(check_str, sizeof(check_str), "invalid certificate pin, expected base64-encoded " - "%u bytes", KNOT_QUIC_PIN_LEN); + "%u bytes", KNOT_TLS_PIN_LEN); args->err_str = check_str; return KNOT_EINVAL; } -#endif // ENABLE_QUIC return KNOT_EOK; } @@ -551,7 +547,6 @@ static void check_mtu(knotd_conf_check_args_t *args, conf_val_t *xdp_listen) #endif } -#ifdef ENABLE_QUIC static bool listen_hit(const struct sockaddr_storage *ss1, const struct sockaddr_storage *ss2) { @@ -562,7 +557,33 @@ static bool listen_hit(const struct sockaddr_storage *ss1, return sockaddr_cmp(ss1, ss2, false) == 0; } } -#endif // ENABLE_QUIC + +static bool listen_overlaps( + knotd_conf_check_args_t *args, + conf_val_t *chk_listen, + size_t chk_listen_count) +{ + conf_val_t listen_val = conf_get_txn(args->extra->conf, args->extra->txn, + C_SRV, C_LISTEN); + size_t listen_count = conf_val_count(&listen_val); + + for (size_t i = 0; listen_count > 0 && i < chk_listen_count; i++) { + struct sockaddr_storage chk_addr = conf_addr(chk_listen, NULL); + + for (size_t j = 0; j < listen_count; j++) { + struct sockaddr_storage listen_addr = conf_addr(&listen_val, NULL); + if (listen_hit(&chk_addr, &listen_addr)) { + return true; + } + conf_val_next(&listen_val); + } + + conf_val(&listen_val); + conf_val_next(chk_listen); + } + + return false; +} int check_server( knotd_conf_check_args_t *args) @@ -576,30 +597,26 @@ int check_server( return KNOT_EINVAL; } + conf_val_t listls_val = conf_get_txn(args->extra->conf, args->extra->txn, + C_SRV, C_LISTEN_TLS); + size_t listls_count = conf_val_count(&listls_val); + if (listls_count > 0) { + if (listen_overlaps(args, &listls_val, listls_count)) { + args->err_str = "TLS listen address/port overlaps " + "with TCP listen address/port"; + return KNOT_EINVAL; + } + } + conf_val_t liquic_val = conf_get_txn(args->extra->conf, args->extra->txn, C_SRV, C_LISTEN_QUIC); size_t liquic_count = conf_val_count(&liquic_val); if (liquic_count > 0) { #ifdef ENABLE_QUIC - conf_val_t listen_val = conf_get_txn(args->extra->conf, args->extra->txn, - C_SRV, C_LISTEN); - size_t listen_count = conf_val_count(&listen_val); - - for (size_t i = 0; listen_count > 0 && i < liquic_count; i++) { - struct sockaddr_storage liquic_addr = conf_addr(&liquic_val, NULL); - - for (size_t j = 0; j < listen_count; j++) { - struct sockaddr_storage listen_addr = conf_addr(&listen_val, NULL); - if (listen_hit(&liquic_addr, &listen_addr)) { - args->err_str = "QUIC listen address/port overlaps " - "with UDP listen address/port"; - return KNOT_EINVAL; - } - conf_val_next(&listen_val); - } - - conf_val(&listen_val); - conf_val_next(&liquic_val); + if (listen_overlaps(args, &liquic_val, liquic_count)) { + args->err_str = "QUIC listen address/port overlaps " + "with UDP listen address/port"; + return KNOT_EINVAL; } #else args->err_str = "QUIC processing not available"; @@ -713,10 +730,6 @@ int check_policy( C_NSEC3_ITER, args->id, args->id_len); unsigned algorithm = conf_opt(&alg); - if (algorithm < DNSSEC_KEY_ALGORITHM_RSA_SHA256) { - CONF_LOG(LOG_NOTICE, "algorithm %u is deprecated and shouldn't be used for DNSSEC signing", - algorithm); - } int64_t ksk_size = conf_int(&ksk); if (ksk_size != YP_NIL && !dnssec_algorithm_key_size_check(algorithm, ksk_size)) { @@ -779,14 +792,6 @@ int check_policy( return KNOT_EINVAL; } -#ifndef HAVE_GNUTLS_REPRODUCIBLE - conf_val_t repro_sign = conf_rawid_get_txn(args->extra->conf, args->extra->txn, C_POLICY, - C_REPRO_SIGNING, args->id, args->id_len); - if (conf_bool(&repro_sign)) { - CONF_LOG(LOG_WARNING, "reproducible signing not available, signing normally"); - } -#endif - if (conf_bool(&nsec3)) { uint16_t iters = conf_int(&nsec3_iters); if (iters > 0) { @@ -880,12 +885,18 @@ int check_remote( return KNOT_EINVAL; } + conf_val_t tls = conf_rawid_get_txn(args->extra->conf, args->extra->txn, C_RMT, + C_TLS, args->id, args->id_len); conf_val_t quic = conf_rawid_get_txn(args->extra->conf, args->extra->txn, C_RMT, C_QUIC, args->id, args->id_len); if (quic.code == KNOT_EOK) { #ifdef ENABLE_QUIC - (void)0; + if (conf_bool(&quic) && conf_bool(&tls)) { + args->err_str = "remote can't use both QUIC and TLS"; + return KNOT_EINVAL; + } #else + (void)tls; args->err_str = "QUIC not available"; return KNOT_EINVAL; #endif diff --git a/src/knot/ctl/commands.c b/src/knot/ctl/commands.c index 7febce1..56e1d67 100644 --- a/src/knot/ctl/commands.c +++ b/src/knot/ctl/commands.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,12 +17,14 @@ #include #include #include +#include #include #include "knot/common/log.h" #include "knot/common/stats.h" #include "knot/conf/confio.h" #include "knot/ctl/commands.h" +#include "knot/ctl/process.h" #include "knot/dnssec/key-events.h" #include "knot/events/events.h" #include "knot/events/handlers.h" @@ -36,6 +38,7 @@ #include "knot/zone/zonefile.h" #include "libknot/libknot.h" #include "libknot/yparser/yptrafo.h" +#include "contrib/atomic.h" #include "contrib/files.h" #include "contrib/string.h" #include "contrib/strtonum.h" @@ -68,7 +71,7 @@ static struct { sizeof(((send_ctx_t *)0)->ttl) + sizeof(((send_ctx_t *)0)->type) + sizeof(((send_ctx_t *)0)->rdata)]; -} ctl_globals; +} ctl_globals[CTL_MAX_CONCURRENT + 1]; static bool allow_blocking_while_ctl_txn(zone_event_type_t event) { @@ -645,47 +648,49 @@ static int zone_backup_cmd(zone_t *zone, ctl_args_t *args) return KNOT_EOK; } + int ret = KNOT_EOK; + pthread_mutex_lock(&zone->cu_lock); if (zone->backup_ctx != NULL) { log_zone_warning(zone->name, "backup or restore already in progress, skipping zone"); ctx->failed = true; - return KNOT_EPROGRESS; + ret = KNOT_EPROGRESS; } - if (ctx->restore_mode && zone->control_update != NULL) { + if (ctx->restore_mode && zone->control_update != NULL && ret == KNOT_EOK) { log_zone_warning(zone->name, "restoring backup not possible due to open control transaction"); ctx->failed = true; - return KNOT_TXN_EEXISTS; + ret = KNOT_TXN_EEXISTS; + } + + if (ret == KNOT_EOK) { + zone->backup_ctx = ctx; } + pthread_mutex_unlock(&zone->cu_lock); ctx->zone_count++; - int ret; - if (!ctx->backup_global) { + if (!ctx->backup_global && ret == KNOT_EOK) { ret = global_backup(ctx, zone_catalog(zone), zone->name); - if (ret != KNOT_EOK) { - return ret; - } } - if (ctx->backup_params & BACKUP_PARAM_KEYSONLY) { + bool finish = false; + if ((ctx->backup_params & BACKUP_PARAM_KEYSONLY) && ret == KNOT_EOK) { ret = zone_backup_keysonly(ctx, conf(), zone); - if (ret != KNOT_EOK) { - return ret; - } - if (ctx->restore_mode) { + if (ctx->restore_mode && ret == KNOT_EOK) { ret = zone_keys_load(zone, args); - if (ret != KNOT_EOK) { - return ret; - } } if (!(ctx->backup_params & BACKUP_PARAM_EVENT)) { - return ret; + finish = true; } } - zone->backup_ctx = ctx; + if (ret != KNOT_EOK || finish) { + zone->backup_ctx = NULL; + return ret; + } + pthread_mutex_lock(&ctx->readers_mutex); ctx->readers++; pthread_mutex_unlock(&ctx->readers_mutex); @@ -720,7 +725,7 @@ static int zones_apply_backup(ctl_args_t *args, bool restore_mode) zone_backup_ctx_t *ctx = latest_backup_ctx(args); /* QUIC - server key and cert backup. */ - ret = backup_quic(ctx, args->server->quic_active); + ret = backup_quic(ctx, args->server->quic_active || args->server->tls_active); if (ret != KNOT_EOK) { log_ctl_error("control, QUIC %s error (%s)", restore_mode ? "restore" : "backup", @@ -761,6 +766,11 @@ static int zone_sign(zone_t *zone, _unused_ ctl_args_t *args) return schedule_trigger(zone, args, ZONE_EVENT_DNSSEC, true); } +static int zone_validate(zone_t *zone, _unused_ ctl_args_t *args) +{ + return schedule_trigger(zone, args, ZONE_EVENT_VALIDATE, true); +} + static int zone_keys_load(zone_t *zone, _unused_ ctl_args_t *args) { conf_val_t val = conf_zone_get(conf(), C_DNSSEC_SIGNING, zone->name); @@ -811,8 +821,8 @@ static int zone_ksk_sbm_confirm(zone_t *zone, _unused_ ctl_args_t *args) conf_val_t val = conf_zone_get(conf(), C_DNSSEC_SIGNING, zone->name); if (ret == KNOT_EOK && conf_bool(&val)) { - // NOT zone_events_schedule_user(), intentionally! - ret = schedule_trigger(zone, args, ZONE_EVENT_DNSSEC, false); + // NOT zone_events_schedule_user() or schedule_trigger(), intentionally! + zone_events_schedule_now(zone, ZONE_EVENT_DNSSEC); } return ret; @@ -846,17 +856,23 @@ static int zone_xfr_thaw(zone_t *zone, _unused_ ctl_args_t *args) return KNOT_EOK; } -static int zone_txn_begin(zone_t *zone, _unused_ ctl_args_t *args) +static int zone_txn_begin_l(zone_t *zone, _unused_ ctl_args_t *args) { - if (zone->control_update != NULL) { + if (zone->control_update != NULL || conf()->io.txn != NULL) { return KNOT_TXN_EEXISTS; } - if (zone->backup_ctx != NULL && zone->backup_ctx->restore_mode) { + struct zone_backup_ctx *backup_ctx = zone->backup_ctx; + if (backup_ctx != NULL && backup_ctx->restore_mode) { log_zone_warning(zone->name, "zone restore pending, try opening control transaction later"); return KNOT_EAGAIN; } + if (zone->events.running && zone->events.type >= 0 && zone->events.blocking[zone->events.type] != NULL) { + log_zone_warning(zone->name, "some blocking event running, try opening control transaction later"); + return KNOT_EAGAIN; + } + zone->control_update = malloc(sizeof(zone_update_t)); if (zone->control_update == NULL) { return KNOT_ENOMEM; @@ -872,7 +888,15 @@ static int zone_txn_begin(zone_t *zone, _unused_ ctl_args_t *args) return ret; } -static int zone_txn_commit(zone_t *zone, _unused_ ctl_args_t *args) +static int zone_txn_begin(zone_t *zone, ctl_args_t *args) +{ + pthread_mutex_lock(&zone->cu_lock); + int ret = zone_txn_begin_l(zone, args); + pthread_mutex_unlock(&zone->cu_lock); + return ret; +} + +static int zone_txn_commit_l(zone_t *zone, _unused_ ctl_args_t *args) { if (zone->control_update == NULL) { args->suppress = true; @@ -934,15 +958,26 @@ static int zone_txn_commit(zone_t *zone, _unused_ ctl_args_t *args) return KNOT_EOK; } +static int zone_txn_commit(zone_t *zone, ctl_args_t *args) +{ + pthread_mutex_lock(&zone->cu_lock); + int ret = zone_txn_commit_l(zone, args); + pthread_mutex_unlock(&zone->cu_lock); + return ret; +} + static int zone_txn_abort(zone_t *zone, _unused_ ctl_args_t *args) { + pthread_mutex_lock(&zone->cu_lock); if (zone->control_update == NULL) { args->suppress = true; + pthread_mutex_unlock(&zone->cu_lock); return KNOT_TXN_ENOTEXISTS; } zone_control_clear(zone); + pthread_mutex_unlock(&zone->cu_lock); return KNOT_EOK; } @@ -1089,7 +1124,7 @@ static int get_owner(uint8_t *out, size_t out_len, knot_dname_t *origin, static int zone_read(zone_t *zone, ctl_args_t *args) { - send_ctx_t *ctx = &ctl_globals.send_ctx; + send_ctx_t *ctx = &ctl_globals[args->thread_idx].send_ctx; int ret = init_send_ctx(ctx, zone->name, args); if (ret != KNOT_EOK) { return ret; @@ -1131,7 +1166,7 @@ static int zone_flag_txn_get(zone_t *zone, ctl_args_t *args, const char *flag) return KNOT_TXN_ENOTEXISTS; } - send_ctx_t *ctx = &ctl_globals.send_ctx; + send_ctx_t *ctx = &ctl_globals[args->thread_idx].send_ctx; int ret = init_send_ctx(ctx, zone->name, args); if (ret != KNOT_EOK) { return ret; @@ -1170,7 +1205,10 @@ static int zone_flag_txn_get(zone_t *zone, ctl_args_t *args, const char *flag) static int zone_txn_get(zone_t *zone, ctl_args_t *args) { - return zone_flag_txn_get(zone, args, NULL); + pthread_mutex_lock(&zone->cu_lock); + int ret = zone_flag_txn_get(zone, args, NULL); + pthread_mutex_unlock(&zone->cu_lock); + return ret; } static int send_changeset_part(changeset_t *ch, send_ctx_t *ctx, bool from) @@ -1233,7 +1271,7 @@ static int send_changeset(changeset_t *ch, send_ctx_t *ctx) return send_changeset_part(ch, ctx, false); } -static int zone_txn_diff(zone_t *zone, ctl_args_t *args) +static int zone_txn_diff_l(zone_t *zone, ctl_args_t *args) { if (zone->control_update == NULL) { args->suppress = true; @@ -1245,7 +1283,7 @@ static int zone_txn_diff(zone_t *zone, ctl_args_t *args) return zone_flag_txn_get(zone, args, CTL_FLAG_DIFF_ADD); } - send_ctx_t *ctx = &ctl_globals.send_ctx; + send_ctx_t *ctx = &ctl_globals[args->thread_idx].send_ctx; int ret = init_send_ctx(ctx, zone->name, args); if (ret != KNOT_EOK) { return ret; @@ -1254,6 +1292,14 @@ static int zone_txn_diff(zone_t *zone, ctl_args_t *args) return send_changeset(&zone->control_update->change, ctx); } +static int zone_txn_diff(zone_t *zone, ctl_args_t *args) +{ + pthread_mutex_lock(&zone->cu_lock); + int ret = zone_txn_diff_l(zone, args); + pthread_mutex_unlock(&zone->cu_lock); + return ret; +} + static int get_ttl(zone_t *zone, ctl_args_t *args, uint32_t *ttl) { knot_dname_storage_t owner; @@ -1297,8 +1343,8 @@ static int create_rrset(knot_rrset_t **rrset, zone_t *zone, ctl_args_t *args, const char *ttl = need_ttl ? args->data[KNOT_CTL_IDX_TTL] : NULL; // Prepare a buffer for a reconstructed record. - const size_t buff_len = sizeof(ctl_globals.txt_rr); - char *buff = ctl_globals.txt_rr; + const size_t buff_len = sizeof(ctl_globals[args->thread_idx].txt_rr); + char *buff = ctl_globals[args->thread_idx].txt_rr; // Choose default TTL if none was specified. uint32_t default_ttl = 0; @@ -1321,7 +1367,7 @@ static int create_rrset(knot_rrset_t **rrset, zone_t *zone, ctl_args_t *args, size_t rdata_len = ret; // Parse the record. - zs_scanner_t *scanner = &ctl_globals.scanner; + zs_scanner_t *scanner = &ctl_globals[args->thread_idx].scanner; if (zs_init(scanner, origin, KNOT_CLASS_IN, default_ttl) != 0 || zs_set_input_string(scanner, buff, rdata_len) != 0 || zs_parse_record(scanner) != 0 || @@ -1347,7 +1393,7 @@ parser_failed: return ret; } -static int zone_txn_set(zone_t *zone, ctl_args_t *args) +static int zone_txn_set_l(zone_t *zone, ctl_args_t *args) { if (zone->control_update == NULL) { args->suppress = true; @@ -1371,7 +1417,15 @@ static int zone_txn_set(zone_t *zone, ctl_args_t *args) return ret; } -static int zone_txn_unset(zone_t *zone, ctl_args_t *args) +static int zone_txn_set(zone_t *zone, ctl_args_t *args) +{ + pthread_mutex_lock(&zone->cu_lock); + int ret = zone_txn_set_l(zone, args); + pthread_mutex_unlock(&zone->cu_lock); + return ret; +} + +static int zone_txn_unset_l(zone_t *zone, ctl_args_t *args) { if (zone->control_update == NULL) { args->suppress = true; @@ -1421,6 +1475,14 @@ static int zone_txn_unset(zone_t *zone, ctl_args_t *args) } } +static int zone_txn_unset(zone_t *zone, ctl_args_t *args) +{ + pthread_mutex_lock(&zone->cu_lock); + int ret = zone_txn_unset_l(zone, args); + pthread_mutex_unlock(&zone->cu_lock); + return ret; +} + static bool zone_exists(const knot_dname_t *zone, void *data) { assert(zone); @@ -1487,7 +1549,7 @@ static int purge_orphan_member_cb(const knot_dname_t *member, const knot_dname_t orphan->name = (knot_dname_t *)member; orphan->server = server; - purge_flag_t params = + const purge_flag_t params = PURGE_ZONE_TIMERS | PURGE_ZONE_JOURNAL | PURGE_ZONE_KASPDB | PURGE_ZONE_BEST | PURGE_ZONE_LOG; @@ -1530,7 +1592,7 @@ static int catalog_orphans_sweep(server_t *server) knot_strerror(ret)); } } else { - log_error("can't open catalog for purging (%s)", + log_error("can not open catalog for purging (%s)", knot_strerror(ret)); } @@ -1683,7 +1745,7 @@ static int zone_purge(zone_t *zone, ctl_args_t *args) (void)zone_events_schedule_blocking(zone, ZONE_EVENT_EXPIRE, true); } - purge_flag_t params = + const purge_flag_t params = MATCH_OR_FILTER(args, CTL_FILTER_PURGE_TIMERS) * PURGE_ZONE_TIMERS | MATCH_OR_FILTER(args, CTL_FILTER_PURGE_ZONEFILE) * PURGE_ZONE_ZONEFILE | MATCH_OR_FILTER(args, CTL_FILTER_PURGE_JOURNAL) * PURGE_ZONE_JOURNAL | @@ -1695,213 +1757,82 @@ static int zone_purge(zone_t *zone, ctl_args_t *args) return selective_zone_purge(conf(), zone, params); } -static int send_stats_ctr(mod_ctr_t *ctr, uint64_t **stats_vals, unsigned threads, - ctl_args_t *args, knot_ctl_data_t *data) +int ctl_dump_ctr(stats_dump_params_t *params, stats_dump_ctx_t *ctx) { - char index[128]; - char value[32]; - - if (ctr->count == 1) { - uint64_t counter = stats_get_counter(stats_vals, ctr->offset, threads); - int ret = snprintf(value, sizeof(value), "%"PRIu64, counter); - if (ret <= 0 || ret >= sizeof(value)) { - return KNOT_ESPACE; - } - - (*data)[KNOT_CTL_IDX_ID] = NULL; - (*data)[KNOT_CTL_IDX_DATA] = value; + ctl_args_t *args = ctx->ctx; - ret = knot_ctl_send(args->ctl, KNOT_CTL_TYPE_DATA, data); - if (ret != KNOT_EOK) { - return ret; - } - } else { - bool force = ctl_has_flag(args->data[KNOT_CTL_IDX_FLAGS], - CTL_FLAG_FORCE); - - for (uint32_t i = 0; i < ctr->count; i++) { - uint64_t counter = stats_get_counter(stats_vals, ctr->offset + i, threads); - - // Skip empty counters. - if (counter == 0 && !force) { - continue; - } - - int ret; - if (ctr->idx_to_str) { - char *str = ctr->idx_to_str(i, ctr->count); - if (str == NULL) { - continue; - } - ret = snprintf(index, sizeof(index), "%s", str); - free(str); - } else { - ret = snprintf(index, sizeof(index), "%u", i); - } - if (ret <= 0 || ret >= sizeof(index)) { - return KNOT_ESPACE; - } - - ret = snprintf(value, sizeof(value), "%"PRIu64, counter); - if (ret <= 0 || ret >= sizeof(value)) { - return KNOT_ESPACE; - } - - (*data)[KNOT_CTL_IDX_ID] = index; - (*data)[KNOT_CTL_IDX_DATA] = value; - - knot_ctl_type_t type = (i == 0) ? KNOT_CTL_TYPE_DATA : - KNOT_CTL_TYPE_EXTRA; - ret = knot_ctl_send(args->ctl, type, data); - if (ret != KNOT_EOK) { - return ret; - } - } + if (ctx->item != NULL && strcasecmp(ctx->item, params->item) != 0) { + return KNOT_EOK; } + ctx->match = true; - return KNOT_EOK; -} - -static int modules_stats(list_t *query_modules, ctl_args_t *args, knot_ctl_data_t *data) -{ - if (query_modules == NULL) { + if (params->value == 0 && + !ctl_has_flag(args->data[KNOT_CTL_IDX_FLAGS], CTL_FLAG_FORCE)) { return KNOT_EOK; } - const char *section = args->data[KNOT_CTL_IDX_SECTION]; - const char *item = args->data[KNOT_CTL_IDX_ITEM]; - - bool section_found = (section == NULL) ? true : false; - bool item_found = (item == NULL) ? true : false; - - knotd_mod_t *mod; - WALK_LIST(mod, *query_modules) { - // Skip modules without statistics. - if (mod->stats_count == 0) { - continue; - } - - // Check for specific module. - if (section != NULL) { - if (section_found) { - break; - } else if (strcasecmp(mod->id->name + 1, section) == 0) { - section_found = true; - } else { - continue; - } - } - - (*data)[KNOT_CTL_IDX_SECTION] = mod->id->name + 1; - - unsigned threads = knotd_mod_threads(mod); - - for (int i = 0; i < mod->stats_count; i++) { - mod_ctr_t *ctr = mod->stats_info + i; - - // Skip empty counter. - if (ctr->name == NULL) { - continue; - } - - // Check for specific counter. - if (item != NULL) { - if (item_found) { - break; - } else if (strcasecmp(ctr->name, item) == 0) { - item_found = true; - } else { - continue; - } - } + char value[32]; + int ret = snprintf(value, sizeof(value), "%"PRIu64, params->value); + if (ret <= 0 || ret >= sizeof(value)) { + return KNOT_ESPACE; + } - (*data)[KNOT_CTL_IDX_ITEM] = ctr->name; + knot_ctl_data_t data = { + [KNOT_CTL_IDX_SECTION] = params->section, + [KNOT_CTL_IDX_ITEM] = params->item, + [KNOT_CTL_IDX_ID] = params->id, + [KNOT_CTL_IDX_ZONE] = params->zone, + [KNOT_CTL_IDX_DATA] = value, + }; - // Send the counters. - int ret = send_stats_ctr(ctr, mod->stats_vals, threads, args, data); - if (ret != KNOT_EOK) { - return ret; - } - } - } + knot_ctl_type_t type = (params->value_pos == 0) ? + KNOT_CTL_TYPE_DATA : KNOT_CTL_TYPE_EXTRA; - return (section_found && item_found) ? KNOT_EOK : KNOT_ENOENT; + return knot_ctl_send(args->ctl, type, &data); } static int common_stats(ctl_args_t *args, zone_t *zone) { - const char *section = args->data[KNOT_CTL_IDX_SECTION]; - const char *item = args->data[KNOT_CTL_IDX_ITEM]; - - char value[32]; - knot_ctl_data_t data = { - [KNOT_CTL_IDX_DATA] = value + stats_dump_ctx_t dump_ctx = { + .server = args->server, + .zone = zone, + .section = args->data[KNOT_CTL_IDX_SECTION], + .item = args->data[KNOT_CTL_IDX_ITEM], + .ctx = args, }; - knot_dname_txt_storage_t name = ""; - if (zone != NULL) { - if (knot_dname_to_str(name, zone->name, sizeof(name)) == NULL) { - return KNOT_EINVAL; - } - data[KNOT_CTL_IDX_ZONE] = name; - } - - bool found = (section == NULL) ? true : false; - - // Process zone metrics. - const char *section_name = (zone != NULL) ? "zone" : "server"; - if (section == NULL || strcasecmp(section, section_name) == 0) { - data[KNOT_CTL_IDX_SECTION] = section_name; - - const stats_item_t *items = (zone != NULL) ? zone_contents_stats : - server_stats; - for (const stats_item_t *i = items; i->name != NULL; i++) { - if (item != NULL) { - if (found) { - break; - } else if (strcmp(i->name, item) == 0) { - found = true; - } else { - continue; - } - } else { - found = true; - } +#define STATS_CHECK(ret, send) { \ + if (ret != KNOT_EOK) { \ + if ((send)) { /* Prevents duplicit zone error logs. */ \ + send_error(args, knot_strerror(ret)); \ + } \ + return ret; \ + } \ +} - data[KNOT_CTL_IDX_ITEM] = i->name; - int ret = snprintf(value, sizeof(value), "%"PRIu64, - (zone != NULL) ? i->zone_val(zone) : - i->server_val(args->server)); - if (ret <= 0 || ret >= sizeof(value)) { - ret = KNOT_ESPACE; - send_error(args, knot_strerror(ret)); - return ret; - } + if (zone == NULL) { + int ret = stats_server(ctl_dump_ctr, &dump_ctx); + STATS_CHECK(ret, true); - ret = knot_ctl_send(args->ctl, KNOT_CTL_TYPE_DATA, &data); - if (ret != KNOT_EOK) { - send_error(args, knot_strerror(ret)); - return ret; - } - } - } + ret = stats_xdp(ctl_dump_ctr, &dump_ctx); + STATS_CHECK(ret, true); - if (section == NULL || strncasecmp(section, "mod-", strlen("mod-")) == 0) { - list_t *query_modules = (zone != NULL) ? &zone->query_modules : - conf()->query_modules; - int ret = modules_stats(query_modules, args, &data); - if (ret != KNOT_EOK) { - send_error(args, knot_strerror(ret)); - return ret; - } + dump_ctx.query_modules = conf()->query_modules; + ret = stats_modules(ctl_dump_ctr, &dump_ctx); + STATS_CHECK(ret, true); + } else { + int ret = stats_zone(ctl_dump_ctr, &dump_ctx); + STATS_CHECK(ret, false); - found = true; + dump_ctx.query_modules = &zone->query_modules; + ret = stats_modules(ctl_dump_ctr, &dump_ctx); + STATS_CHECK(ret, false); } - if (!found) { - send_error(args, knot_strerror(KNOT_EINVAL)); - return KNOT_EINVAL; + if (!dump_ctx.match) { + STATS_CHECK(KNOT_EINVAL, zone == NULL); } +#undef STATS_CHECK return KNOT_EOK; } @@ -1932,6 +1863,8 @@ static int ctl_zone(ctl_args_t *args, ctl_cmd_t cmd) return zones_apply_backup(args, true); case CTL_ZONE_SIGN: return zones_apply(args, zone_sign); + case CTL_ZONE_VALIDATE: + return zones_apply(args, zone_validate); case CTL_ZONE_KEYS_LOAD: return zones_apply(args, zone_keys_load); case CTL_ZONE_KEY_ROLL: @@ -1976,6 +1909,27 @@ static int ctl_zone(ctl_args_t *args, ctl_cmd_t cmd) } } +static void check_zone_txn(zone_t *zone, const knot_dname_t **exists) +{ + if (zone->control_update != NULL) { + *exists = zone->name; + } +} + +static int check_no_zone_txn(server_t *server, const char *action) +{ + const knot_dname_t *zone_txn_exists = NULL; + knot_zonedb_foreach(server->zone_db, check_zone_txn, &zone_txn_exists); + if (zone_txn_exists != NULL) { + knot_dname_txt_storage_t zone_str; + knot_dname_to_str(zone_str, zone_txn_exists, sizeof(zone_str)); + log_warning("%s rejected due to existing transaction for zone %s", + action, zone_str); + return KNOT_TXN_EEXISTS; + } + return KNOT_EOK; +} + static int server_status(ctl_args_t *args) { const char *type = args->data[KNOT_CTL_IDX_TYPE]; @@ -1998,7 +1952,7 @@ static int server_status(ctl_args_t *args) conf()->cache.srv_xdp_threads, conf()->cache.srv_bg_threads, running_bkg_wrk, wrk_queue); } else if (strcasecmp(type, "configure") == 0) { - ret = snprintf(buff, sizeof(buff), "%s", CONFIGURE_SUMMARY); + ret = snprintf(buff, sizeof(buff), "%s", configure_summary); } else if (strcasecmp(type, "cert-key") == 0) { uint8_t pin[128]; size_t pin_len = server_cert_pin(args->server, pin, sizeof(pin)); @@ -2034,7 +1988,10 @@ static int ctl_server(ctl_args_t *args, ctl_cmd_t cmd) ret = KNOT_CTL_ESTOP; break; case CTL_RELOAD: - ret = server_reload(args->server, RELOAD_FULL); + ret = check_no_zone_txn(args->server, "server reload"); + if (ret == KNOT_EOK) { + ret = server_reload(args->server, RELOAD_FULL); + } if (ret != KNOT_EOK) { send_error(args, knot_strerror(ret)); } @@ -2171,7 +2128,10 @@ static int ctl_conf_txn(ctl_args_t *args, ctl_cmd_t cmd) switch (cmd) { case CTL_CONF_BEGIN: - ret = conf_io_begin(false); + ret = check_no_zone_txn(args->server, "config, transaction"); + if (ret == KNOT_EOK) { + ret = conf_io_begin(false); + } break; case CTL_CONF_ABORT: conf_io_abort(false); @@ -2368,56 +2328,64 @@ static int ctl_conf_modify(ctl_args_t *args, ctl_cmd_t cmd) return ret; } +typedef enum { + CTL_LOCK_NONE = 0x00, + CTL_LOCK_SRV_R = 0x01, // Can run in parallel with other R commands. + CTL_LOCK_SRV_W = 0x02, // Cannot run in parallel with other commands. +} ctl_lock_flag_t; + typedef struct { const char *name; int (*fcn)(ctl_args_t *, ctl_cmd_t); + ctl_lock_flag_t locks; } desc_t; static const desc_t cmd_table[] = { [CTL_NONE] = { "" }, - [CTL_STATUS] = { "status", ctl_server }, - [CTL_STOP] = { "stop", ctl_server }, - [CTL_RELOAD] = { "reload", ctl_server }, - [CTL_STATS] = { "stats", ctl_stats }, - - [CTL_ZONE_STATUS] = { "zone-status", ctl_zone }, - [CTL_ZONE_RELOAD] = { "zone-reload", ctl_zone }, - [CTL_ZONE_REFRESH] = { "zone-refresh", ctl_zone }, - [CTL_ZONE_RETRANSFER] = { "zone-retransfer", ctl_zone }, - [CTL_ZONE_NOTIFY] = { "zone-notify", ctl_zone }, - [CTL_ZONE_FLUSH] = { "zone-flush", ctl_zone }, - [CTL_ZONE_BACKUP] = { "zone-backup", ctl_zone }, - [CTL_ZONE_RESTORE] = { "zone-restore", ctl_zone }, - [CTL_ZONE_SIGN] = { "zone-sign", ctl_zone }, - [CTL_ZONE_KEYS_LOAD] = { "zone-keys-load", ctl_zone }, - [CTL_ZONE_KEY_ROLL] = { "zone-key-rollover", ctl_zone }, - [CTL_ZONE_KSK_SBM] = { "zone-ksk-submitted", ctl_zone }, - [CTL_ZONE_FREEZE] = { "zone-freeze", ctl_zone }, - [CTL_ZONE_THAW] = { "zone-thaw", ctl_zone }, - [CTL_ZONE_XFR_FREEZE] = { "zone-xfr-freeze", ctl_zone }, - [CTL_ZONE_XFR_THAW] = { "zone-xfr-thaw", ctl_zone }, - - [CTL_ZONE_READ] = { "zone-read", ctl_zone }, - [CTL_ZONE_BEGIN] = { "zone-begin", ctl_zone }, - [CTL_ZONE_COMMIT] = { "zone-commit", ctl_zone }, - [CTL_ZONE_ABORT] = { "zone-abort", ctl_zone }, - [CTL_ZONE_DIFF] = { "zone-diff", ctl_zone }, - [CTL_ZONE_GET] = { "zone-get", ctl_zone }, - [CTL_ZONE_SET] = { "zone-set", ctl_zone }, - [CTL_ZONE_UNSET] = { "zone-unset", ctl_zone }, - [CTL_ZONE_PURGE] = { "zone-purge", ctl_zone }, - [CTL_ZONE_STATS] = { "zone-stats", ctl_zone }, - - [CTL_CONF_LIST] = { "conf-list", ctl_conf_list }, - [CTL_CONF_READ] = { "conf-read", ctl_conf_read }, - [CTL_CONF_BEGIN] = { "conf-begin", ctl_conf_txn }, - [CTL_CONF_COMMIT] = { "conf-commit", ctl_conf_txn }, - [CTL_CONF_ABORT] = { "conf-abort", ctl_conf_txn }, - [CTL_CONF_DIFF] = { "conf-diff", ctl_conf_read }, - [CTL_CONF_GET] = { "conf-get", ctl_conf_read }, - [CTL_CONF_SET] = { "conf-set", ctl_conf_modify }, - [CTL_CONF_UNSET] = { "conf-unset", ctl_conf_modify }, + [CTL_STATUS] = { "status", ctl_server, CTL_LOCK_SRV_R }, + [CTL_STOP] = { "stop", ctl_server, CTL_LOCK_SRV_R }, + [CTL_RELOAD] = { "reload", ctl_server, CTL_LOCK_SRV_W }, + [CTL_STATS] = { "stats", ctl_stats, CTL_LOCK_SRV_R }, + + [CTL_ZONE_STATUS] = { "zone-status", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_RELOAD] = { "zone-reload", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_REFRESH] = { "zone-refresh", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_RETRANSFER] = { "zone-retransfer", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_NOTIFY] = { "zone-notify", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_FLUSH] = { "zone-flush", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_BACKUP] = { "zone-backup", ctl_zone, CTL_LOCK_SRV_W }, // Backup and restore must be exclusive as the global backup ctx is accessed. + [CTL_ZONE_RESTORE] = { "zone-restore", ctl_zone, CTL_LOCK_SRV_W }, + [CTL_ZONE_SIGN] = { "zone-sign", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_VALIDATE] = { "zone-validate", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_KEYS_LOAD] = { "zone-keys-load", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_KEY_ROLL] = { "zone-key-rollover", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_KSK_SBM] = { "zone-ksk-submitted", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_FREEZE] = { "zone-freeze", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_THAW] = { "zone-thaw", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_XFR_FREEZE] = { "zone-xfr-freeze", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_XFR_THAW] = { "zone-xfr-thaw", ctl_zone, CTL_LOCK_SRV_R }, + + [CTL_ZONE_READ] = { "zone-read", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_BEGIN] = { "zone-begin", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_COMMIT] = { "zone-commit", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_ABORT] = { "zone-abort", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_DIFF] = { "zone-diff", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_GET] = { "zone-get", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_SET] = { "zone-set", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_UNSET] = { "zone-unset", ctl_zone, CTL_LOCK_SRV_R }, + [CTL_ZONE_PURGE] = { "zone-purge", ctl_zone, CTL_LOCK_SRV_W }, + [CTL_ZONE_STATS] = { "zone-stats", ctl_zone, CTL_LOCK_SRV_R }, + + [CTL_CONF_LIST] = { "conf-list", ctl_conf_list, CTL_LOCK_SRV_R }, // Can either read live conf or conf txn. The latter would deserve CTL_LOCK_SRV_W, but when conf txn exists, all cmds are done by single thread anyway. + [CTL_CONF_READ] = { "conf-read", ctl_conf_read, CTL_LOCK_SRV_R }, + [CTL_CONF_BEGIN] = { "conf-begin", ctl_conf_txn, CTL_LOCK_SRV_W }, // It's locked only during conf-begin, not for the whole duration of the transaction. + [CTL_CONF_COMMIT] = { "conf-commit", ctl_conf_txn, CTL_LOCK_SRV_W }, + [CTL_CONF_ABORT] = { "conf-abort", ctl_conf_txn, CTL_LOCK_SRV_W }, + [CTL_CONF_DIFF] = { "conf-diff", ctl_conf_read, CTL_LOCK_SRV_W }, + [CTL_CONF_GET] = { "conf-get", ctl_conf_read, CTL_LOCK_SRV_W }, + [CTL_CONF_SET] = { "conf-set", ctl_conf_modify, CTL_LOCK_SRV_W }, + [CTL_CONF_UNSET] = { "conf-unset", ctl_conf_modify, CTL_LOCK_SRV_W }, }; #define MAX_CTL_CODE (sizeof(cmd_table) / sizeof(desc_t) - 1) @@ -2446,13 +2414,52 @@ ctl_cmd_t ctl_str_to_cmd(const char *cmd_str) return CTL_NONE; } +static int ctl_lock(server_t *server, ctl_lock_flag_t flags, uint64_t timeout_ms) +{ + struct timespec ts; + int ret = clock_gettime(CLOCK_REALTIME, &ts); + if (ret != 0) { + return KNOT_ERROR; + } + ts.tv_sec += timeout_ms / 1000; + ts.tv_nsec += (timeout_ms % 1000) * 1000000LU; + + if ((flags & CTL_LOCK_SRV_W)) { + assert(!(flags & CTL_LOCK_SRV_R)); +#if !defined(__APPLE__) + ret = pthread_rwlock_timedwrlock(&server->ctl_lock, &ts); +#else + ret = pthread_rwlock_wrlock(&server->ctl_lock); +#endif + } + if ((flags & CTL_LOCK_SRV_R)) { +#if !defined(__APPLE__) + ret = pthread_rwlock_timedrdlock(&server->ctl_lock, &ts); +#else + ret = pthread_rwlock_rdlock(&server->ctl_lock); +#endif + } + return (ret != 0 ? KNOT_EBUSY : KNOT_EOK); +} + +static void ctl_unlock(server_t *server) +{ + pthread_rwlock_unlock(&server->ctl_lock); +} + int ctl_exec(ctl_cmd_t cmd, ctl_args_t *args) { if (args == NULL) { return KNOT_EINVAL; } - return cmd_table[cmd].fcn(args, cmd); + int ret = ctl_lock(args->server, cmd_table[cmd].locks, conf()->cache.ctl_timeout); + if (ret == KNOT_EOK) { + ret = cmd_table[cmd].fcn(args, cmd); + ctl_unlock(args->server); + } + + return ret; } bool ctl_has_flag(const char *flags, const char *flag) diff --git a/src/knot/ctl/commands.h b/src/knot/ctl/commands.h index ed7e75c..b0f33d8 100644 --- a/src/knot/ctl/commands.h +++ b/src/knot/ctl/commands.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -87,6 +87,7 @@ typedef enum { CTL_ZONE_BACKUP, CTL_ZONE_RESTORE, CTL_ZONE_SIGN, + CTL_ZONE_VALIDATE, CTL_ZONE_KEYS_LOAD, CTL_ZONE_KEY_ROLL, CTL_ZONE_KSK_SBM, @@ -124,6 +125,7 @@ typedef struct { knot_ctl_data_t data; server_t *server; bool suppress; // Suppress error reporting in the "all zones" ctl commands. + unsigned thread_idx; } ctl_args_t; /*! diff --git a/src/knot/ctl/process.c b/src/knot/ctl/process.c index 50fde21..9e6e0df 100644 --- a/src/knot/ctl/process.c +++ b/src/knot/ctl/process.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ #include "libknot/error.h" #include "contrib/string.h" -int ctl_process(knot_ctl_t *ctl, server_t *server) +int ctl_process(knot_ctl_t *ctl, server_t *server, int thread_idx, bool *exclusive) { if (ctl == NULL || server == NULL) { return KNOT_EINVAL; @@ -29,7 +29,8 @@ int ctl_process(knot_ctl_t *ctl, server_t *server) ctl_args_t args = { .ctl = ctl, .type = KNOT_CTL_TYPE_END, - .server = server + .server = server, + .thread_idx = thread_idx, }; // Strip redundant/unprocessed data units in the current block. @@ -90,11 +91,21 @@ int ctl_process(knot_ctl_t *ctl, server_t *server) continue; } + if ((cmd == CTL_CONF_COMMIT || cmd == CTL_CONF_ABORT) && !*exclusive) { + log_ctl_warning("control, invalid reception of '%s'", cmd_name); + continue; + } + // Execute the command. int cmd_ret = ctl_exec(cmd, &args); switch (cmd_ret) { case KNOT_EOK: strip = false; + if (cmd == CTL_CONF_BEGIN) { + *exclusive = true; + } else if (cmd == CTL_CONF_COMMIT || cmd == CTL_CONF_ABORT) { + *exclusive = false; + } case KNOT_CTL_ESTOP: case KNOT_CTL_EZONE: // KNOT_CTL_EZONE - don't change strip, but don't be reported diff --git a/src/knot/ctl/process.h b/src/knot/ctl/process.h index ab0f75f..2ae6ea0 100644 --- a/src/knot/ctl/process.h +++ b/src/knot/ctl/process.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,12 +19,16 @@ #include "libknot/libknot.h" #include "knot/server/server.h" +#define CTL_MAX_CONCURRENT 8 // Number of CTL threads EXCLUDING the main thread which can also process CTL. + /*! * Processes incoming control commands. * - * \param[in] ctl Control context. - * \param[in] server Server instance. + * \param[in] ctl Control context. + * \param[in] server Server instance. + * \param[in] thread_idx Index of a thread which performs the operation. + * \param[out] exclusive All following CTLs shall (not) be processed exclusively by this thread. * * \return Error code, KNOT_EOK if successful. */ -int ctl_process(knot_ctl_t *ctl, server_t *server); +int ctl_process(knot_ctl_t *ctl, server_t *server, int thread_idx, bool *exclusive); diff --git a/src/knot/dnssec/context.c b/src/knot/dnssec/context.c index 1a19f68..24b41f7 100644 --- a/src/knot/dnssec/context.c +++ b/src/knot/dnssec/context.c @@ -213,11 +213,13 @@ int kdnssec_ctx_init(conf_t *conf, kdnssec_ctx_t *ctx, const knot_dname_t *zone_ goto init_error; } - ctx->policy = calloc(1, sizeof(*ctx->policy)); + ctx->policy = calloc(1, sizeof(*ctx->policy) + sizeof(*ctx->stats)); if (ctx->policy == NULL) { ret = KNOT_ENOMEM; goto init_error; } + ctx->stats = (void *)ctx->policy + sizeof(*ctx->policy); + knot_spin_init(&ctx->stats->lock); ret = kasp_db_get_saved_ttls(ctx->kasp_db, zone_name, &ctx->policy->saved_max_ttl, @@ -287,6 +289,7 @@ void kdnssec_ctx_deinit(kdnssec_ctx_t *ctx) } if (ctx->policy != NULL) { + knot_spin_destroy(&ctx->stats->lock); free(ctx->policy->string); knot_dynarray_foreach(parent, knot_kasp_parent_t, i, ctx->policy->parents) { free(i->addr); @@ -331,18 +334,22 @@ int kdnssec_validation_ctx(conf_t *conf, kdnssec_ctx_t *ctx, const zone_contents return KNOT_ENOMEM; } - ctx->policy = calloc(1, sizeof(*ctx->policy)); + ctx->policy = calloc(1, sizeof(*ctx->policy) + sizeof(*ctx->stats)); if (ctx->policy == NULL) { free(ctx->zone); return KNOT_ENOMEM; } + ctx->stats = (void *)ctx->policy + sizeof(*ctx->policy); + knot_spin_init(&ctx->stats->lock); policy_from_zone(ctx->policy, zone); if (conf != NULL) { conf_val_t policy_id = conf_zone_get(conf, C_DNSSEC_POLICY, zone->apex->owner); conf_id_fix_default(&policy_id); - conf_val_t num_threads = conf_id_get(conf, C_POLICY, C_SIGNING_THREADS, &policy_id); - ctx->policy->signing_threads = conf_int(&num_threads); + conf_val_t val = conf_id_get(conf, C_POLICY, C_SIGNING_THREADS, &policy_id); + ctx->policy->signing_threads = conf_int(&val); + val = conf_id_get(conf, C_POLICY, C_RRSIG_REFRESH, &policy_id); + ctx->policy->rrsig_refresh_before = conf_int_alt(&val, true); } else { ctx->policy->signing_threads = MAX(dt_optimal_size(), 1); } diff --git a/src/knot/dnssec/context.h b/src/knot/dnssec/context.h index 756bc56..2d126db 100644 --- a/src/knot/dnssec/context.h +++ b/src/knot/dnssec/context.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,14 +16,20 @@ #pragma once -#include - #include "libdnssec/keystore.h" - +#include "contrib/spinlock.h" +#include "contrib/time.h" #include "knot/conf/conf.h" #include "knot/dnssec/kasp/kasp_zone.h" #include "knot/dnssec/kasp/policy.h" +typedef struct { + size_t rrsig_count; + knot_time_t expire; + + knot_spin_t lock; +} zone_sign_stats_t; + /*! * \brief DNSSEC signing context. */ @@ -38,6 +44,8 @@ typedef struct { char *kasp_zone_path; + zone_sign_stats_t *stats; + bool rrsig_drop_existing; bool keep_deleted_keys; bool keytag_conflict; diff --git a/src/knot/dnssec/ds_query.c b/src/knot/dnssec/ds_query.c index 2ac91cc..0b85247 100644 --- a/src/knot/dnssec/ds_query.c +++ b/src/knot/dnssec/ds_query.c @@ -28,8 +28,8 @@ #define DS_CHECK_LOG(priority, zone, remote, flags, fmt, ...) \ ns_log(priority, zone, LOG_OPERATION_DS_CHECK, LOG_DIRECTION_OUT, &(remote)->addr, \ - ((flags) & KNOT_REQUESTOR_QUIC) ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_TCP, \ - ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, fmt, ## __VA_ARGS__) + flags2proto(flags), ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, \ + fmt, ## __VA_ARGS__) static bool match_key_ds(knot_kasp_key_t *key, knot_rdata_t *ds) { diff --git a/src/knot/dnssec/key-events.c b/src/knot/dnssec/key-events.c index 58d7ec0..db762b6 100644 --- a/src/knot/dnssec/key-events.c +++ b/src/knot/dnssec/key-events.c @@ -17,8 +17,8 @@ #include #include "contrib/macros.h" +#include "knot/common/dbus.h" #include "knot/common/log.h" -#include "knot/common/systemd.h" #include "knot/dnssec/kasp/keystate.h" #include "knot/dnssec/key-events.h" #include "knot/dnssec/policy.h" @@ -881,7 +881,7 @@ int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_sign_roll_flags_t flags, if (ret == KNOT_EOK && reschedule->keys_changed) { ret = kdnssec_ctx_commit(ctx); if (ret == KNOT_EOK && (ctx->dbus_event & DBUS_EVENT_KEYS_UPDATED)) { - systemd_emit_keys_updated(ctx->zone->dname); + dbus_emit_keys_updated(ctx->zone->dname); } } @@ -891,7 +891,7 @@ int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_sign_roll_flags_t flags, log_fmt_zone(LOG_NOTICE, LOG_SOURCE_ZONE, ctx->zone->dname, param, "DNSSEC, KSK submission, waiting for confirmation"); if (ctx->dbus_event & DBUS_EVENT_ZONE_SUBMISSION) { - systemd_emit_zone_submission(ctx->zone->dname, ready_keytag, ready_keyid); + dbus_emit_zone_submission(ctx->zone->dname, ready_keytag, ready_keyid); } } diff --git a/src/knot/dnssec/key_records.c b/src/knot/dnssec/key_records.c index 9b22f7a..366ab4a 100644 --- a/src/knot/dnssec/key_records.c +++ b/src/knot/dnssec/key_records.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -189,7 +189,7 @@ int key_records_dump(char **buf, size_t *buf_size, const key_records_t *r, bool return ret >= 0 ? KNOT_EOK : ret; } -int key_records_sign(const zone_key_t *key, key_records_t *r, const kdnssec_ctx_t *kctx, knot_time_t *expires) +int key_records_sign(const zone_key_t *key, key_records_t *r, const kdnssec_ctx_t *kctx) { dnssec_sign_ctx_t *sign_ctx; int ret = dnssec_sign_new(&sign_ctx, key->key); @@ -198,20 +198,20 @@ int key_records_sign(const zone_key_t *key, key_records_t *r, const kdnssec_ctx_ } if (!knot_rrset_empty(&r->dnskey) && knot_zone_sign_use_key(key, &r->dnskey)) { - ret = knot_sign_rrset(&r->rrsig, &r->dnskey, key->key, sign_ctx, kctx, NULL, expires); + ret = knot_sign_rrset(&r->rrsig, &r->dnskey, key->key, sign_ctx, kctx, NULL); } if (ret == KNOT_EOK && !knot_rrset_empty(&r->cdnskey) && knot_zone_sign_use_key(key, &r->cdnskey)) { - ret = knot_sign_rrset(&r->rrsig, &r->cdnskey, key->key, sign_ctx, kctx, NULL, expires); + ret = knot_sign_rrset(&r->rrsig, &r->cdnskey, key->key, sign_ctx, kctx, NULL); } if (ret == KNOT_EOK && !knot_rrset_empty(&r->cds) && knot_zone_sign_use_key(key, &r->cds)) { - ret = knot_sign_rrset(&r->rrsig, &r->cds, key->key, sign_ctx, kctx, NULL, expires); + ret = knot_sign_rrset(&r->rrsig, &r->cds, key->key, sign_ctx, kctx, NULL); } dnssec_sign_free(sign_ctx); return ret; } -int key_records_verify(key_records_t *r, kdnssec_ctx_t *kctx, knot_time_t timestamp) +int key_records_verify(key_records_t *r, kdnssec_ctx_t *kctx, knot_time_t timestamp, knot_time_t min_valid) { kctx->now = timestamp; int ret = kasp_zone_keys_from_rr(kctx->zone, &r->dnskey.rrs, false, &kctx->keytag_conflict); @@ -224,12 +224,17 @@ int key_records_verify(key_records_t *r, kdnssec_ctx_t *kctx, knot_time_t timest return KNOT_ENOMEM; } - ret = knot_validate_rrsigs(&r->dnskey, &r->rrsig, sign_ctx, false); + knot_time_t until = 0; + ret = knot_validate_rrsigs(&r->dnskey, &r->rrsig, sign_ctx, false, &until); if (ret == KNOT_EOK && !knot_rrset_empty(&r->cdnskey)) { - ret = knot_validate_rrsigs(&r->cdnskey, &r->rrsig, sign_ctx, false); + ret = knot_validate_rrsigs(&r->cdnskey, &r->rrsig, sign_ctx, false, &until); } if (ret == KNOT_EOK && !knot_rrset_empty(&r->cds)) { - ret = knot_validate_rrsigs(&r->cds, &r->rrsig, sign_ctx, false); + ret = knot_validate_rrsigs(&r->cds, &r->rrsig, sign_ctx, false, &until); + } + + if (ret == KNOT_EOK && knot_time_lt(until, min_valid)) { + ret = KNOT_ESOON_EXPIRE; } zone_sign_ctx_free(sign_ctx); diff --git a/src/knot/dnssec/key_records.h b/src/knot/dnssec/key_records.h index b53ed86..dd28b4f 100644 --- a/src/knot/dnssec/key_records.h +++ b/src/knot/dnssec/key_records.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,10 +39,10 @@ int key_records_intersect(key_records_t *r, const key_records_t *against); int key_records_dump(char **buf, size_t *buf_size, const key_records_t *r, bool verbose); -int key_records_sign(const zone_key_t *key, key_records_t *r, const kdnssec_ctx_t *kctx, knot_time_t *expires); +int key_records_sign(const zone_key_t *key, key_records_t *r, const kdnssec_ctx_t *kctx); // WARNING this modifies 'kctx' with updated timestamp and with zone_keys from r->dnskey -int key_records_verify(key_records_t *r, kdnssec_ctx_t *kctx, knot_time_t timestamp); +int key_records_verify(key_records_t *r, kdnssec_ctx_t *kctx, knot_time_t timestamp, knot_time_t min_valid); size_t key_records_serialized_size(const key_records_t *r); diff --git a/src/knot/dnssec/rrset-sign.c b/src/knot/dnssec/rrset-sign.c index 4c9e904..1dc9edc 100644 --- a/src/knot/dnssec/rrset-sign.c +++ b/src/knot/dnssec/rrset-sign.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -157,13 +157,13 @@ static int sign_ctx_add_self(dnssec_sign_ctx_t *ctx, const uint8_t *rdata) */ static int sign_ctx_add_records(dnssec_sign_ctx_t *ctx, const knot_rrset_t *covered) { - size_t rrwl = knot_rrset_size(covered); + size_t rrwl = knot_rrset_size_estimate(covered); uint8_t *rrwf = malloc(rrwl); if (!rrwf) { return KNOT_ENOMEM; } - int written = knot_rrset_to_wire_extra(covered, rrwf, rrwl, 0, NULL, KNOT_PF_BUFENOUGH); + int written = knot_rrset_to_wire_extra(covered, rrwf, rrwl, 0, NULL, 0); if (written < 0) { free(rrwf); return written; @@ -263,7 +263,7 @@ static int rrsigs_create_rdata(knot_rrset_t *rrsigs, dnssec_sign_ctx_t *ctx, int knot_sign_rrset(knot_rrset_t *rrsigs, const knot_rrset_t *covered, const dnssec_key_t *key, dnssec_sign_ctx_t *sign_ctx, - const kdnssec_ctx_t *dnssec_ctx, knot_mm_t *mm, knot_time_t *expires) + const kdnssec_ctx_t *dnssec_ctx, knot_mm_t *mm) { if (knot_rrset_empty(covered) || !key || !sign_ctx || !dnssec_ctx || rrsigs->type != KNOT_RRTYPE_RRSIG || @@ -279,8 +279,11 @@ int knot_sign_rrset(knot_rrset_t *rrsigs, const knot_rrset_t *covered, int ret = rrsigs_create_rdata(rrsigs, sign_ctx, covered, key, (uint32_t)sig_incept, (uint32_t)sig_expire, sign_flags, mm); - if (ret == KNOT_EOK && expires != NULL) { - *expires = knot_time_min(*expires, sig_expire); + if (ret == KNOT_EOK) { + knot_spin_lock(&dnssec_ctx->stats->lock); + dnssec_ctx->stats->rrsig_count++; + dnssec_ctx->stats->expire = knot_time_min(dnssec_ctx->stats->expire, sig_expire); + knot_spin_unlock(&dnssec_ctx->stats->lock); } return ret; } @@ -300,7 +303,7 @@ int knot_sign_rrset2(knot_rrset_t *rrsigs, const knot_rrset_t *rrset, } int ret = knot_sign_rrset(rrsigs, rrset, key->key, sign_ctx->sign_ctxs[i], - sign_ctx->dnssec_ctx, mm, NULL); + sign_ctx->dnssec_ctx, mm); if (ret != KNOT_EOK) { return ret; } diff --git a/src/knot/dnssec/rrset-sign.h b/src/knot/dnssec/rrset-sign.h index 8e00402..ba0f027 100644 --- a/src/knot/dnssec/rrset-sign.h +++ b/src/knot/dnssec/rrset-sign.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,7 +31,6 @@ * \param sign_ctx Signing context. * \param dnssec_ctx DNSSEC context. * \param mm Memory context. - * \param expires Out: When will the new RRSIG expire. * * \return Error code, KNOT_EOK if successful. */ @@ -40,8 +39,7 @@ int knot_sign_rrset(knot_rrset_t *rrsigs, const dnssec_key_t *key, dnssec_sign_ctx_t *sign_ctx, const kdnssec_ctx_t *dnssec_ctx, - knot_mm_t *mm, - knot_time_t *expires); + knot_mm_t *mm); /*! * \brief Create RRSIG RR for given RR set, choose which key to use. diff --git a/src/knot/dnssec/zone-events.c b/src/knot/dnssec/zone-events.c index faf093d..2ca35ac 100644 --- a/src/knot/dnssec/zone-events.c +++ b/src/knot/dnssec/zone-events.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include "libdnssec/random.h" #include "libknot/libknot.h" #include "knot/conf/conf.h" +#include "knot/common/dbus.h" #include "knot/common/log.h" #include "knot/dnssec/key-events.h" #include "knot/dnssec/key_records.h" @@ -157,7 +158,6 @@ int knot_dnssec_zone_sign(zone_update_t *update, const knot_dname_t *zone_name = update->new_cont->apex->owner; kdnssec_ctx_t ctx = { 0 }; zone_keyset_t keyset = { 0 }; - knot_time_t zone_expire = 0; int result = kdnssec_ctx_init(conf, &ctx, zone_name, zone_kaspdb(update->zone), NULL); if (result != KNOT_EOK) { @@ -259,7 +259,7 @@ int knot_dnssec_zone_sign(zone_update_t *update, goto done; } - result = knot_zone_sign(update, &keyset, &ctx, &zone_expire); + result = knot_zone_sign(update, &keyset, &ctx); if (result != KNOT_EOK) { log_zone_error(zone_name, "DNSSEC, failed to sign zone content (%s)", knot_strerror(result)); @@ -302,13 +302,14 @@ int knot_dnssec_zone_sign(zone_update_t *update, } } - log_zone_info(zone_name, "DNSSEC, successfully signed, serial %u", - zone_contents_serial(update->new_cont)); + log_zone_info(zone_name, "DNSSEC, successfully signed, serial %u, new RRSIGs %zu", + zone_contents_serial(update->new_cont), ctx.stats->rrsig_count); done: if (result == KNOT_EOK) { - reschedule->next_sign = schedule_next(&ctx, &keyset, ctx.offline_next_time, zone_expire); + reschedule->next_sign = schedule_next(&ctx, &keyset, ctx.offline_next_time, ctx.stats->expire); reschedule->plan_dnskey_sync = ctx.policy->has_dnskey_sync; + update->new_cont->dnssec_expire = ctx.stats->expire; } else { reschedule->next_sign = knot_dnssec_failover_delay(&ctx); reschedule->next_rollover = 0; @@ -329,7 +330,6 @@ int knot_dnssec_sign_update(zone_update_t *update, conf_t *conf) const knot_dname_t *zone_name = update->new_cont->apex->owner; kdnssec_ctx_t ctx = { 0 }; zone_keyset_t keyset = { 0 }; - knot_time_t zone_expire = 0; int result = kdnssec_ctx_init(conf, &ctx, zone_name, zone_kaspdb(update->zone), NULL); if (result != KNOT_EOK) { @@ -381,7 +381,7 @@ int knot_dnssec_sign_update(zone_update_t *update, conf_t *conf) goto done; } - result = knot_zone_sign_update(update, &keyset, &ctx, &zone_expire); + result = knot_zone_sign_update(update, &keyset, &ctx); if (result != KNOT_EOK) { log_zone_error(zone_name, "DNSSEC, failed to sign changeset (%s)", knot_strerror(result)); @@ -434,17 +434,18 @@ int knot_dnssec_sign_update(zone_update_t *update, conf_t *conf) } } - log_zone_info(zone_name, "DNSSEC, incrementally signed, serial %u", - zone_contents_serial(update->new_cont)); + log_zone_info(zone_name, "DNSSEC, incrementally signed, serial %u, new RRSIGs %zu", + zone_contents_serial(update->new_cont), ctx.stats->rrsig_count); done: if (result == KNOT_EOK) { - knot_time_t next = knot_time_min(ctx.offline_next_time, zone_expire); + knot_time_t next = knot_time_min(ctx.offline_next_time, ctx.stats->expire); // NOTE: this is usually NOOP since signing planned earlier zone_events_schedule_at(update->zone, ZONE_EVENT_DNSSEC, (time_t)(next ? next : -1)); if (ctx.policy->has_dnskey_sync) { zone_events_schedule_now(update->zone, ZONE_EVENT_DNSKEY_SYNC); } + update->new_cont->dnssec_expire = knot_time_min(update->zone->contents->dnssec_expire, ctx.stats->expire); } free_zone_keys(&keyset); @@ -462,25 +463,83 @@ knot_time_t knot_dnssec_failover_delay(const kdnssec_ctx_t *ctx) } } -int knot_dnssec_validate_zone(zone_update_t *update, conf_t *conf, knot_time_t now, bool incremental) +static void log_validation_error(zone_update_t *update, const char *msg_valid, + int ret, bool warning) +{ + unsigned level = warning ? LOG_WARNING : LOG_ERR; + + log_fmt_zone(level, LOG_SOURCE_ZONE, update->zone->name, NULL, + "DNSSEC, %svalidation failed (%s)", msg_valid, knot_strerror(ret)); + + char type_str[16]; + knot_dname_txt_storage_t name_str; + if (knot_dname_to_str(name_str, update->validation_hint.node, sizeof(name_str)) != NULL && + knot_rrtype_to_string(update->validation_hint.rrtype, type_str, sizeof(type_str)) >= 0) { + log_fmt_zone(level, LOG_SOURCE_ZONE, update->zone->name, NULL, + "DNSSEC, validation hint: %s %s", name_str, type_str); + } +} + +int knot_dnssec_validate_zone(zone_update_t *update, conf_t *conf, + knot_time_t now, bool incremental, bool log_plan) { kdnssec_ctx_t ctx = { 0 }; int ret = kdnssec_validation_ctx(conf, &ctx, update->new_cont); + if (ret != KNOT_EOK) { + goto end; + } if (now != 0) { ctx.now = now; } + + ret = knot_zone_check_nsec_chain(update, &ctx, incremental); if (ret == KNOT_EOK) { - ret = knot_zone_check_nsec_chain(update, &ctx, incremental); - } - if (ret == KNOT_EOK) { - knot_time_t unused = 0; assert(ctx.validation_mode); if (incremental) { - ret = knot_zone_sign_update(update, NULL, &ctx, &unused); + ret = knot_zone_sign_update(update, NULL, &ctx); } else { - ret = knot_zone_sign(update, NULL, &ctx, &unused); + ret = knot_zone_sign(update, NULL, &ctx); } } +end: + if (log_plan) { + const char *msg_valid = incremental ? "incremental " : ""; + if (ret != KNOT_EOK) { + log_validation_error(update, msg_valid, ret, false); + if (conf->cache.srv_dbus_event & DBUS_EVENT_ZONE_INVALID) { + dbus_emit_zone_invalid(update->zone->name, 0); + } + } else if (update->validation_hint.warning != KNOT_EOK) { + log_validation_error(update, msg_valid, update->validation_hint.warning, true); + if (conf->cache.srv_dbus_event & DBUS_EVENT_ZONE_INVALID) { + dbus_emit_zone_invalid(update->zone->name, update->validation_hint.remaining_secs); + } + } else { + log_zone_info(update->zone->name, "DNSSEC, %svalidation successful, checked RRSIGs %zu", + msg_valid, ctx.stats->rrsig_count); + } + + conf_val_t val = conf_zone_get(conf, C_DNSSEC_VALIDATION, update->zone->name); + bool configured = conf_bool(&val); + bool bogus = (ret != KNOT_EOK); + bool running = (update->zone->contents == update->new_cont); + bool may_expire = zone_is_slave(conf, update->zone); + knot_time_t expire = (ctx.stats != NULL ? ctx.stats->expire : 0); + assert(bogus || knot_time_geq(expire, ctx.now)); + + if (running && bogus && may_expire) { + zone_events_schedule_now(update->zone, ZONE_EVENT_EXPIRE); + } + if (configured && !bogus) { + if (!incremental) { + zone_events_schedule_at(update->zone, ZONE_EVENT_VALIDATE, 0); // cancel previously planned re-check when fully re-checked + } + zone_events_schedule_at(update->zone, ZONE_EVENT_VALIDATE, // this works for incremental verify as well, re-planning on later + knot_time_add(expire, 1)); // is a NOOP, sooner is proper + } + } + kdnssec_ctx_deinit(&ctx); + return ret; } diff --git a/src/knot/dnssec/zone-events.h b/src/knot/dnssec/zone-events.h index 462f87a..2f75614 100644 --- a/src/knot/dnssec/zone-events.h +++ b/src/knot/dnssec/zone-events.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,10 +16,7 @@ #pragma once -#include - -#include "knot/zone/zone.h" -#include "knot/updates/changesets.h" +#include "contrib/time.h" #include "knot/updates/zone-update.h" #include "knot/dnssec/context.h" @@ -53,17 +50,6 @@ typedef struct { bool plan_dnskey_sync; } zone_sign_reschedule_t; -/*! - * \brief Generate/rollover keys in keystore as needed. - * - * \param kctx Pointers to the keytore, policy, etc. - * \param zone_name Zone name. - * - * \return Error code, KNOT_EOK if successful. - */ -int knot_dnssec_sign_process_events(const kdnssec_ctx_t *kctx, - const knot_dname_t *zone_name); - /*! * \brief DNSSEC re-sign zone, store new records into changeset. Valid signatures * and NSEC(3) records will not be changed. @@ -130,7 +116,9 @@ knot_time_t knot_dnssec_failover_delay(const kdnssec_ctx_t *ctx); * \param conf Knot configuration. * \param now If not zero: adjust "now" to this timestamp. * \param incremental Try to validate incrementally. + * \param log_plan Log the result and plan subsequent validation event. * * \return KNOT_E* */ -int knot_dnssec_validate_zone(zone_update_t *update, conf_t *conf, knot_time_t now, bool incremental); +int knot_dnssec_validate_zone(zone_update_t *update, conf_t *conf, + knot_time_t now, bool incremental, bool log_plan); diff --git a/src/knot/dnssec/zone-sign.c b/src/knot/dnssec/zone-sign.c index 62f809e..3cd2420 100644 --- a/src/knot/dnssec/zone-sign.c +++ b/src/knot/dnssec/zone-sign.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -209,7 +209,6 @@ bool rrsig_covers_type(const knot_rrset_t *rrsig, uint16_t type) * \param skip_crypto All RRSIGs in this node have been verified, just check validity. * \param changeset Changeset to be updated. * \param update Zone update to be updated. Exactly one of "changeset" and "update" must be NULL! - * \param expires_at Earliest RRSIG expiration. * * \return Error code, KNOT_EOK if successful. */ @@ -218,8 +217,7 @@ static int add_missing_rrsigs(const knot_rrset_t *covered, zone_sign_ctx_t *sign_ctx, bool skip_crypto, changeset_t *changeset, - zone_update_t *update, - knot_time_t *expires_at) + zone_update_t *update) { assert(!knot_rrset_empty(covered)); assert(sign_ctx); @@ -258,11 +256,14 @@ static int add_missing_rrsigs(const knot_rrset_t *covered, sign_ctx->dnssec_ctx, refresh, skip_crypto, NULL, &valid_at)) { knot_rdata_t *valid_rr = knot_rdataset_at(&rrsigs->rrs, valid_at); result = knot_rdataset_remove(&to_remove.rrs, valid_rr, NULL); - note_earliest_expiration(valid_rr, sign_ctx->dnssec_ctx->now, expires_at); + knot_spin_lock(&sign_ctx->dnssec_ctx->stats->lock); + note_earliest_expiration(valid_rr, sign_ctx->dnssec_ctx->now, + &sign_ctx->dnssec_ctx->stats->expire); + knot_spin_unlock(&sign_ctx->dnssec_ctx->stats->lock); continue; } result = knot_sign_rrset(&to_add, covered, key->key, sign_ctx->sign_ctxs[i], - sign_ctx->dnssec_ctx, NULL, expires_at); + sign_ctx->dnssec_ctx, NULL); } if (!knot_rrset_empty(&to_remove) && result == KNOT_EOK) { @@ -306,9 +307,10 @@ static bool key_used(bool ksk, bool zsk, uint16_t type, int knot_validate_rrsigs(const knot_rrset_t *covered, const knot_rrset_t *rrsigs, zone_sign_ctx_t *sign_ctx, - bool skip_crypto) + bool skip_crypto, + knot_time_t *valid_until) { - if (covered == NULL || rrsigs == NULL || sign_ctx == NULL) { + if (covered == NULL || rrsigs == NULL || sign_ctx == NULL || valid_until == NULL) { return KNOT_EINVAL; } @@ -327,7 +329,14 @@ int knot_validate_rrsigs(const knot_rrset_t *covered, if (valid_signature_exists(covered, rrsigs, key->key, sign_ctx->sign_ctxs[i], sign_ctx->dnssec_ctx, 0, skip_crypto, val_inval_map, &valid_at)) { valid_exists = true; + knot_rdata_t *valid_rr = knot_rdataset_at(&rrsigs->rrs, valid_at); + note_earliest_expiration(valid_rr, sign_ctx->dnssec_ctx->now, valid_until); } + + knot_spin_lock(&sign_ctx->dnssec_ctx->stats->lock); + sign_ctx->dnssec_ctx->stats->rrsig_count++; + sign_ctx->dnssec_ctx->stats->expire = knot_time_min(sign_ctx->dnssec_ctx->stats->expire, *valid_until); + knot_spin_unlock(&sign_ctx->dnssec_ctx->stats->lock); } for (int i = 0; i < rrsigs->rrs.count; i++) { @@ -398,7 +407,7 @@ static int force_resign_rrset(const knot_rrset_t *covered, } } - return add_missing_rrsigs(covered, NULL, sign_ctx, false, changeset, NULL, NULL); + return add_missing_rrsigs(covered, NULL, sign_ctx, false, changeset, NULL); } /*! @@ -409,7 +418,6 @@ static int force_resign_rrset(const knot_rrset_t *covered, * \param sign_ctx Local zone signing context. * \param skip_crypto All RRSIGs in this node have been verified, just check validity. * \param changeset Changeset to be updated. - * \param expires_at Current earliest expiration, will be updated. * * \return Error code, KNOT_EOK if successful. */ @@ -417,12 +425,11 @@ static int resign_rrset(const knot_rrset_t *covered, const knot_rrset_t *rrsigs, zone_sign_ctx_t *sign_ctx, bool skip_crypto, - changeset_t *changeset, - knot_time_t *expires_at) + changeset_t *changeset) { assert(!knot_rrset_empty(covered)); - return add_missing_rrsigs(covered, rrsigs, sign_ctx, skip_crypto, changeset, NULL, expires_at); + return add_missing_rrsigs(covered, rrsigs, sign_ctx, skip_crypto, changeset, NULL); } static int remove_standalone_rrsigs(const zone_node_t *node, @@ -463,14 +470,13 @@ static int remove_standalone_rrsigs(const zone_node_t *node, * \param node Node to be signed. * \param sign_ctx Local zone signing context. * \param changeset Changeset to be updated. - * \param expires_at Current earliest expiration, will be updated. + * \param hint Out: if DNSSEC validation failed, hint why and where. * * \return Error code, KNOT_EOK if successful. */ static int sign_node_rrsets(const zone_node_t *node, zone_sign_ctx_t *sign_ctx, changeset_t *changeset, - knot_time_t *expires_at, dnssec_validation_hint_t *hint) { assert(node); @@ -499,17 +505,25 @@ static int sign_node_rrsets(const zone_node_t *node, } if (sign_ctx->dnssec_ctx->validation_mode) { - result = knot_validate_rrsigs(&rrset, &rrsigs, sign_ctx, skip_crypto); + knot_time_t until = 0; + result = knot_validate_rrsigs(&rrset, &rrsigs, sign_ctx, skip_crypto, &until); + knot_time_t diff = knot_time_diff(until, sign_ctx->dnssec_ctx->now); if (result != KNOT_EOK) { hint->node = node->owner; hint->rrtype = rrset.type; + } else if (diff < sign_ctx->dnssec_ctx->policy->rrsig_refresh_before) { + hint->node = node->owner; + hint->rrtype = rrset.type; + hint->warning = KNOT_ESOON_EXPIRE; + assert(until > 0); + hint->remaining_secs = MAX(0, diff); } } else if (sign_ctx->dnssec_ctx->rrsig_drop_existing) { result = force_resign_rrset(&rrset, &rrsigs, sign_ctx, changeset); } else { result = resign_rrset(&rrset, &rrsigs, sign_ctx, skip_crypto, - changeset, expires_at); + changeset); } } @@ -526,7 +540,6 @@ typedef struct { zone_tree_t *tree; zone_sign_ctx_t *sign_ctx; changeset_t changeset; - knot_time_t expires_at; dnssec_validation_hint_t *hint; size_t num_threads; size_t thread_index; @@ -557,11 +570,7 @@ static int sign_node(zone_node_t *node, void *data) return KNOT_EOK; } - int result = sign_node_rrsets(node, args->sign_ctx, - &args->changeset, &args->expires_at, - args->hint); - - return result; + return sign_node_rrsets(node, args->sign_ctx, &args->changeset, args->hint); } static void *tree_sign_thread(void *_arg) @@ -585,7 +594,6 @@ static int set_signed(zone_node_t *node, _unused_ void *data) * \param zone_keys Zone keys. * \param policy DNSSEC policy. * \param update Zone update structure to be updated. - * \param expires_at Expiration time of the oldest signature in zone. * * \return Error code, KNOT_EOK if successful. */ @@ -593,8 +601,7 @@ static int zone_tree_sign(zone_tree_t *tree, size_t num_threads, zone_keyset_t *zone_keys, const kdnssec_ctx_t *dnssec_ctx, - zone_update_t *update, - knot_time_t *expires_at) + zone_update_t *update) { assert(zone_keys || dnssec_ctx->validation_mode); assert(dnssec_ctx); @@ -603,7 +610,6 @@ static int zone_tree_sign(zone_tree_t *tree, int ret = KNOT_EOK; node_sign_args_t args[num_threads]; memset(args, 0, sizeof(args)); - *expires_at = knot_time_plus(dnssec_ctx->now, dnssec_ctx->policy->rrsig_lifetime); // init context structures for (size_t i = 0; i < num_threads; i++) { @@ -619,7 +625,6 @@ static int zone_tree_sign(zone_tree_t *tree, if (ret != KNOT_EOK) { break; } - args[i].expires_at = 0; args[i].hint = &update->validation_hint; args[i].num_threads = num_threads; args[i].thread_index = i; @@ -662,7 +667,6 @@ static int zone_tree_sign(zone_tree_t *tree, ret = args[i].errcode; if (ret == KNOT_EOK && !dnssec_ctx->validation_mode) { ret = zone_update_apply_changeset(update, &args[i].changeset); // _fix not needed - *expires_at = knot_time_min(*expires_at, args[i].expires_at); } } } @@ -701,10 +705,9 @@ static int rrset_add_zone_ds(knot_rrset_t *rrset, zone_key_t *zone_key, dnssec_k int knot_zone_sign(zone_update_t *update, zone_keyset_t *zone_keys, - const kdnssec_ctx_t *dnssec_ctx, - knot_time_t *expire_at) + const kdnssec_ctx_t *dnssec_ctx) { - if (!update || !dnssec_ctx || !expire_at || + if (!update || !dnssec_ctx || dnssec_ctx->policy->signing_threads < 1 || (zone_keys == NULL && !dnssec_ctx->validation_mode)) { return KNOT_EINVAL; @@ -712,16 +715,14 @@ int knot_zone_sign(zone_update_t *update, int result; - knot_time_t normal_expire = 0; result = zone_tree_sign(update->new_cont->nodes, dnssec_ctx->policy->signing_threads, - zone_keys, dnssec_ctx, update, &normal_expire); + zone_keys, dnssec_ctx, update); if (result != KNOT_EOK) { return result; } - knot_time_t nsec3_expire = 0; result = zone_tree_sign(update->new_cont->nsec3_nodes, dnssec_ctx->policy->signing_threads, - zone_keys, dnssec_ctx, update, &nsec3_expire); + zone_keys, dnssec_ctx, update); if (result != KNOT_EOK) { return result; } @@ -732,8 +733,6 @@ int knot_zone_sign(zone_update_t *update, result = zone_tree_apply(whole ? update->new_cont->nsec3_nodes : update->a_ctx->nsec3_ptrs, set_signed, NULL); } - *expire_at = knot_time_min(normal_expire, nsec3_expire); - return result; } @@ -948,7 +947,7 @@ bool knot_zone_sign_use_key(const zone_key_t *key, const knot_rrset_t *covered) } } -static int sign_in_changeset(zone_node_t *node, uint16_t rrtype, knot_rrset_t *rrsigs, +static int sign_in_changeset(zone_node_t *node, uint16_t rrtype, zone_sign_ctx_t *sign_ctx, int ret_prev, bool skip_crypto, zone_update_t *up) { @@ -959,7 +958,8 @@ static int sign_in_changeset(zone_node_t *node, uint16_t rrtype, knot_rrset_t *r if (knot_rrset_empty(&rr)) { return KNOT_EOK; } - return add_missing_rrsigs(&rr, rrsigs, sign_ctx, skip_crypto, NULL, up, NULL); + knot_rrset_t rrsigs = node_rrset(node, KNOT_RRTYPE_RRSIG); + return add_missing_rrsigs(&rr, &rrsigs, sign_ctx, skip_crypto, NULL, up); } int knot_zone_sign_nsecs_in_changeset(const zone_keyset_t *zone_keys, @@ -982,10 +982,9 @@ int knot_zone_sign_nsecs_in_changeset(const zone_keyset_t *zone_keys, zone_node_t *n = zone_tree_it_val(&it); bool skip_crypto = (n->flags & NODE_FLAGS_RRSIGS_VALID) && !dnssec_ctx->keytag_conflict; - knot_rrset_t rrsigs = node_rrset(n, KNOT_RRTYPE_RRSIG); - ret = sign_in_changeset(n, KNOT_RRTYPE_NSEC, &rrsigs, sign_ctx, ret, skip_crypto, update); - ret = sign_in_changeset(n, KNOT_RRTYPE_NSEC3, &rrsigs, sign_ctx, ret, skip_crypto, update); - ret = sign_in_changeset(n, KNOT_RRTYPE_NSEC3PARAM, &rrsigs, sign_ctx, ret, skip_crypto, update); + ret = sign_in_changeset(n, KNOT_RRTYPE_NSEC, sign_ctx, ret, skip_crypto, update); + ret = sign_in_changeset(n, KNOT_RRTYPE_NSEC3, sign_ctx, ret, skip_crypto, update); + ret = sign_in_changeset(n, KNOT_RRTYPE_NSEC3PARAM, sign_ctx, ret, skip_crypto, update); if (ret == KNOT_EOK) { n->flags |= NODE_FLAGS_RRSIGS_VALID; // non-NSEC RRSIGs had been validated in knot_dnssec_sign_update() @@ -1023,10 +1022,9 @@ bool knot_zone_sign_rr_should_be_signed(const zone_node_t *node, int knot_zone_sign_update(zone_update_t *update, zone_keyset_t *zone_keys, - const kdnssec_ctx_t *dnssec_ctx, - knot_time_t *expire_at) + const kdnssec_ctx_t *dnssec_ctx) { - if (update == NULL || dnssec_ctx == NULL || expire_at == NULL || + if (update == NULL || dnssec_ctx == NULL || dnssec_ctx->policy->signing_threads < 1 || (zone_keys == NULL && !dnssec_ctx->validation_mode)) { return KNOT_EINVAL; @@ -1038,16 +1036,16 @@ int knot_zone_sign_update(zone_update_t *update, * If so, we have to sign the whole zone. */ const bool full_sign = apex_dnssec_changed(update); if (full_sign) { - ret = knot_zone_sign(update, zone_keys, dnssec_ctx, expire_at); + ret = knot_zone_sign(update, zone_keys, dnssec_ctx); } else { ret = zone_tree_sign(update->a_ctx->node_ptrs, dnssec_ctx->policy->signing_threads, - zone_keys, dnssec_ctx, update, expire_at); + zone_keys, dnssec_ctx, update); if (ret == KNOT_EOK) { ret = zone_tree_apply(update->a_ctx->node_ptrs, set_signed, NULL); } if (ret == KNOT_EOK && dnssec_ctx->validation_mode) { ret = zone_tree_sign(update->a_ctx->nsec3_ptrs, dnssec_ctx->policy->signing_threads, - zone_keys, dnssec_ctx, update, expire_at); + zone_keys, dnssec_ctx, update); } if (ret == KNOT_EOK && dnssec_ctx->validation_mode) { ret = zone_tree_apply(update->a_ctx->nsec3_ptrs, set_signed, NULL); diff --git a/src/knot/dnssec/zone-sign.h b/src/knot/dnssec/zone-sign.h index ba6e2b2..480bcf9 100644 --- a/src/knot/dnssec/zone-sign.h +++ b/src/knot/dnssec/zone-sign.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -81,13 +81,15 @@ keyptr_dynarray_t knot_zone_sign_get_cdnskeys(const kdnssec_ctx_t *ctx, * \param rrsigs RRSIG with signatures. * \param sign_ctx Signing context (with keys == NULL) * \param skip_crypto Crypto operations might be skipped as they had been successful earlier. + * \param valid_until End of soonest RRSIG validity. * * \return KNOT_E* */ int knot_validate_rrsigs(const knot_rrset_t *covered, const knot_rrset_t *rrsigs, zone_sign_ctx_t *sign_ctx, - bool skip_crypto); + bool skip_crypto, + knot_time_t *valid_until); /*! * \brief Update zone signatures and store performed changes in update. @@ -97,14 +99,12 @@ int knot_validate_rrsigs(const knot_rrset_t *covered, * \param update Zone Update containing the zone and to be updated with new DNSKEYs and RRSIGs. * \param zone_keys Zone keys. * \param dnssec_ctx DNSSEC context. - * \param expire_at Time, when the oldest signature in the zone expires. * * \return Error code, KNOT_EOK if successful. */ int knot_zone_sign(zone_update_t *update, zone_keyset_t *zone_keys, - const kdnssec_ctx_t *dnssec_ctx, - knot_time_t *expire_at); + const kdnssec_ctx_t *dnssec_ctx); /*! * \brief Sign NSEC/NSEC3 nodes in changeset and update the changeset. @@ -138,14 +138,12 @@ bool knot_zone_sign_rr_should_be_signed(const zone_node_t *node, * \param update Zone Update structure. * \param zone_keys Zone keys. * \param dnssec_ctx DNSSEC context. - * \param expire_at Time, when the oldest signature in the update expires. * * \return Error code, KNOT_EOK if successful. */ int knot_zone_sign_update(zone_update_t *update, zone_keyset_t *zone_keys, - const kdnssec_ctx_t *dnssec_ctx, - knot_time_t *expire_at); + const kdnssec_ctx_t *dnssec_ctx); /*! * \brief Force re-sign of a RRSet in zone apex. diff --git a/src/knot/events/events.c b/src/knot/events/events.c index f0de68e..6224006 100644 --- a/src/knot/events/events.c +++ b/src/knot/events/events.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,6 +46,7 @@ static const event_info_t EVENT_INFO[] = { { ZONE_EVENT_BACKUP, event_backup, "backup/restore" }, { ZONE_EVENT_NOTIFY, event_notify, "notify" }, { ZONE_EVENT_DNSSEC, event_dnssec, "re-sign" }, + { ZONE_EVENT_VALIDATE, event_validate, "DNSSEC-validate" }, { ZONE_EVENT_UFREEZE, event_ufreeze, "update-freeze" }, { ZONE_EVENT_UTHAW, event_uthaw, "update-thaw" }, { ZONE_EVENT_DS_CHECK, event_ds_check, "DS-check" }, diff --git a/src/knot/events/events.h b/src/knot/events/events.h index a32d195..cf1b362 100644 --- a/src/knot/events/events.h +++ b/src/knot/events/events.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,6 +38,7 @@ typedef enum zone_event_type { ZONE_EVENT_BACKUP, ZONE_EVENT_NOTIFY, ZONE_EVENT_DNSSEC, + ZONE_EVENT_VALIDATE, ZONE_EVENT_UFREEZE, ZONE_EVENT_UTHAW, ZONE_EVENT_DS_CHECK, diff --git a/src/knot/events/handlers.h b/src/knot/events/handlers.h index d74fd8a..45b7b45 100644 --- a/src/knot/events/handlers.h +++ b/src/knot/events/handlers.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,6 +39,8 @@ int event_dnssec(conf_t *conf, zone_t *zone); /*! \brief NOT A HANDLER, just a helper function to reschedule based on reschedule_t */ void event_dnssec_reschedule(conf_t *conf, zone_t *zone, const zone_sign_reschedule_t *refresh, bool zone_changed); +/*! \brief Validate the wole zone's DNSSEC. */ +int event_validate(conf_t *conf, zone_t *zone); /*! \brief Freeze those events causing zone contents change. */ int event_ufreeze(conf_t *conf, zone_t *zone); /*! \brief Unfreeze zone updates. */ diff --git a/src/knot/events/handlers/dnskey_sync.c b/src/knot/events/handlers/dnskey_sync.c index c6d80ff..018f66b 100644 --- a/src/knot/events/handlers/dnskey_sync.c +++ b/src/knot/events/handlers/dnskey_sync.c @@ -26,8 +26,8 @@ #define DNSKEY_SYNC_LOG(priority, zone, remote, flags, fmt, ...) \ ns_log(priority, zone, LOG_OPERATION_DNSKEY_SYNC, LOG_DIRECTION_OUT, &(remote)->addr, \ - ((flags) & KNOT_REQUESTOR_QUIC) ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_TCP, \ - ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, fmt, ## __VA_ARGS__) + flags2proto(flags), ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, \ + fmt, ## __VA_ARGS__) static const unsigned remote_rrs[] = { KNOT_RRTYPE_DNSKEY, KNOT_RRTYPE_CDNSKEY, KNOT_RRTYPE_CDS }; #define REMOTE_NTYPES (sizeof(remote_rrs) / sizeof(remote_rrs[0])) diff --git a/src/knot/events/handlers/ds_push.c b/src/knot/events/handlers/ds_push.c index be7621f..761b800 100644 --- a/src/knot/events/handlers/ds_push.c +++ b/src/knot/events/handlers/ds_push.c @@ -38,8 +38,8 @@ struct ds_push_data { #define DS_PUSH_LOG(priority, zone, remote, flags, fmt, ...) \ ns_log(priority, zone, LOG_OPERATION_DS_PUSH, LOG_DIRECTION_OUT, &(remote)->addr, \ - ((flags) & KNOT_REQUESTOR_QUIC) ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_TCP, \ - ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, fmt, ## __VA_ARGS__) + flags2proto(flags), ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, \ + fmt, ## __VA_ARGS__) static const knot_rdata_t remove_cds = { 5, { 0, 0, 0, 0, 0 } }; @@ -53,7 +53,7 @@ static int ds_push_begin(knot_layer_t *layer, void *params) static int parent_soa_produce(struct ds_push_data *data, knot_pkt_t *pkt) { assert(data->parent_query[0] != '\0'); - data->parent_query = knot_wire_next_label(data->parent_query, NULL); + data->parent_query = knot_dname_next_label(data->parent_query); int ret = knot_pkt_put_question(pkt, data->parent_query, KNOT_CLASS_IN, KNOT_RRTYPE_SOA); if (ret != KNOT_EOK) { diff --git a/src/knot/events/handlers/notify.c b/src/knot/events/handlers/notify.c index 9dae70a..9a8b8df 100644 --- a/src/knot/events/handlers/notify.c +++ b/src/knot/events/handlers/notify.c @@ -84,8 +84,8 @@ static const knot_layer_api_t NOTIFY_API = { #define NOTIFY_OUT_LOG(priority, zone, remote, flags, fmt, ...) \ ns_log(priority, zone, LOG_OPERATION_NOTIFY, LOG_DIRECTION_OUT, &(remote)->addr, \ - ((flags) & KNOT_REQUESTOR_QUIC) ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_TCP, \ - ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, fmt, ## __VA_ARGS__) + flags2proto(flags), ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, \ + fmt, ## __VA_ARGS__) static int send_notify(conf_t *conf, zone_t *zone, const knot_rrset_t *soa, const conf_remote_t *slave, int timeout, bool retry) diff --git a/src/knot/events/handlers/refresh.c b/src/knot/events/handlers/refresh.c index 8099df6..6c22707 100644 --- a/src/knot/events/handlers/refresh.c +++ b/src/knot/events/handlers/refresh.c @@ -68,24 +68,24 @@ * \endverbatim */ -#define PROTO(data) \ - ((data)->layer->flags & KNOT_REQUESTOR_QUIC) ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_TCP - #define REFRESH_LOG(priority, data, msg...) \ ns_log(priority, (data)->zone->name, LOG_OPERATION_REFRESH, LOG_DIRECTION_NONE, \ &(data)->remote->addr, 0, false, (data)->remote->key.name, msg) #define REFRESH_LOG_PROTO(priority, data, msg...) \ ns_log(priority, (data)->zone->name, LOG_OPERATION_REFRESH, LOG_DIRECTION_NONE, \ - &(data)->remote->addr, PROTO(data), (data)->layer->flags & KNOT_REQUESTOR_REUSED, (data)->remote->key.name, msg) + &(data)->remote->addr, flags2proto((data)->layer->flags), \ + (data)->layer->flags & KNOT_REQUESTOR_REUSED, (data)->remote->key.name, msg) #define AXFRIN_LOG(priority, data, msg...) \ ns_log(priority, (data)->zone->name, LOG_OPERATION_AXFR, LOG_DIRECTION_IN, \ - &(data)->remote->addr, PROTO(data), (data)->layer->flags & KNOT_REQUESTOR_REUSED, (data)->remote->key.name, msg) + &(data)->remote->addr, flags2proto((data)->layer->flags), \ + (data)->layer->flags & KNOT_REQUESTOR_REUSED, (data)->remote->key.name, msg) #define IXFRIN_LOG(priority, data, msg...) \ ns_log(priority, (data)->zone->name, LOG_OPERATION_IXFR, LOG_DIRECTION_IN, \ - &(data)->remote->addr, PROTO(data), (data)->layer->flags & KNOT_REQUESTOR_REUSED, (data)->remote->key.name, msg) + &(data)->remote->addr, flags2proto((data)->layer->flags), \ + (data)->layer->flags & KNOT_REQUESTOR_REUSED, (data)->remote->key.name, msg) enum state { REFRESH_STATE_INVALID = 0, @@ -123,7 +123,7 @@ struct refresh_data { int ret; //!< Error code. enum state state; //!< Event processing state. - enum xfr_type xfr_type; //!< Transer type (mostly IXFR versus AXFR). + enum xfr_type xfr_type; //!< Transfer type (mostly IXFR versus AXFR). bool axfr_style_ixfr; //!< Master responded with AXFR-style-IXFR. knot_rrset_t *initial_soa_copy; //!< Copy of the received initial SOA. struct xfr_stats stats; //!< Transfer statistics. @@ -1200,14 +1200,33 @@ static int transfer_consume(knot_layer_t *layer, knot_pkt_t *pkt) // Transfer completed if (next == KNOT_STATE_DONE) { // Log transfer even if we still can fail + uint32_t serial; + switch (data->xfr_type) { + case XFR_TYPE_AXFR: + serial = zone_contents_serial(data->axfr.zone); + break; + case XFR_TYPE_IXFR: + serial = knot_soa_serial(data->ixfr.final_soa->rrs.rdata); + break; + case XFR_TYPE_UPTODATE: + if (slave_zone_serial(data->zone, data->conf, &serial) == KNOT_EOK) { + break; + } + // FALLTHROUGH + default: + serial = 0; + } + char serial_log[32]; + (void)snprintf(serial_log, sizeof(serial_log), + " remote serial %u,", serial); xfr_log_finished(data->zone->name, data->xfr_type == XFR_TYPE_IXFR || data->xfr_type == XFR_TYPE_UPTODATE ? LOG_OPERATION_IXFR : LOG_OPERATION_AXFR, LOG_DIRECTION_IN, &data->remote->addr, - (layer->flags & KNOT_REQUESTOR_QUIC ? - KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_TCP), - data->remote->key.name, &data->stats); + flags2proto(layer->flags), + data->remote->key.name, + serial_log, &data->stats); /* * TODO: Move finialization into finish diff --git a/src/knot/events/handlers/update.c b/src/knot/events/handlers/update.c index b4092a3..2c6758c 100644 --- a/src/knot/events/handlers/update.c +++ b/src/knot/events/handlers/update.c @@ -28,6 +28,9 @@ #include "knot/zone/zone.h" #include "libdnssec/random.h" #include "libknot/libknot.h" +#include "libknot/quic/quic_conn.h" +#include "libknot/quic/quic.h" +#include "libknot/quic/tls.h" #include "contrib/net.h" #include "contrib/time.h" @@ -51,6 +54,33 @@ static void init_qdata_from_request(knotd_qdata_t *qdata, qdata->extra->zone = zone; } +#ifdef ENABLE_QUIC +static int ddnsq_alloc_reply(knot_quic_reply_t *r) +{ + r->out_payload->iov_len = KNOT_WIRE_MAX_PKTSIZE; + + return KNOT_EOK; +} + +static int ddnsq_send_reply(knot_quic_reply_t *r) +{ + int fd = *(int *)r->sock; + int ret = net_dgram_send(fd, r->out_payload->iov_base, r->out_payload->iov_len, r->ip_rem); + if (ret < 0) { + return knot_map_errno(); + } else if (ret == r->out_payload->iov_len) { + return KNOT_EOK; + } else { + return KNOT_EAGAIN; + } +} + +static void ddnsq_free_reply(knot_quic_reply_t *r) +{ + r->out_payload->iov_len = 0; +} +#endif // ENABLE_QUIC + static int check_prereqs(knot_request_t *request, zone_update_t *update, knotd_qdata_t *qdata) @@ -65,6 +95,15 @@ static int check_prereqs(knot_request_t *request, return ret; } + ret = ddns_precheck_update(request->query, update, &rcode); + if (ret != KNOT_EOK) { + UPDATE_LOG(LOG_WARNING, qdata, "broken update format (%s)", + knot_strerror(ret)); + assert(rcode != KNOT_RCODE_NOERROR); + knot_wire_set_rcode(request->resp->wire, rcode); + return ret; + } + return KNOT_EOK; } @@ -104,6 +143,7 @@ static int process_bulk(zone_t *zone, list_t *requests, zone_update_t *up) knot_request_t *req = node->d; // Init qdata structure for logging (unique per-request). knotd_qdata_params_t params = { + .proto = flags2proto(req->flags), .remote = &req->remote }; knotd_qdata_t qdata; @@ -118,6 +158,8 @@ static int process_bulk(zone_t *zone, list_t *requests, zone_update_t *up) ret = process_single_update(req, up, &qdata); if (ret != KNOT_EOK) { + log_zone_error(zone->name, "DDNS, dropping %zu updates in a bulk", + list_size(requests)); return ret; } } @@ -338,6 +380,39 @@ static void send_update_response(conf_t *conf, zone_t *zone, knot_request_t *req (void)process_query_sign_response(req->resp, &qdata); } + if (net_is_stream(req->fd) && req->tls_req_ctx.conn != NULL) { + (void)knot_tls_send_dns(req->tls_req_ctx.conn, + req->resp->wire, req->resp->size); + knot_tls_conn_block(req->tls_req_ctx.conn, false); + } +#ifdef ENABLE_QUIC + else if (req->quic_conn != NULL) { + assert(!net_is_stream(req->fd)); + uint8_t op_buf[KNOT_WIRE_MAX_PKTSIZE]; + struct iovec out_payload = { .iov_base = op_buf, .iov_len = sizeof(op_buf) }; + knot_quic_reply_t rpl = { + .ip_rem = &req->remote, + .ip_loc = &req->source, + .in_payload = NULL, + .out_payload = &out_payload, + .sock = &req->fd, + .alloc_reply = ddnsq_alloc_reply, + .send_reply = ddnsq_send_reply, + .free_reply = ddnsq_free_reply + }; + + void *succ = knot_quic_stream_add_data(req->quic_conn, req->quic_stream, + req->resp->wire, req->resp->size); + if (succ != NULL) { // else ENOMEM + (void)knot_quic_send(req->quic_conn->quic_table, req->quic_conn, + &rpl, 4, KNOT_QUIC_SEND_IGNORE_BLOCKED); + } + knot_quic_conn_block(req->quic_conn, false); + } else // NOTE ties to 'if' below +#else + assert(req->quic_conn == NULL); +#endif // ENABLE_QUIC + if (net_is_stream(req->fd)) { net_dns_tcp_send(req->fd, req->resp->wire, req->resp->size, conf->cache.srv_tcp_remote_io_timeout, NULL); @@ -348,22 +423,13 @@ static void send_update_response(conf_t *conf, zone_t *zone, knot_request_t *req } } -static void free_request(knot_request_t *req) -{ - close(req->fd); - knot_pkt_free(req->query); - knot_pkt_free(req->resp); - dnssec_binary_free(&req->sign.tsig_key.secret); - free(req); -} - static void send_update_responses(conf_t *conf, zone_t *zone, list_t *updates) { ptrnode_t *node, *nxt; WALK_LIST_DELSAFE(node, nxt, *updates) { knot_request_t *req = node->d; send_update_response(conf, zone, req); - free_request(req); + knot_request_free(req, NULL); } ptrlist_free(updates, NULL); } diff --git a/src/knot/events/handlers/validate.c b/src/knot/events/handlers/validate.c new file mode 100644 index 0000000..e410b4f --- /dev/null +++ b/src/knot/events/handlers/validate.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include "knot/common/log.h" +#include "knot/conf/conf.h" +#include "knot/dnssec/zone-events.h" +#include "knot/zone/zone.h" + +int event_validate(conf_t *conf, zone_t *zone) +{ + knot_time_t now = knot_time(); + zone_update_t fake_upd = { + .zone = zone, + .new_cont = zone->contents, + // .validation_hint is zeroed + }; + + log_zone_info(zone->name, "DNSSEC, re-validating zone fully"); + + return knot_dnssec_validate_zone(&fake_upd, conf, now, false, true); +} diff --git a/src/knot/events/replan.c b/src/knot/events/replan.c index ed03fe1..29a07ea 100644 --- a/src/knot/events/replan.c +++ b/src/knot/events/replan.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -108,6 +108,9 @@ void replan_from_timers(conf_t *conf, zone_t *zone) if (zone->contents == NULL && zone->timers.last_refresh_ok) { // zone disappeared w/o expiry refresh = now; } + if (refresh == 0) { // sanitize in case of concurrent purge event + refresh = now; + } assert(refresh > 0); } diff --git a/src/knot/include/module.h b/src/knot/include/module.h index 15a9077..9998e48 100644 --- a/src/knot/include/module.h +++ b/src/knot/include/module.h @@ -36,7 +36,7 @@ /*** Query module API. ***/ /*! Current module ABI version. */ -#define KNOTD_MOD_ABI_VERSION 500 +#define KNOTD_MOD_ABI_VERSION 600 /*! Module configuration name prefix. */ #define KNOTD_MOD_NAME_PREFIX "mod-" @@ -354,7 +354,7 @@ knotd_conf_t knotd_conf_check_item(knotd_conf_check_args_t *args, const yp_name_t *item_name); /*! - * \brief Checks if address is in at least one of given ranges. + * Checks if address is in at least one of given ranges. * * \param[in] range * \param[in] addr @@ -393,11 +393,13 @@ typedef enum { KNOTD_QUERY_PROTO_UDP = KNOT_PROBE_PROTO_UDP, /*!< Pure UDP. */ KNOTD_QUERY_PROTO_TCP = KNOT_PROBE_PROTO_TCP, /*!< Pure TCP. */ KNOTD_QUERY_PROTO_QUIC = KNOT_PROBE_PROTO_QUIC, /*!< QUIC/UDP. */ + KNOTD_QUERY_PROTO_TLS = KNOT_PROBE_PROTO_TLS, /*!< TLS/TCP. */ } knotd_query_proto_t; /*! Query processing specific flags. */ typedef enum { - KNOTD_QUERY_FLAG_COOKIE = 1 << 0, /*!< Valid DNS Cookie indication. */ + KNOTD_QUERY_FLAG_COOKIE = 1 << 0, /*!< Valid DNS Cookie indication. */ + KNOTD_QUERY_FLAG_AUTHORIZED = 1 << 1, /*!< Successfully authorized operation. */ } knotd_query_flag_t; /*! Query processing data context parameters. */ @@ -411,6 +413,7 @@ typedef struct { void *server; /*!< Server object private item. */ const struct knot_xdp_msg *xdp_msg; /*!< Possible XDP message context. */ struct knot_quic_conn *quic_conn; /*!< QUIC connection context. */ + struct knot_tls_conn *tls_conn; /*!< TLS connection context. */ int64_t quic_stream; /*!< QUIC stream ID inside quic_conn. */ uint32_t measured_rtt; /*!< Measured RTT in usecs: QUIC or TCP-XDP. */ } knotd_qdata_params_t; @@ -493,6 +496,7 @@ knot_rrset_t knotd_qdata_zone_apex_rrset(const knotd_qdata_t *qdata, uint16_t ty * \param[in] qdata Query data. * \param[in] zone_name Optional zone name, the current one otherwise. * \param[in] node_name Optional node name, apex otherwise. + * \param[in] type RRSet type. * \param[out] out Destination rrset to store the output to. * * \return Error code (KNOT_ENOZONE, KNOT_EEMPTYZONE, KNOT_ENONODE), KNOT_EOK if success. @@ -501,6 +505,12 @@ int knotd_qdata_zone_rrset(const knotd_qdata_t *qdata, const knot_dname_t *zone_ const knot_dname_t *node_name, uint16_t type, knot_rrset_t *out); +/*! Transport protocol processing states. */ +typedef enum { + KNOTD_PROTO_STATE_PASS = 0, /*!< Process normally. */ + KNOTD_PROTO_STATE_BLOCK = 1, /*!< Block the packet/connection. */ +} knotd_proto_state_t; + /*! General query processing states. */ typedef enum { KNOTD_STATE_NOOP = 0, /*!< No response. */ @@ -509,7 +519,7 @@ typedef enum { KNOTD_STATE_FINAL = 6, /*!< Finished and finalized (QNAME, EDNS, TSIG). */ } knotd_state_t; -/*! brief Internet query processing states. */ +/*! Internet query processing states. */ typedef enum { KNOTD_IN_STATE_BEGIN, /*!< Begin name resolution. */ KNOTD_IN_STATE_NODATA, /*!< Positive result with NO data. */ @@ -523,14 +533,28 @@ typedef enum { /*! Query module processing stages. */ typedef enum { - KNOTD_STAGE_BEGIN = 0, /*!< Before query processing. */ - KNOTD_STAGE_PREANSWER, /*!< Before section processing. */ - KNOTD_STAGE_ANSWER, /*!< Answer section processing. */ - KNOTD_STAGE_AUTHORITY, /*!< Authority section processing. */ - KNOTD_STAGE_ADDITIONAL, /*!< Additional section processing. */ - KNOTD_STAGE_END, /*!< After query processing. */ + KNOTD_STAGE_PROTO_BEGIN = 0, /*!< Start of transport protocol processing. */ + KNOTD_STAGE_BEGIN, /*!< Before query processing. */ + KNOTD_STAGE_PREANSWER, /*!< Before section processing. */ + KNOTD_STAGE_ANSWER, /*!< Answer section processing. */ + KNOTD_STAGE_AUTHORITY, /*!< Authority section processing. */ + KNOTD_STAGE_ADDITIONAL, /*!< Additional section processing. */ + KNOTD_STAGE_END, /*!< After query processing. */ + KNOTD_STAGE_PROTO_END, /*!< End of transport protocol processing. */ } knotd_stage_t; +/*! + * Transport protocol processing hook. + * + * \param[in] state Current processing state. + * \param[in] params Processing parameters. + * \param[in] mod Module context. + * + * \return Next processing state. + */ +typedef knotd_proto_state_t (*knotd_mod_proto_hook_f) + (knotd_proto_state_t state, knotd_qdata_params_t *params, knotd_mod_t *mod); + /*! * General processing hook. * @@ -557,6 +581,17 @@ typedef knotd_state_t (*knotd_mod_hook_f) typedef knotd_in_state_t (*knotd_mod_in_hook_f) (knotd_in_state_t state, knot_pkt_t *pkt, knotd_qdata_t *qdata, knotd_mod_t *mod); +/*! + * Registers transport protocol processing module hook. + * + * \param[in] mod Module context. + * \param[in] stage Processing stage (KNOTD_STAGE_PROTO_BEGIN or KNOTD_STAGE_PROTO_END). + * \param[in] hook Module hook. + * + * \return Error code, KNOT_EOK if success. + */ +int knotd_mod_proto_hook(knotd_mod_t *mod, knotd_stage_t stage, knotd_mod_proto_hook_f hook); + /*! * Registers general processing module hook. * diff --git a/src/knot/modules/cookies/cookies.c b/src/knot/modules/cookies/cookies.c index 34c4b22..48eca7d 100644 --- a/src/knot/modules/cookies/cookies.c +++ b/src/knot/modules/cookies/cookies.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,19 +20,10 @@ #include "knot/include/module.h" #include "libknot/libknot.h" +#include "contrib/atomic.h" #include "contrib/string.h" #include "libdnssec/random.h" -#ifdef HAVE_ATOMIC -#define ATOMIC_SET(dst, val) __atomic_store_n(&(dst), (val), __ATOMIC_RELAXED) -#define ATOMIC_GET(src) __atomic_load_n(&(src), __ATOMIC_RELAXED) -#define ATOMIC_ADD(dst, val) __atomic_add_fetch(&(dst), (val), __ATOMIC_RELAXED) -#else -#define ATOMIC_SET(dst, val) ((dst) = (val)) -#define ATOMIC_GET(src) (src) -#define ATOMIC_ADD(dst, val) ((dst) += (val)) -#endif - #define BADCOOKIE_CTR_INIT 1 #define MOD_SECRET_LIFETIME "\x0F""secret-lifetime" @@ -59,13 +50,13 @@ int cookies_conf_check(knotd_conf_check_args_t *args) typedef struct { struct { - uint64_t variable; + knot_atomic_uint64_t variable; uint64_t constant; } secret; pthread_t update_secret; uint32_t secret_lifetime; uint32_t badcookie_slip; - uint16_t badcookie_ctr; // Counter for BADCOOKIE answers. + knot_atomic_uint16_t badcookie_ctr; // Counter for BADCOOKIE answers. } cookies_ctx_t; static void update_ctr(cookies_ctx_t *ctx) @@ -285,7 +276,7 @@ int cookies_load(knotd_mod_t *mod) } } -#ifndef HAVE_ATOMIC +#ifndef KNOT_HAVE_ATOMIC knotd_mod_log(mod, LOG_WARNING, "the module might work slightly wrong on this platform"); ctx->badcookie_slip = 1; #endif diff --git a/src/knot/modules/probe/probe.c b/src/knot/modules/probe/probe.c index 9207308..3e0a646 100644 --- a/src/knot/modules/probe/probe.c +++ b/src/knot/modules/probe/probe.c @@ -19,18 +19,11 @@ #include "knot/conf/schema.h" #include "knot/include/module.h" +#include "contrib/atomic.h" #include "contrib/string.h" #include "contrib/time.h" #include "libknot/libknot.h" -#ifdef HAVE_ATOMIC -#define ATOMIC_SET(dst, val) __atomic_store_n(&(dst), (val), __ATOMIC_RELAXED) -#define ATOMIC_GET(src) __atomic_load_n(&(src), __ATOMIC_RELAXED) -#else -#define ATOMIC_SET(dst, val) ((dst) = (val)) -#define ATOMIC_GET(src) (src) -#endif - #define MOD_PATH "\x04""path" #define MOD_CHANNELS "\x08""channels" #define MOD_MAX_RATE "\x08""max-rate" @@ -45,7 +38,7 @@ const yp_item_t probe_conf[] = { typedef struct { knot_probe_t **probes; size_t probe_count; - uint64_t *last_times; + knot_atomic_uint64_t *last_times; uint64_t min_diff_ns; char *path; } probe_ctx_t; @@ -139,7 +132,7 @@ int probe_load(knotd_mod_t *mod) return KNOT_ENOMEM; } - ctx->last_times = calloc(ctx->probe_count, sizeof(uint64_t)); + ctx->last_times = calloc(ctx->probe_count, sizeof(*ctx->last_times)); if (ctx->last_times == NULL) { free_probe_ctx(ctx); return KNOT_ENOMEM; diff --git a/src/knot/modules/rrl/Makefile.inc b/src/knot/modules/rrl/Makefile.inc index d82edf9..fbb9eb0 100644 --- a/src/knot/modules/rrl/Makefile.inc +++ b/src/knot/modules/rrl/Makefile.inc @@ -1,15 +1,20 @@ knot_modules_rrl_la_SOURCES = knot/modules/rrl/rrl.c \ knot/modules/rrl/functions.c \ - knot/modules/rrl/functions.h + knot/modules/rrl/functions.h \ + knot/modules/rrl/kru-generic.c \ + knot/modules/rrl/kru-avx2.c \ + knot/modules/rrl/kru.h +noinst_HEADERS = knot/modules/rrl/kru.inc.c EXTRA_DIST += knot/modules/rrl/rrl.rst if STATIC_MODULE_rrl libknotd_la_SOURCES += $(knot_modules_rrl_la_SOURCES) +libknotd_la_LIBADD += $(math_LIBS) endif if SHARED_MODULE_rrl knot_modules_rrl_la_LDFLAGS = $(KNOTD_MOD_LDFLAGS) knot_modules_rrl_la_CPPFLAGS = $(KNOTD_MOD_CPPFLAGS) -knot_modules_rrl_la_LIBADD = $(libcontrib_LIBS) +knot_modules_rrl_la_LIBADD = $(libcontrib_LIBS) $(math_LIBS) pkglib_LTLIBRARIES += knot/modules/rrl.la endif diff --git a/src/knot/modules/rrl/functions.c b/src/knot/modules/rrl/functions.c index df35394..01d89cb 100644 --- a/src/knot/modules/rrl/functions.c +++ b/src/knot/modules/rrl/functions.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,516 +14,223 @@ along with this program. If not, see . */ -#include +#include #include #include "knot/modules/rrl/functions.h" +#include "knot/modules/rrl/kru.h" +#include "contrib/macros.h" #include "contrib/musl/inet_ntop.h" -#include "contrib/openbsd/strlcat.h" #include "contrib/sockaddr.h" #include "contrib/time.h" -#include "libdnssec/error.h" #include "libdnssec/random.h" -/* Hopscotch defines. */ -#define HOP_LEN (sizeof(unsigned)*8) -/* Limits (class, ipv6 remote, dname) */ -#define RRL_CLSBLK_MAXLEN (1 + 8 + 255) -/* CIDR block prefix lengths for v4/v6 */ -#define RRL_V4_PREFIX_LEN 3 /* /24 */ -#define RRL_V6_PREFIX_LEN 7 /* /56 */ -/* Defaults */ -#define RRL_SSTART 2 /* 1/Nth of the rate for slow start */ -#define RRL_PSIZE_LARGE 1024 -#define RRL_CAPACITY 4 /* Window size in seconds */ -#define RRL_LOCK_GRANULARITY 32 /* Last digit granularity */ - -/* Classification */ -enum { - CLS_NULL = 0 << 0, /* Empty bucket. */ - CLS_NORMAL = 1 << 0, /* Normal response. */ - CLS_ERROR = 1 << 1, /* Error response. */ - CLS_NXDOMAIN = 1 << 2, /* NXDOMAIN (special case of error). */ - CLS_EMPTY = 1 << 3, /* Empty response. */ - CLS_LARGE = 1 << 4, /* Response size over threshold (1024k). */ - CLS_WILDCARD = 1 << 5, /* Wildcard query. */ - CLS_ANY = 1 << 6, /* ANY query (spec. class). */ - CLS_DNSSEC = 1 << 7 /* DNSSEC related RR query (spec. class) */ -}; +// CIDR block prefix lengths for v4/v6 (hardcoded also in unit tests). +#define RRL_V4_PREFIXES (uint8_t[]) { 18, 20, 24, 32 } +#define RRL_V4_RATE_MULT (kru_price_t[]) { 768, 256, 32, 1 } -/* Classification string. */ -struct cls_name { - int code; - const char *name; -}; +#define RRL_V6_PREFIXES (uint8_t[]) { 32, 48, 56, 64, 128 } +#define RRL_V6_RATE_MULT (kru_price_t[]) { 64, 4, 3, 2, 1 } -static const struct cls_name rrl_cls_names[] = { - { CLS_NORMAL, "POSITIVE" }, - { CLS_ERROR, "ERROR" }, - { CLS_NXDOMAIN, "NXDOMAIN"}, - { CLS_EMPTY, "EMPTY"}, - { CLS_LARGE, "LARGE"}, - { CLS_WILDCARD, "WILDCARD"}, - { CLS_ANY, "ANY"}, - { CLS_DNSSEC, "DNSSEC"}, - { CLS_NULL, "NULL"}, - { CLS_NULL, NULL} -}; +#define RRL_V4_PREFIXES_CNT (sizeof(RRL_V4_PREFIXES) / sizeof(*RRL_V4_PREFIXES)) +#define RRL_V6_PREFIXES_CNT (sizeof(RRL_V6_PREFIXES) / sizeof(*RRL_V6_PREFIXES)) +#define RRL_MAX_PREFIXES_CNT ((RRL_V4_PREFIXES_CNT > RRL_V6_PREFIXES_CNT) ? RRL_V4_PREFIXES_CNT : RRL_V6_PREFIXES_CNT) -static inline const char *rrl_clsstr(int code) -{ - for (const struct cls_name *c = rrl_cls_names; c->name; c++) { - if (c->code == code) { - return c->name; - } - } +#ifndef CLOCK_MONOTONIC_COARSE +#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC +#endif - return "unknown class"; -} +#define RRL_LIMIT_KOEF 1/2 // Avoid probabilistic rounding wherever possible. -/* Bucket flags. */ -enum { - RRL_BF_NULL = 0 << 0, /* No flags. */ - RRL_BF_SSTART = 1 << 0, /* Bucket in slow-start after collision. */ - RRL_BF_ELIMIT = 1 << 1 /* Bucket is rate-limited. */ +struct rrl_table { + kru_price_t v4_prices[RRL_V4_PREFIXES_CNT]; + kru_price_t v6_prices[RRL_V6_PREFIXES_CNT]; + uint32_t log_period; + bool rw_mode; + _Atomic uint32_t log_time; + _Alignas(64) uint8_t kru[]; }; -static uint8_t rrl_clsid(rrl_req_t *p) -{ - /* Check error code */ - int ret = CLS_NULL; - switch (knot_wire_get_rcode(p->wire)) { - case KNOT_RCODE_NOERROR: ret = CLS_NORMAL; break; - case KNOT_RCODE_NXDOMAIN: return CLS_NXDOMAIN; break; - default: return CLS_ERROR; break; - } - - /* Check if answered from a qname */ - if (ret == CLS_NORMAL && p->flags & RRL_REQ_WILDCARD) { - return CLS_WILDCARD; - } - - /* Check query type for spec. classes. */ - if (p->query) { - switch(knot_pkt_qtype(p->query)) { - case KNOT_RRTYPE_ANY: /* ANY spec. class */ - return CLS_ANY; - break; - case KNOT_RRTYPE_DNSKEY: - case KNOT_RRTYPE_RRSIG: - case KNOT_RRTYPE_DS: /* DNSSEC-related RR class. */ - return CLS_DNSSEC; - break; - default: - break; - } - } - - /* Check packet size for threshold. */ - if (p->len >= RRL_PSIZE_LARGE) { - return CLS_LARGE; - } - - /* Check ancount */ - if (knot_wire_get_ancount(p->wire) == 0) { - return CLS_EMPTY; - } - - return ret; -} - -static int rrl_clsname(uint8_t *dst, size_t maxlen, uint8_t cls, rrl_req_t *req, - const knot_dname_t *name) +static void addr_tostr(char *dst, size_t maxlen, const struct sockaddr_storage *ss) { - if (name == NULL) { - /* Fallback for errors etc. */ - name = (const knot_dname_t *)"\x00"; - } - - switch (cls) { - case CLS_ERROR: /* Could be a non-existent zone or garbage. */ - case CLS_NXDOMAIN: /* Queries to non-existent names in zone. */ - case CLS_WILDCARD: /* Queries to names covered by a wildcard. */ - break; - default: - /* Use QNAME */ - if (req->query) { - name = knot_pkt_qname(req->query); - } - break; - } + assert(ss); - /* Write to wire */ - return knot_dname_to_wire(dst, name, maxlen); -} - -static int rrl_classify(uint8_t *dst, size_t maxlen, const struct sockaddr_storage *remote, - rrl_req_t *req, const knot_dname_t *name) -{ - /* Class */ - uint8_t cls = rrl_clsid(req); - *dst = cls; - int blklen = sizeof(cls); - - /* Address (in network byteorder, adjust masks). */ - uint64_t netblk = 0; - if (remote->ss_family == AF_INET6) { - struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)remote; - memcpy(&netblk, &ipv6->sin6_addr, RRL_V6_PREFIX_LEN); - } else { - struct sockaddr_in *ipv4 = (struct sockaddr_in *)remote; - memcpy(&netblk, &ipv4->sin_addr, RRL_V4_PREFIX_LEN); - } - memcpy(dst + blklen, &netblk, sizeof(netblk)); - blklen += sizeof(netblk); - - /* Name */ - int ret = rrl_clsname(dst + blklen, maxlen - blklen, cls, req, name); - if (ret < 0) { - return ret; - } - uint8_t len = ret; - blklen += len; - - return blklen; -} - -static int bucket_free(rrl_item_t *bucket, uint32_t now) -{ - return bucket->cls == CLS_NULL || (bucket->time + 1 < now); -} - -static int bucket_match(rrl_item_t *bucket, rrl_item_t *match) -{ - return bucket->cls == match->cls && - bucket->netblk == match->netblk && - bucket->qname == match->qname; -} - -static int find_free(rrl_table_t *tbl, unsigned id, uint32_t now) -{ - for (int i = id; i < tbl->size; i++) { - if (bucket_free(&tbl->arr[i], now)) { - return i - id; - } - } - for (int i = 0; i < id; i++) { - if (bucket_free(&tbl->arr[i], now)) { - return i + (tbl->size - id); - } - } - - /* this happens if table is full... force vacate current elm */ - return id; -} - -static inline unsigned find_match(rrl_table_t *tbl, uint32_t id, rrl_item_t *m) -{ - unsigned new_id = 0; - unsigned hop = 0; - unsigned match_bitmap = tbl->arr[id].hop; - while (match_bitmap != 0) { - hop = __builtin_ctz(match_bitmap); /* offset of next potential match */ - new_id = (id + hop) % tbl->size; - if (bucket_match(&tbl->arr[new_id], m)) { - return hop; - } else { - match_bitmap &= ~(1 << hop); /* clear potential match */ - } - } - - return HOP_LEN + 1; -} - -static inline unsigned reduce_dist(rrl_table_t *tbl, unsigned id, unsigned dist, unsigned *free_id) -{ - unsigned rd = HOP_LEN - 1; - while (rd > 0) { - unsigned vacate_id = (tbl->size + *free_id - rd) % tbl->size; /* bucket to be vacated */ - if (tbl->arr[vacate_id].hop != 0) { - unsigned hop = __builtin_ctz(tbl->arr[vacate_id].hop); /* offset of first valid bucket */ - if (hop < rd) { /* only offsets in are interesting */ - unsigned new_id = (vacate_id + hop) % tbl->size; /* this item will be displaced to [free_id] */ - unsigned keep_hop = tbl->arr[*free_id].hop; /* unpredictable padding */ - memcpy(tbl->arr + *free_id, tbl->arr + new_id, sizeof(rrl_item_t)); - tbl->arr[*free_id].hop = keep_hop; - tbl->arr[new_id].cls = CLS_NULL; - tbl->arr[vacate_id].hop &= ~(1 << hop); - tbl->arr[vacate_id].hop |= 1 << rd; - *free_id = new_id; - return dist - (rd - hop); - } - } - --rd; - } - - assert(rd == 0); /* this happens with p=1/fact(HOP_LEN) */ - *free_id = id; - dist = 0; /* force vacate initial element */ - return dist; -} - -static void subnet_tostr(char *dst, size_t maxlen, const struct sockaddr_storage *ss) -{ const void *addr; - const char *suffix; if (ss->ss_family == AF_INET6) { addr = &((struct sockaddr_in6 *)ss)->sin6_addr; - suffix = "/56"; } else { addr = &((struct sockaddr_in *)ss)->sin_addr; - suffix = "/24"; } - if (knot_inet_ntop(ss->ss_family, addr, dst, maxlen) != NULL) { - strlcat(dst, suffix, maxlen); - } else { + if (knot_inet_ntop(ss->ss_family, addr, dst, maxlen) == NULL) { dst[0] = '\0'; } } -static void rrl_log_state(knotd_mod_t *mod, const struct sockaddr_storage *ss, - uint16_t flags, uint8_t cls, const knot_dname_t *qname) +static void rrl_log_limited(knotd_mod_t *mod, const struct sockaddr_storage *ss, + const uint8_t prefix, bool rate) { - if (mod == NULL || ss == NULL) { + if (mod == NULL) { return; } char addr_str[SOCKADDR_STRLEN]; - subnet_tostr(addr_str, sizeof(addr_str), ss); - - const char *what = "leaves"; - if (flags & RRL_BF_ELIMIT) { - what = "enters"; - } + addr_tostr(addr_str, sizeof(addr_str), ss); - knot_dname_txt_storage_t buf; - char *qname_str = knot_dname_to_str(buf, qname, sizeof(buf)); - if (qname_str == NULL) { - qname_str = "?"; - } - - knotd_mod_log(mod, LOG_NOTICE, "address/subnet %s, class %s, qname %s, %s limiting", - addr_str, rrl_clsstr(cls), qname_str, what); + knotd_mod_log(mod, LOG_NOTICE, "address %s limited on /%d by %s", + addr_str, prefix, rate ? "rate" : "time"); } -static void rrl_lock(rrl_table_t *tbl, int lk_id) +rrl_table_t *rrl_create(size_t size, uint32_t instant_limit, uint32_t rate_limit, + bool rw_mode, uint32_t log_period) { - assert(lk_id > -1); - pthread_mutex_lock(tbl->lk + lk_id); -} - -static void rrl_unlock(rrl_table_t *tbl, int lk_id) -{ - assert(lk_id > -1); - pthread_mutex_unlock(tbl->lk + lk_id); -} - -static int rrl_setlocks(rrl_table_t *tbl, uint32_t granularity) -{ - assert(!tbl->lk); /* Cannot change while locks are used. */ - assert(granularity <= tbl->size / 10); /* Due to int. division err. */ - - if (pthread_mutex_init(&tbl->ll, NULL) < 0) { - return KNOT_ENOMEM; + if (size == 0 || instant_limit == 0 || rate_limit == 0) { + return NULL; } - /* Alloc new locks. */ - tbl->lk = malloc(granularity * sizeof(pthread_mutex_t)); - if (!tbl->lk) { - return KNOT_ENOMEM; - } - memset(tbl->lk, 0, granularity * sizeof(pthread_mutex_t)); + size--; + size_t capacity_log = 1; + while (size >>= 1) capacity_log++; - /* Initialize. */ - for (size_t i = 0; i < granularity; ++i) { - if (pthread_mutex_init(tbl->lk + i, NULL) < 0) { - break; - } - ++tbl->lk_count; + rrl_table_t *rrl; + size_t rrl_size = offsetof(struct rrl_table, kru) + KRU.get_size(capacity_log); + if (posix_memalign((void **)&rrl, 64, rrl_size) != 0) { + return NULL; } + memset(rrl, 0, rrl_size); - /* Incomplete initialization */ - if (tbl->lk_count != granularity) { - for (size_t i = 0; i < tbl->lk_count; ++i) { - pthread_mutex_destroy(tbl->lk + i); - } - free(tbl->lk); - tbl->lk_count = 0; - return KNOT_ERROR; + assert(rate_limit <= 1000ll * instant_limit); // Ensured by config check. + kru_price_t base_price = KRU_LIMIT / instant_limit; + const kru_price_t max_decay = (uint64_t)base_price * rate_limit / 1000; + if (!rw_mode) { + base_price = base_price * RRL_LIMIT_KOEF; } - return KNOT_EOK; -} - -rrl_table_t *rrl_create(size_t size, uint32_t rate) -{ - if (size == 0) { + if (!KRU.initialize((struct kru *)rrl->kru, capacity_log, max_decay)) { + free(rrl); return NULL; } - const size_t tbl_len = sizeof(rrl_table_t) + size * sizeof(rrl_item_t); - rrl_table_t *tbl = calloc(1, tbl_len); - if (!tbl) { - return NULL; + for (size_t i = 0; i < RRL_V4_PREFIXES_CNT; i++) { + rrl->v4_prices[i] = base_price / RRL_V4_RATE_MULT[i]; } - tbl->size = size; - tbl->rate = rate; - if (dnssec_random_buffer((uint8_t *)&tbl->key, sizeof(tbl->key)) != DNSSEC_EOK) { - free(tbl); - return NULL; + for (size_t i = 0; i < RRL_V6_PREFIXES_CNT; i++) { + rrl->v6_prices[i] = base_price / RRL_V6_RATE_MULT[i]; } - if (rrl_setlocks(tbl, RRL_LOCK_GRANULARITY) != KNOT_EOK) { - free(tbl); - return NULL; - } + rrl->rw_mode = rw_mode; + rrl->log_period = log_period; - return tbl; -} + struct timespec now_ts; + clock_gettime(CLOCK_MONOTONIC_COARSE, &now_ts); + uint32_t now = now_ts.tv_sec * 1000 + now_ts.tv_nsec / 1000000; + rrl->log_time = now - log_period; -static knot_dname_t *buf_qname(uint8_t *buf) -{ - return buf + sizeof(uint8_t) + sizeof(uint64_t); + return rrl; } -/*! \brief Get bucket for current combination of parameters. */ -static rrl_item_t *rrl_hash(rrl_table_t *tbl, const struct sockaddr_storage *remote, - rrl_req_t *req, const knot_dname_t *zone, uint32_t stamp, - int *lock, uint8_t *buf, size_t buf_len) +int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, knotd_mod_t *mod) { - int len = rrl_classify(buf, buf_len, remote, req, zone); - if (len < 0) { - return NULL; - } + assert(rrl); + assert(remote); - uint32_t id = SipHash24(&tbl->key, buf, len) % tbl->size; - - /* Lock for lookup. */ - pthread_mutex_lock(&tbl->ll); - - /* Find an exact match in rate * RRL_CAPACITY, - .cls = buf[0], - .flags = RRL_BF_NULL, - .qname = SipHash24(&tbl->key, qname, knot_dname_size(qname)), - .time = stamp - }; - - unsigned dist = find_match(tbl, id, &match); - if (dist > HOP_LEN) { /* not an exact match, find free element [f] */ - dist = find_free(tbl, id, stamp); - } + struct timespec now_ts; + clock_gettime(CLOCK_MONOTONIC_COARSE, &now_ts); + uint32_t now = now_ts.tv_sec * 1000 + now_ts.tv_nsec / 1000000; - /* Reduce distance to fit size; - while (dist >= HOP_LEN) { - dist = reduce_dist(tbl, id, dist, &free_id); - } + uint16_t load = 0; + uint8_t prefix = 0; + _Alignas(16) uint8_t key[16] = { 0 }; + if (remote->ss_family == AF_INET6) { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)remote; + memcpy(key, &ipv6->sin6_addr, 16); - /* Assign granular lock and unlock lookup. */ - *lock = free_id % tbl->lk_count; - rrl_lock(tbl, *lock); - pthread_mutex_unlock(&tbl->ll); - - /* found free bucket which is in arr[id].hop |= (1 << dist); - rrl_item_t *bucket = &tbl->arr[free_id]; - assert(free_id == (id + dist) % tbl->size); - - /* Inspect bucket state. */ - unsigned hop = bucket->hop; - if (bucket->cls == CLS_NULL) { - memcpy(bucket, &match, sizeof(rrl_item_t)); - bucket->hop = hop; + if (rrl->rw_mode) { + prefix = KRU.limited_multi_prefix_or( + (struct kru *)rrl->kru, now, 1, key, RRL_V6_PREFIXES, + rrl->v6_prices, RRL_V6_PREFIXES_CNT, NULL); + } else { + load = KRU.load_multi_prefix_max( + (struct kru *)rrl->kru, now, 1, key, RRL_V6_PREFIXES, + NULL, RRL_V6_PREFIXES_CNT, &prefix); + } + } else { + struct sockaddr_in *ipv4 = (struct sockaddr_in *)remote; + memcpy(key, &ipv4->sin_addr, 4); + + if (rrl->rw_mode) { + prefix = KRU.limited_multi_prefix_or( + (struct kru *)rrl->kru, now, 0, key, RRL_V4_PREFIXES, + rrl->v4_prices, RRL_V4_PREFIXES_CNT, NULL); + } else { + load = KRU.load_multi_prefix_max( + (struct kru *)rrl->kru, now, 0, key, RRL_V4_PREFIXES, + NULL, RRL_V4_PREFIXES_CNT, &prefix); + } } - /* Check for collisions. */ - if (!bucket_match(bucket, &match)) { - if (!(bucket->flags & RRL_BF_SSTART)) { - memcpy(bucket, &match, sizeof(rrl_item_t)); - bucket->hop = hop; - bucket->ntok = tbl->rate + tbl->rate / RRL_SSTART; - bucket->flags |= RRL_BF_SSTART; + + if (rrl->rw_mode) { + if (prefix == 0) { + return KNOT_EOK; } + } else { + if (load <= (1 << 16) * RRL_LIMIT_KOEF) { + return KNOT_EOK; + } + } + + uint32_t log_time_orig = atomic_load_explicit(&rrl->log_time, memory_order_relaxed); + if (rrl->log_period && (now - log_time_orig + 1024 >= rrl->log_period + 1024)) { + do { + if (atomic_compare_exchange_weak_explicit(&rrl->log_time, &log_time_orig, now, + memory_order_relaxed, memory_order_relaxed)) { + rrl_log_limited(mod, remote, prefix, rrl->rw_mode); + break; + } + } while (now - log_time_orig + 1024 >= rrl->log_period + 1024); } - return bucket; + return KNOT_ELIMIT; } -int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, - rrl_req_t *req, const knot_dname_t *zone, knotd_mod_t *mod) +void rrl_update(rrl_table_t *rrl, const struct sockaddr_storage *remote, size_t value) { - if (!rrl || !req || !remote) { - return KNOT_EINVAL; - } + assert(rrl); + assert(remote); + assert(!rrl->rw_mode); - uint8_t buf[RRL_CLSBLK_MAXLEN]; + struct timespec now_ts; + clock_gettime(CLOCK_MONOTONIC_COARSE, &now_ts); + uint32_t now = now_ts.tv_sec * 1000 + now_ts.tv_nsec / 1000000; - /* Calculate hash and fetch */ - int ret = KNOT_EOK; - int lock = -1; - uint32_t now = time_now().tv_sec; - rrl_item_t *bucket = rrl_hash(rrl, remote, req, zone, now, &lock, buf, sizeof(buf)); - if (!bucket) { - if (lock > -1) { - rrl_unlock(rrl, lock); - } - return KNOT_ERROR; - } - - /* Calculate rate for dT */ - uint32_t dt = now - bucket->time; - if (dt > RRL_CAPACITY) { - dt = RRL_CAPACITY; - } - /* Visit bucket. */ - bucket->time = now; - if (dt > 0) { /* Window moved. */ - - /* Check state change. */ - if ((bucket->ntok > 0 || dt > 1) && (bucket->flags & RRL_BF_ELIMIT)) { - bucket->flags &= ~RRL_BF_ELIMIT; - rrl_log_state(mod, remote, bucket->flags, bucket->cls, - knot_pkt_qname(req->query)); - } + _Alignas(16) uint8_t key[16] = { 0 }; + if (remote->ss_family == AF_INET6) { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)remote; + memcpy(key, &ipv6->sin6_addr, 16); - /* Add new tokens. */ - uint32_t dn = rrl->rate * dt; - if (bucket->flags & RRL_BF_SSTART) { /* Bucket in slow-start. */ - bucket->flags &= ~RRL_BF_SSTART; - } - bucket->ntok += dn; - if (bucket->ntok > RRL_CAPACITY * rrl->rate) { - bucket->ntok = RRL_CAPACITY * rrl->rate; + kru_price_t prices[RRL_V6_PREFIXES_CNT]; + for (size_t i = 0; i < RRL_V6_PREFIXES_CNT; i++) { + prices[i] = MIN(value * rrl->v6_prices[i], (kru_price_t)-1LL); } - } - /* Last item taken. */ - if (bucket->ntok == 1 && !(bucket->flags & RRL_BF_ELIMIT)) { - bucket->flags |= RRL_BF_ELIMIT; - rrl_log_state(mod, remote, bucket->flags, bucket->cls, - knot_pkt_qname(req->query)); - } + (void)KRU.load_multi_prefix_max((struct kru *)rrl->kru, now, + 1, key, RRL_V6_PREFIXES, prices, + RRL_V6_PREFIXES_CNT, NULL); + } else { + struct sockaddr_in *ipv4 = (struct sockaddr_in *)remote; + memcpy(key, &ipv4->sin_addr, 4); - /* Decay current bucket. */ - if (bucket->ntok > 0) { - --bucket->ntok; - } else if (bucket->ntok == 0) { - ret = KNOT_ELIMIT; - } + kru_price_t prices[RRL_V4_PREFIXES_CNT]; + for (size_t i = 0; i < RRL_V4_PREFIXES_CNT; i++) { + prices[i] = MIN(value * rrl->v4_prices[i], (kru_price_t)-1LL); + } - if (lock > -1) { - rrl_unlock(rrl, lock); + (void)KRU.load_multi_prefix_max((struct kru *)rrl->kru, now, + 0, key, RRL_V4_PREFIXES, prices, + RRL_V4_PREFIXES_CNT, NULL); } - return ret; } bool rrl_slip_roll(int n_slip) @@ -540,15 +247,5 @@ bool rrl_slip_roll(int n_slip) void rrl_destroy(rrl_table_t *rrl) { - if (rrl) { - if (rrl->lk_count > 0) { - pthread_mutex_destroy(&rrl->ll); - } - for (size_t i = 0; i < rrl->lk_count; ++i) { - pthread_mutex_destroy(rrl->lk + i); - } - free(rrl->lk); - } - free(rrl); } diff --git a/src/knot/modules/rrl/functions.h b/src/knot/modules/rrl/functions.h index 0f09234..0941c83 100644 --- a/src/knot/modules/rrl/functions.h +++ b/src/knot/modules/rrl/functions.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,95 +17,63 @@ #pragma once #include -#include #include -#include "libknot/libknot.h" #include "knot/include/module.h" -#include "contrib/openbsd/siphash.h" -/*! - * \brief RRL hash bucket. - */ -typedef struct { - unsigned hop; /* Hop bitmap. */ - uint64_t netblk; /* Prefix associated. */ - uint16_t ntok; /* Tokens available. */ - uint8_t cls; /* Bucket class. */ - uint8_t flags; /* Flags. */ - uint32_t qname; /* imputed(QNAME) hash. */ - uint32_t time; /* Timestamp. */ -} rrl_item_t; +typedef struct rrl_table rrl_table_t; /*! - * \brief RRL hash bucket table. + * \brief Create a RRL table. * - * Table is fixed size, so collisions may occur and are dealt with - * in a way, that hashbucket rate is reset and enters slow-start for 1 dt. - * When a bucket is in a slow-start mode, it cannot reset again for the time - * period. + * \param size Fixed table size. + * \param instant_limit Instant limit. + * \param rate_limit Rate limit. + * \param rw_mode If disabled, RW operation is divided into R and W operations. + * \param log_period If nonzero, maximum logging period (in milliseconds). * - * To avoid lock contention, N locks are created and distributed amongst buckets. - * As of now lock K for bucket N is calculated as K = N % (num_buckets). - */ - -typedef struct { - SIPHASH_KEY key; /* Siphash key. */ - uint32_t rate; /* Configured RRL limit. */ - pthread_mutex_t ll; - pthread_mutex_t *lk; /* Table locks. */ - unsigned lk_count; /* Table lock count (granularity). */ - size_t size; /* Number of buckets. */ - rrl_item_t arr[]; /* Buckets. */ -} rrl_table_t; - -/*! \brief RRL request flags. */ -typedef enum { - RRL_REQ_NOFLAG = 0 << 0, /*!< No flags. */ - RRL_REQ_WILDCARD = 1 << 1 /*!< Query to wildcard name. */ -} rrl_req_flag_t; - -/*! - * \brief RRL request descriptor. - */ -typedef struct { - const uint8_t *wire; - uint16_t len; - rrl_req_flag_t flags; - knot_pkt_t *query; -} rrl_req_t; - -/*! - * \brief Create a RRL table. - * \param size Fixed hashtable size (reasonable large prime is recommended). - * \param rate Rate (in pkts/sec). * \return created table or NULL. */ -rrl_table_t *rrl_create(size_t size, uint32_t rate); +rrl_table_t *rrl_create(size_t size, uint32_t instant_limit, uint32_t rate_limit, + bool rw_mode, uint32_t log_period); /*! * \brief Query the RRL table for accept or deny, when the rate limit is reached. * + * \note This function is common to both RW and non-RW modes! + * * \param rrl RRL table. * \param remote Source address. - * \param req RRL request (containing resp., flags and question). - * \param zone Zone name related to the response (or NULL). * \param mod Query module (needed for logging). + * * \retval KNOT_EOK if passed. * \retval KNOT_ELIMIT when the limit is reached. */ -int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, - rrl_req_t *req, const knot_dname_t *zone, knotd_mod_t *mod); +int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, knotd_mod_t *mod); + +/*! + * \brief Update the RRL table. + * + * \note This function is only for the non-RW mode! + * + * \param rrl RRL table. + * \param remote Source address. + * \param value Value with which the table is updated. + */ +void rrl_update(rrl_table_t *rrl, const struct sockaddr_storage *remote, size_t value); /*! * \brief Roll a dice whether answer slips or not. + * * \param n_slip Number represents every Nth answer that is slipped. + * * \return true or false */ bool rrl_slip_roll(int n_slip); /*! * \brief Destroy RRL table. + * * \param rrl RRL table. */ void rrl_destroy(rrl_table_t *rrl); diff --git a/src/knot/modules/rrl/kru-avx2.c b/src/knot/modules/rrl/kru-avx2.c new file mode 100644 index 0000000..183ae44 --- /dev/null +++ b/src/knot/modules/rrl/kru-avx2.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +// Checked with clang 5 (2017) and gcc 6 (2016). +// For other cases we'll rather keep just the generic implementation. +#if defined(__x86_64__) && (__clang_major__ >= 5 || __GNUC__ >= 6) + +// This file has code for new-ish x86 (2015+ usually, Atom 2021+) - AES + AVX2 +#if __clang_major__ >= 12 + #pragma clang attribute push (__attribute__((target("arch=x86-64-v3,aes"))), \ + apply_to = function) +#elif __clang__ + #pragma clang attribute push (__attribute__((target("avx2,aes"))), \ + apply_to = function) +#else + #pragma GCC push_options + #if __GNUC__ >= 11 + #pragma GCC target("arch=x86-64-v3,aes") + // try harder for auto-vectorization, etc. + #pragma GCC optimize("O3") + #else + #pragma GCC target("avx2,aes") + #endif +#endif + +#define USE_AES 1 +#define USE_AVX2 1 +#define USE_SSE41 1 + +#include "./kru.inc.c" +const struct kru_api KRU_AVX2 = KRU_API_INITIALIZER; + +#ifdef __clang__ + #pragma clang attribute pop +#else + #pragma GCC pop_options +#endif + +__attribute__((constructor)) +static void detect_CPU_avx2(void) +{ + // Checking just AES+AVX2 will most likely be OK even if we used arch=x86-64-v3 + if (__builtin_cpu_supports("aes") && __builtin_cpu_supports("avx2")) { + KRU = KRU_AVX2; + } +} + +#else + +#include "./kru.h" +const struct kru_api KRU_AVX2 = {NULL}; + +#endif diff --git a/src/knot/modules/rrl/kru-generic.c b/src/knot/modules/rrl/kru-generic.c new file mode 100644 index 0000000..71ffdd4 --- /dev/null +++ b/src/knot/modules/rrl/kru-generic.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include "./kru.inc.c" + +const struct kru_api KRU_GENERIC = KRU_API_INITIALIZER; +struct kru_api KRU = KRU_API_INITIALIZER; // generic version is the default diff --git a/src/knot/modules/rrl/kru.h b/src/knot/modules/rrl/kru.h new file mode 100644 index 0000000..7eef6c0 --- /dev/null +++ b/src/knot/modules/rrl/kru.h @@ -0,0 +1,90 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +#define ALIGNED_CPU_CACHE _Alignas(64) + +// An unsigned integral type used for prices, blocking occurs when sum of prices overflows. +// Greater than 16-bit type enables randomized fractional incrementing as the internal counters are still 16-bit. +// Exponential decay always uses randomized rounding on 32 bits. +typedef uint32_t kru_price_t; + +#define KRU_PRICE_BITS (8 * sizeof(kru_price_t)) + +// maximal allowed sum of prices without limiting +#define KRU_LIMIT (((kru_price_t)-1ll) - (1ll << (KRU_PRICE_BITS - 16)) + 1) + +struct kru; + +/// Usage: KRU.limited(...) +struct kru_api { + /// Initialize a new KRU structure that can track roughly 2^capacity_log limited keys. + /// + /// The kru parameter should point to a zeroed preallocated memory + /// of size returned by get_size aligned to 64-bytes; + /// deallocate the memory to destroy KRU. + /// RAM: the current parametrization will use roughly 8 bytes * 2^capacity_log. + /// + /// The number of non-limited keys is basically arbitrary, + /// but the total sum of prices per tick (for queries returning false) + /// should not get over roughly 2^(capacity_log + 15). + /// Note that the _multi variants increase these totals + /// by tracking multiple keys in a single query. + /// + /// Returns false if kru is NULL or other failure occurs. + bool (*initialize)(struct kru *kru, int capacity_log, kru_price_t max_decay); + + /// Calculate size of the KRU structure. + size_t (*get_size)(int capacity_log); + + /// Determine if a key should get limited (and update the KRU). + /// key needs to be aligned to a multiple of 16 bytes. + bool (*limited)(struct kru *kru, uint32_t time_now, uint8_t key[static const 16], kru_price_t price); + + /// Multiple queries. Returns OR of answers. Updates KRU only if no query is blocked (and possibly on race). + bool (*limited_multi_or)(struct kru *kru, uint32_t time_now, uint8_t **keys, kru_price_t *prices, size_t queries_cnt); + + /// Same as previous but without short-circuit evaluation; for time measurement purposes. + bool (*limited_multi_or_nobreak)(struct kru *kru, uint32_t time_now, uint8_t ** keys, kru_price_t *prices, size_t queries_cnt); + + /// Multiple queries based on different prefixes of a single key. + /// Returns a prefix (value in prefixes) on which the key is blocked, or zero if all queries passed. + /// Updates KRU only if no query is blocked, unless a race condition occurs -- + /// in such a case all longer prefixes might have been updated. + /// The key of i-th query consists of prefixes[i] bits of key, prefixes[i], and namespace. + /// If zero is returned, *max_load_out (unless NULL) is set to + /// the maximum of final values of the involved counters normalized to the limit 2^16. + uint8_t (*limited_multi_prefix_or)(struct kru *kru, uint32_t time_now, + uint8_t namespace, uint8_t key[static 16], uint8_t *prefixes, kru_price_t *prices, size_t queries_cnt, uint16_t *max_load_out); + + /// Multiple queries based on different prefixes of a single key. + /// Returns the maximum of final values of the involved counters normalized to the limit 2^16 + /// and stores the corresponding prefix (value in prefixes) to *prefix_out (unless NULL). + /// Set prices to NULL to skip updating; otherwise, KRU is always updated, using maximal allowed value on overflow. + /// The key of i-th query consists of prefixes[i] bits of key, prefixes[i], and namespace. + uint16_t (*load_multi_prefix_max)(struct kru *kru, uint32_t time_now, + uint8_t namespace, uint8_t key[static 16], uint8_t *prefixes, kru_price_t *prices, size_t queries_cnt, uint8_t *prefix_out); +}; + +// The functions are stored this way to make it easier to switch +// implementation based on detected CPU. +extern struct kru_api KRU; +extern const struct kru_api KRU_GENERIC, KRU_AVX2; diff --git a/src/knot/modules/rrl/kru.inc.c b/src/knot/modules/rrl/kru.inc.c new file mode 100644 index 0000000..49e359e --- /dev/null +++ b/src/knot/modules/rrl/kru.inc.c @@ -0,0 +1,615 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +/* +KRU estimates recently pricey inputs + +Authors of the simple agorithm (without aging, multi-choice, etc.): + Metwally, D. Agrawal, and A. E. Abbadi. + Efficient computation of frequent and top-k elements in data streams. + In International Conference on Database Theory, 2005. + +With TABLE_COUNT > 1 we're improving reliability by utilizing the property that +longest buckets (cache-lines) get very much shortened, already by providing two choices: + https://en.wikipedia.org/wiki/2-choice_hashing + +The point is to answer point-queries that estimate if the item has been heavily used recently. +To give more weight to recent usage, we use aging via exponential decay (simple to compute). +That has applications for garbage collection of cache and various limiting scenario +(excessive rate, traffic, CPU, maybe RAM). + +### Choosing parameters + +Size (`loads_bits` = log2 length): + - The KRU takes 64 bytes * length * TABLE_COUNT + some small constants. + As TABLE_COUNT == 2 and loads_bits = capacity_log >> 4, we get capacity * 8 Bytes. + - The length should probably be at least something like the square of the number of utilized CPUs. + But this most likely won't be a limiting factor. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "./kru.h" +#include "contrib/macros.h" +#include "libdnssec/error.h" +#include "libdnssec/random.h" +typedef uint64_t hash_t; +#if USE_AES + /// 4-8 rounds should be an OK choice, most likely. + #define AES_ROUNDS 4 +#else + #include "contrib/openbsd/siphash.h" + + /// 1,3 should be OK choice, probably. + enum { + SIPHASH_RC = 1, + SIPHASH_RF = 3, + }; +#endif + +#if USE_AVX2 || USE_SSE41 || USE_AES + #include + #include +#endif + +/// Block of loads sharing the same time, so that we're more space-efficient. +/// It's exactly a single cache line. +struct load_cl { + ALIGNED_CPU_CACHE + _Atomic uint32_t time; + #define LOADS_LEN 15 + uint16_t ids[LOADS_LEN]; + uint16_t loads[LOADS_LEN]; +}; +static_assert(64 == sizeof(struct load_cl), "bad size of struct load_cl"); + +/// Parametrization for speed of decay. +struct decay_config { + /// Bit shift per tick, fractional + double shift_bits; + + /// Ticks to get zero loads + uint32_t max_ticks; + + uint32_t mult_cache[32]; +}; + +struct kru { +#if USE_AES + /// Hashing secret. Random but shared by all users of the table. + /// Let's not make it too large, so that header fits into 64 Bytes. + _Alignas(32) char hash_key[48]; +#else + /// Hashing secret. Random but shared by all users of the table. + SIPHASH_KEY hash_key; +#endif + struct decay_config decay; + + /// Length of `loads_cls`, stored as binary logarithm. + uint32_t loads_bits; + + #define TABLE_COUNT 2 + /// These are read-write. Each struct has exactly one cache line. + struct load_cl load_cls[][TABLE_COUNT]; +}; + +inline static uint64_t rand_bits(unsigned int bits) +{ + static _Thread_local uint64_t state = 3723796604792068981ull; + const uint64_t prime1 = 11737314301796036329ull; + const uint64_t prime2 = 3107264277052274849ull; + state = prime1 * state + prime2; + //return state & ((1 << bits) - 1); + return state >> (64 - bits); +} + +static inline void decay_initialize(struct decay_config *decay, kru_price_t max_decay) +{ + decay->shift_bits = log2(KRU_LIMIT - 1) - log2(KRU_LIMIT - 1 - max_decay); + decay->max_ticks = 18 / decay->shift_bits; + + decay->mult_cache[0] = 0; // not used + for (size_t ticks = 1; ticks < sizeof(decay->mult_cache) / sizeof(*decay->mult_cache); ticks++) { + decay->mult_cache[ticks] = exp2(32 - decay->shift_bits * ticks) + 0.5; + } +} + +/// Catch up the time drift with configurably slower decay. +static inline void update_time(struct load_cl *l, const uint32_t time_now, + const struct decay_config *decay) +{ + uint32_t ticks; + uint32_t time_last = atomic_load_explicit(&l->time, memory_order_relaxed); + do { + ticks = time_now - time_last; + if (__builtin_expect(!ticks, true)) // we optimize for time not advancing + return; + // We accept some desynchronization of time_now (e.g. from different threads). + if (ticks > (uint32_t)-1024) + return; + } while (!atomic_compare_exchange_weak_explicit(&l->time, &time_last, time_now, memory_order_relaxed, memory_order_relaxed)); + + // If we passed here, we have acquired a time difference we are responsibe for. + + // Don't bother with complex computations if lots of ticks have passed. (little to no speed-up) + if (ticks > decay->max_ticks) { + memset(l->loads, 0, sizeof(l->loads)); + return; + } + + uint32_t mult; + if (__builtin_expect(ticks < sizeof(decay->mult_cache) / sizeof(*decay->mult_cache), 1)) { + mult = decay->mult_cache[ticks]; + } else { + mult = exp2(32 - decay->shift_bits * ticks) + 0.5; + } + + for (int i = 0; i < LOADS_LEN; ++i) { + // We perform decay for the acquired time difference; decays from different threads are commutative. + _Atomic uint16_t *load_at = (_Atomic uint16_t *)&l->loads[i]; + uint16_t l1, load_orig = atomic_load_explicit(load_at, memory_order_relaxed); + const uint16_t rnd = rand_bits(16); + do { + uint64_t m = (((uint64_t)load_orig << 16)) * mult; + m = (m >> 32) + ((m >> 31) & 1); + l1 = (m >> 16) + (rnd < (uint16_t)m); + } while (!atomic_compare_exchange_weak_explicit(load_at, &load_orig, l1, memory_order_relaxed, memory_order_relaxed)); + } +} + +/// Convert capacity_log to loads_bits +static inline int32_t capacity2loads(int capacity_log) +{ + static_assert(LOADS_LEN == 15 && TABLE_COUNT == 2, ""); + // So, the pair of cache lines hold up to 2*15 elements. + // Let's say that we can reliably store 16 = 1 << (1+3). + // (probably more but certainly not 1 << 5) + const int shift = 1 + 3; + int loads_bits = capacity_log - shift; + // Let's behave reasonably for weird capacity_log values. + return loads_bits > 0 ? loads_bits : 1; +} + +static size_t kru_get_size(int capacity_log) +{ + uint32_t loads_bits = capacity2loads(capacity_log); + if (8 * sizeof(hash_t) < TABLE_COUNT * loads_bits + + 8 * sizeof(((struct kru *)0)->load_cls[0]->ids[0])) { + assert(false); + return 0; + } + + return offsetof(struct kru, load_cls) + + sizeof(struct load_cl) * TABLE_COUNT * (1 << loads_bits); +} + +static bool kru_initialize(struct kru *kru, int capacity_log, kru_price_t max_decay) +{ + if (!kru) { + return false; + } + + uint32_t loads_bits = capacity2loads(capacity_log); + if (8 * sizeof(hash_t) < TABLE_COUNT * loads_bits + + 8 * sizeof(((struct kru *)0)->load_cls[0]->ids[0])) { + assert(false); + return false; + } + + kru->loads_bits = loads_bits; + + if (dnssec_random_buffer((uint8_t *)&kru->hash_key, sizeof(kru->hash_key)) != DNSSEC_EOK) { + return false; + } + + decay_initialize(&kru->decay, max_decay); + + return true; +} + +struct query_ctx { + struct load_cl *l[TABLE_COUNT]; + uint32_t time_now; + kru_price_t price; + uint16_t price16, limit16; + uint16_t id; + uint16_t final_load_value; // set by kru_limited_update if not blocked + uint16_t *load; +}; + +/// Phase 1/3 of a query -- hash, prefetch, ctx init. Based on one 16-byte key. +static inline void kru_limited_prefetch(struct kru *kru, uint32_t time_now, uint8_t key[static 16], kru_price_t price, struct query_ctx *ctx) +{ + // Obtain hash of *buf. + hash_t hash; +#if !USE_AES + hash = SipHash(&kru->hash_key, SIPHASH_RC, SIPHASH_RF, key, 16); +#else + { + __m128i h; /// hashing state + h = _mm_load_si128((__m128i *)key); + // Now do the the hashing itself. + __m128i *aes_key = (void*)kru->hash_key; + for (int i = 0; i < AES_ROUNDS; ++i) { + int key_id = i % (sizeof(kru->hash_key) / sizeof(__m128i)); + h = _mm_aesenc_si128(h, _mm_load_si128(&aes_key[key_id])); + } + memcpy(&hash, &h, sizeof(hash)); + } +#endif + + // Choose the cache-lines to operate on + const uint32_t loads_mask = (1 << kru->loads_bits) - 1; + // Fetch the two cache-lines in parallel before we really touch them. + for (int li = 0; li < TABLE_COUNT; ++li) { + struct load_cl * const l = &kru->load_cls[hash & loads_mask][li]; + __builtin_prefetch(l, 0); // hope for read-only access + hash >>= kru->loads_bits; + ctx->l[li] = l; + } + + ctx->time_now = time_now; + ctx->price = price; + ctx->id = hash; +} + +/// Phase 1/3 of a query -- hash, prefetch, ctx init. Based on a bit prefix of one 16-byte key. +static inline void kru_limited_prefetch_prefix(struct kru *kru, uint32_t time_now, uint8_t namespace, uint8_t key[static 16], uint8_t prefix, kru_price_t price, struct query_ctx *ctx) +{ + // Obtain hash of *buf. + hash_t hash; + +#if !USE_AES + { + const int rc = SIPHASH_RC, rf = SIPHASH_RF; + + // Hash prefix of key, prefix size, and namespace together. + SIPHASH_CTX hctx; + SipHash_Init(&hctx, &kru->hash_key); + SipHash_Update(&hctx, rc, rf, &namespace, sizeof(namespace)); + SipHash_Update(&hctx, rc, rf, &prefix, sizeof(prefix)); + SipHash_Update(&hctx, rc, rf, key, prefix / 8); + if (prefix % 8) { + const uint8_t masked_byte = key[prefix / 8] & (0xFF00 >> (prefix % 8)); + SipHash_Update(&hctx, rc, rf, &masked_byte, 1); + } + hash = SipHash_End(&hctx, rc, rf); + } +#else + { + + __m128i h; /// hashing state + h = _mm_load_si128((__m128i *)key); + + { // Keep only the prefix. + const uint8_t p = prefix; + + // Prefix mask (1...0) -> little endian byte array (0x00 ... 0x00 0xFF ... 0xFF). + __m128i mask = _mm_set_epi64x( + (p < 64 ? (p == 0 ? 0 : (uint64_t)-1 << (64 - p)) : (uint64_t)-1), // higher 64 bits (1...) -> second half of byte array (... 0xFF) + (p <= 64 ? 0 : (uint64_t)-1 << (128 - p))); // lower 64 bits (...0) -> first half of byte array (0x00 ...) + + // Swap mask endianness (0x11 ... 0x11 0x00 ... 0x00). + mask = _mm_shuffle_epi8(mask, + _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)); + + // Apply mask. + h = _mm_and_si128(h, mask); + } + + // Now do the the hashing itself. + __m128i *aes_key = (void*)kru->hash_key; + { + // Mix namespace and prefix size into the first aes key. + __m128i aes_key1 = _mm_insert_epi16(_mm_load_si128(aes_key), (namespace << 8) | prefix, 0); + h = _mm_aesenc_si128(h, aes_key1); + } + for (int j = 1; j < AES_ROUNDS; ++j) { + int key_id = j % (sizeof(kru->hash_key) / sizeof(__m128i)); + h = _mm_aesenc_si128(h, _mm_load_si128(&aes_key[key_id])); + } + memcpy(&hash, &h, sizeof(hash)); + } +#endif + + // Choose the cache-lines to operate on + const uint32_t loads_mask = (1 << kru->loads_bits) - 1; + // Fetch the two cache-lines in parallel before we really touch them. + for (int li = 0; li < TABLE_COUNT; ++li) { + struct load_cl * const l = &kru->load_cls[hash & loads_mask][li]; + __builtin_prefetch(l, 0); // hope for read-only access + hash >>= kru->loads_bits; + ctx->l[li] = l; + } + + ctx->time_now = time_now; + ctx->price = price; + ctx->id = hash; +} + +/// Phase 2/3 of a query -- returns answer with no state modification (except update_time). +static inline bool kru_limited_fetch(struct kru *kru, struct query_ctx *ctx) +{ + // Compute 16-bit limit and price. + // For 32-bit prices we assume that a 16-bit load value corresponds + // to the 32-bit value extended by low-significant ones and the limit is 2^32 (without ones). + // The 16-bit price is thus rounded up for the comparison with limit, + // but rounded probabilistically for rising the load. + { + const int fract_bits = 8 * sizeof(ctx->price) - 16; + const kru_price_t price = ctx->price; + const kru_price_t fract = price & ((((kru_price_t)1) << fract_bits) - 1); + + ctx->price16 = price >> fract_bits; + ctx->limit16 = -ctx->price16; + + if ((fract_bits > 0) && (fract > 0)) { + ctx->price16 += (rand_bits(fract_bits) < fract); + ctx->limit16--; + } + } + + for (int li = 0; li < TABLE_COUNT; ++li) { + update_time(ctx->l[li], ctx->time_now, &kru->decay); + } + + const uint16_t id = ctx->id; + + // Find matching element. Matching 16 bits in addition to loads_bits. + ctx->load = NULL; +#if !USE_AVX2 + for (int li = 0; li < TABLE_COUNT; ++li) + for (int i = 0; i < LOADS_LEN; ++i) + if (ctx->l[li]->ids[i] == id) { + ctx->load = &ctx->l[li]->loads[i]; + goto load_found; + } +#else + const __m256i id_v = _mm256_set1_epi16(id); + for (int li = 0; li < TABLE_COUNT; ++li) { + static_assert(LOADS_LEN == 15 && sizeof(ctx->l[li]->ids[0]) == 2, ""); + // unfortunately we can't use aligned load here + __m256i ids_v = _mm256_loadu_si256((__m256i *)((uint16_t *)ctx->l[li]->ids - 1)); + __m256i match_mask = _mm256_cmpeq_epi16(ids_v, id_v); + if (_mm256_testz_si256(match_mask, match_mask)) + continue; // no match of id + int index = _bit_scan_reverse(_mm256_movemask_epi8(match_mask)) / 2 - 1; + // there's a small possibility that we hit equality only on the -1 index + if (index >= 0) { + ctx->load = &ctx->l[li]->loads[index]; + goto load_found; + } + } +#endif + + ctx->final_load_value = 0; + return false; + +load_found:; + ctx->final_load_value = *ctx->load; + return (ctx->final_load_value >= ctx->limit16); +} + +/// Phase 3/3 of a query -- state update, return value overrides previous answer in case of race. +/// Not needed if blocked by fetch phase. If overflow_update is activated, false is always returned. +static inline bool kru_limited_update(struct kru *kru, struct query_ctx *ctx, bool overflow_update) +{ + _Atomic uint16_t *load_at; + if (!ctx->load) { + // No match, so find position of the smallest load. + int min_li = 0; + int min_i = 0; +#if !USE_SSE41 + for (int li = 0; li < TABLE_COUNT; ++li) + for (int i = 0; i < LOADS_LEN; ++i) + if (ctx->l[li]->loads[i] < ctx->l[min_li]->loads[min_i]) { + min_li = li; + min_i = i; + } +#else + int min_val = 0; + for (int li = 0; li < TABLE_COUNT; ++li) { + // BEWARE: we're relying on the exact memory layout of struct load_cl, + // where the .loads array take 15 16-bit values at the very end. + static_assert((offsetof(struct load_cl, loads) - 2) % 16 == 0, + "bad alignment of struct load_cl::loads"); + static_assert(LOADS_LEN == 15 && sizeof(ctx->l[li]->loads[0]) == 2, ""); + __m128i *l_v = (__m128i *)((uint16_t *)ctx->l[li]->loads - 1); + __m128i l0 = _mm_load_si128(l_v); + __m128i l1 = _mm_load_si128(l_v + 1); + // We want to avoid the first item in l0, so we maximize it. + // (but this function takes a signed integer, so -1 is the maximum) + l0 = _mm_insert_epi16(l0, -1, 0); + + // Only one instruction can find minimum and its position, + // and it works on 8x uint16_t. + __m128i mp0 = _mm_minpos_epu16(l0); + __m128i mp1 = _mm_minpos_epu16(l1); + int min0 = _mm_extract_epi16(mp0, 0); + int min1 = _mm_extract_epi16(mp1, 0); + int min01, min_ix; + if (min0 < min1) { + min01 = min0; + min_ix = _mm_extract_epi16(mp0, 1); + } else { + min01 = min1; + min_ix = 8 + _mm_extract_epi16(mp1, 1); + } + + if (li == 0 || min_val > min01) { + min_li = li; + min_i = min_ix; + min_val = min01; + } + } + // now, min_i (and min_ix) is offset by one due to alignment of .loads + if (min_i != 0) // zero is very unlikely + --min_i; +#endif + + ctx->l[min_li]->ids[min_i] = ctx->id; + load_at = (_Atomic uint16_t *)&ctx->l[min_li]->loads[min_i]; + } else { + load_at = (_Atomic uint16_t *)ctx->load; + } + + static_assert(ATOMIC_CHAR16_T_LOCK_FREE == 2, "insufficient atomics"); + const uint16_t price = ctx->price16; + const uint16_t limit = ctx->limit16; + uint16_t load_orig = atomic_load_explicit(load_at, memory_order_relaxed); + uint16_t load_new; + do { + if (load_orig >= limit) { + if (overflow_update) { + load_new = -1; + } else { + return true; + } + } else { + load_new = load_orig + price; + } + } while (!atomic_compare_exchange_weak_explicit(load_at, &load_orig, load_new, memory_order_relaxed, memory_order_relaxed)); + + ctx->final_load_value = load_new; + return false; +} + +static bool kru_limited_multi_or(struct kru *kru, uint32_t time_now, uint8_t **keys, kru_price_t *prices, size_t queries_cnt) +{ + struct query_ctx ctx[queries_cnt]; + + for (size_t i = 0; i < queries_cnt; i++) { + kru_limited_prefetch(kru, time_now, keys[i], prices[i], ctx + i); + } + for (size_t i = 0; i < queries_cnt; i++) { + if (kru_limited_fetch(kru, ctx + i)) + return true; + } + bool ret = false; + + for (size_t i = 0; i < queries_cnt; i++) { + ret |= kru_limited_update(kru, ctx + i, false); + } + + return ret; +} + +static bool kru_limited_multi_or_nobreak(struct kru *kru, uint32_t time_now, uint8_t **keys, kru_price_t *prices, size_t queries_cnt) +{ + struct query_ctx ctx[queries_cnt]; + bool ret = false; + + for (size_t i = 0; i < queries_cnt; i++) { + kru_limited_prefetch(kru, time_now, keys[i], prices[i], ctx + i); + } + for (size_t i = 0; i < queries_cnt; i++) { + if (kru_limited_fetch(kru, ctx + i)) + ret = true; + } + if (ret) return true; + + for (size_t i = 0; i < queries_cnt; i++) { + if (kru_limited_update(kru, ctx + i, false)) + ret = true; + } + + return ret; +} + +static uint8_t kru_limited_multi_prefix_or(struct kru *kru, uint32_t time_now, uint8_t namespace, + uint8_t key[static 16], uint8_t *prefixes, kru_price_t *prices, size_t queries_cnt, uint16_t *max_load_out) +{ + struct query_ctx ctx[queries_cnt]; + + for (size_t i = 0; i < queries_cnt; i++) { + kru_limited_prefetch_prefix(kru, time_now, namespace, key, prefixes[i], prices[i], ctx + i); + } + + for (size_t i = 0; i < queries_cnt; i++) { + if (kru_limited_fetch(kru, ctx + i)) + return prefixes[i]; + } + + for (int i = queries_cnt - 1; i >= 0; i--) { + if (kru_limited_update(kru, ctx + i, false)) + return prefixes[i]; + } + + if (max_load_out) { + *max_load_out = 0; + for (size_t i = 0; i < queries_cnt; i++) { + *max_load_out = MAX(*max_load_out, ctx[i].final_load_value); + } + } + + return 0; +} + +static uint16_t kru_load_multi_prefix_max(struct kru *kru, uint32_t time_now, uint8_t namespace, + uint8_t key[static 16], uint8_t *prefixes, kru_price_t *prices, size_t queries_cnt, uint8_t *prefix_out) +{ + struct query_ctx ctx[queries_cnt]; + + for (size_t i = 0; i < queries_cnt; i++) { + kru_limited_prefetch_prefix(kru, time_now, namespace, key, prefixes[i], (prices ? prices[i] : 0), ctx + i); + } + + for (size_t i = 0; i < queries_cnt; i++) { + kru_limited_fetch(kru, ctx + i); + } + + if (prices) { + for (int i = queries_cnt - 1; i >= 0; i--) { + kru_limited_update(kru, ctx + i, true); + } + } + + uint8_t prefix = 0; + uint16_t max_load = 0; + for (size_t i = 0; i < queries_cnt; i++) { + if (max_load < ctx[i].final_load_value) { + max_load = ctx[i].final_load_value; + prefix = prefixes[i]; + } + } + if (prefix_out) { + *prefix_out = prefix; + } + + return max_load; +} + +/// Update limiting and return true iff it hit the limit instead. +static bool kru_limited(struct kru *kru, uint32_t time_now, uint8_t key[static 16], kru_price_t price) +{ + return kru_limited_multi_or(kru, time_now, &key, &price, 1); +} + +#define KRU_API_INITIALIZER { \ + .get_size = kru_get_size, \ + .initialize = kru_initialize, \ + .limited = kru_limited, \ + .limited_multi_or = kru_limited_multi_or, \ + .limited_multi_or_nobreak = kru_limited_multi_or_nobreak, \ + .limited_multi_prefix_or = kru_limited_multi_prefix_or, \ + .load_multi_prefix_max = kru_load_multi_prefix_max, \ +} diff --git a/src/knot/modules/rrl/rrl.c b/src/knot/modules/rrl/rrl.c index 64f6cbf..d1ec7b5 100644 --- a/src/knot/modules/rrl/rrl.c +++ b/src/knot/modules/rrl/rrl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,28 +14,47 @@ along with this program. If not, see . */ +#include "contrib/time.h" #include "knot/include/module.h" -#include "knot/nameserver/process_query.h" // Dependency on qdata->extra! #include "knot/modules/rrl/functions.h" +#include "knot/modules/rrl/kru.h" #define MOD_RATE_LIMIT "\x0A""rate-limit" +#define MOD_INST_LIMIT "\x0D""instant-limit" +#define MOD_T_RATE_LIMIT "\x0F""time-rate-limit" +#define MOD_T_INST_LIMIT "\x12""time-instant-limit" #define MOD_SLIP "\x04""slip" #define MOD_TBL_SIZE "\x0A""table-size" #define MOD_WHITELIST "\x09""whitelist" +#define MOD_LOG_PERIOD "\x0A""log-period" +#define MOD_DRY_RUN "\x07""dry-run" const yp_item_t rrl_conf[] = { - { MOD_RATE_LIMIT, YP_TINT, YP_VINT = { 1, INT32_MAX } }, - { MOD_SLIP, YP_TINT, YP_VINT = { 0, 100, 1 } }, - { MOD_TBL_SIZE, YP_TINT, YP_VINT = { 1, INT32_MAX, 393241 } }, - { MOD_WHITELIST, YP_TNET, YP_VNONE, YP_FMULTI }, + { MOD_INST_LIMIT, YP_TINT, YP_VINT = { 1, (1ll << 32) / 768 - 1, 50 } }, + { MOD_RATE_LIMIT, YP_TINT, YP_VINT = { 0, ((1ll << 32) / 768 - 1) * 1000, 20 } }, + { MOD_T_INST_LIMIT, YP_TINT, YP_VINT = { 1, 1000000, 5000 } }, + { MOD_T_RATE_LIMIT, YP_TINT, YP_VINT = { 0, 1000000000, 4000 } }, + { MOD_SLIP, YP_TINT, YP_VINT = { 0, 100, 1 } }, + { MOD_TBL_SIZE, YP_TINT, YP_VINT = { 1, INT32_MAX, 524288 } }, + { MOD_WHITELIST, YP_TNET, YP_VNONE, YP_FMULTI }, + { MOD_LOG_PERIOD, YP_TINT, YP_VINT = { 0, INT32_MAX, 0 } }, + { MOD_DRY_RUN, YP_TBOOL, YP_VNONE }, { NULL } }; int rrl_conf_check(knotd_conf_check_args_t *args) { - knotd_conf_t limit = knotd_conf_check_item(args, MOD_RATE_LIMIT); - if (limit.count == 0) { - args->err_str = "no rate limit specified"; + knotd_conf_t rate_limit = knotd_conf_check_item(args, MOD_RATE_LIMIT); + knotd_conf_t inst_limit = knotd_conf_check_item(args, MOD_INST_LIMIT); + if (rate_limit.single.integer > 1000ll * inst_limit.single.integer) { + args->err_str = "rate limit is higher than 1000 times instant rate limit"; + return KNOT_EINVAL; + } + + knotd_conf_t t_rate_limit = knotd_conf_check_item(args, MOD_T_RATE_LIMIT); + knotd_conf_t t_inst_limit = knotd_conf_check_item(args, MOD_T_INST_LIMIT); + if (t_rate_limit.single.integer > 1000ll * t_inst_limit.single.integer) { + args->err_str = "time rate limit is higher than 1000 times time instant limit"; return KNOT_EINVAL; } @@ -43,35 +62,78 @@ int rrl_conf_check(knotd_conf_check_args_t *args) } typedef struct { - rrl_table_t *rrl; + ALIGNED_CPU_CACHE // Ensures that one thread context occupies one cache line. + struct timespec start_time; // Start time of the measurement. + bool whitelist_checked; // Indication whether whitelist check took place. + bool skip; // Skip the rest of the module callbacks. +} thrd_ctx_t; + +typedef struct { + rrl_table_t *rate_table; + rrl_table_t *time_table; + thrd_ctx_t *thrd_ctx; int slip; + bool dry_run; knotd_conf_t whitelist; } rrl_ctx_t; -static const knot_dname_t *name_from_rrsig(const knot_rrset_t *rr) +static uint32_t time_diff_us(const struct timespec *begin, const struct timespec *end) +{ + struct timespec result = time_diff(begin, end); + return (result.tv_sec * 1000000) + (result.tv_nsec / 1000); +} + +static knotd_proto_state_t protolimit_start(knotd_proto_state_t state, + knotd_qdata_params_t *params, + knotd_mod_t *mod) { - if (rr == NULL) { - return NULL; + rrl_ctx_t *ctx = knotd_mod_ctx(mod); + thrd_ctx_t *thrd = &ctx->thrd_ctx[params->thread_id]; + thrd->skip = false; + + // Check if a whitelisted client. + thrd->whitelist_checked = true; + if (knotd_conf_addr_range_match(&ctx->whitelist, params->remote)) { + thrd->skip = true; + return state; } - if (rr->type != KNOT_RRTYPE_RRSIG) { - return NULL; + + // UDP time limiting not implemented (source address can be forged). + if (params->proto == KNOTD_QUERY_PROTO_UDP) { + return state; } - // This is a signature. - return knot_rrsig_signer_name(rr->rrs.rdata); + // Check if the packet is limited. + if (rrl_query(ctx->time_table, params->remote, mod) != KNOT_EOK) { + thrd->skip = true; + knotd_mod_stats_incr(mod, params->thread_id, 2, 0, 1); + return ctx->dry_run ? state : KNOTD_PROTO_STATE_BLOCK; + } else { + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &thrd->start_time); + return state; // Not limited. + } } -static const knot_dname_t *name_from_authrr(const knot_rrset_t *rr) +static knotd_proto_state_t protolimit_end(knotd_proto_state_t state, + knotd_qdata_params_t *params, + knotd_mod_t *mod) { - if (rr == NULL) { - return NULL; + rrl_ctx_t *ctx = knotd_mod_ctx(mod); + thrd_ctx_t *thrd = &ctx->thrd_ctx[params->thread_id]; + + if (thrd->skip || params->proto == KNOTD_QUERY_PROTO_UDP) { + return state; } - if (rr->type != KNOT_RRTYPE_NS && rr->type != KNOT_RRTYPE_SOA) { - return NULL; + + // Update the time table. + struct timespec end_time; + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end_time); + uint64_t diff = time_diff_us(&thrd->start_time, &end_time); + if (diff > 0) { // Zero KRU update is NOOP. + rrl_update(ctx->time_table, params->remote, diff); } - // This is a valid authority RR. - return rr->owner; + return state; } static knotd_state_t ratelimit_apply(knotd_state_t state, knot_pkt_t *pkt, @@ -80,57 +142,36 @@ static knotd_state_t ratelimit_apply(knotd_state_t state, knot_pkt_t *pkt, assert(pkt && qdata && mod); rrl_ctx_t *ctx = knotd_mod_ctx(mod); + thrd_ctx_t *thrd = &ctx->thrd_ctx[qdata->params->thread_id]; - // Rate limit is applied to pure UDP only. - if (qdata->params->proto != KNOTD_QUERY_PROTO_UDP) { + if (thrd->skip) { return state; } - // Rate limit is not applied to responses with a valid cookie. - if (qdata->params->flags & KNOTD_QUERY_FLAG_COOKIE) { + // Don't limit authorized operations. + if (qdata->params->flags & KNOTD_QUERY_FLAG_AUTHORIZED) { + thrd->skip = true; return state; } - // Exempt clients. - if (knotd_conf_addr_range_match(&ctx->whitelist, knotd_qdata_remote_addr(qdata))) { + // Rate limit is applied to UDP only. + if (qdata->params->proto != KNOTD_QUERY_PROTO_UDP) { return state; } - rrl_req_t req = { - .wire = pkt->wire, - .query = qdata->query - }; - - if (!EMPTY_LIST(qdata->extra->wildcards)) { - req.flags = RRL_REQ_WILDCARD; - } - - // Take the zone name if known. - const knot_dname_t *zone_name = knotd_qdata_zone_name(qdata); - - // Take the signer name as zone name if there is an RRSIG. - if (zone_name == NULL) { - const knot_pktsection_t *ans = knot_pkt_section(pkt, KNOT_ANSWER); - for (int i = 0; i < ans->count; i++) { - zone_name = name_from_rrsig(knot_pkt_rr(ans, i)); - if (zone_name != NULL) { - break; - } - } + // Check for whitelisted client IF PER-ZONE module (no proto callbacks). + if (!thrd->whitelist_checked && + knotd_conf_addr_range_match(&ctx->whitelist, qdata->params->remote)) { + thrd->skip = true; + return state; } - // Take the NS or SOA owner name if there is no RRSIG. - if (zone_name == NULL) { - const knot_pktsection_t *auth = knot_pkt_section(pkt, KNOT_AUTHORITY); - for (int i = 0; i < auth->count; i++) { - zone_name = name_from_authrr(knot_pkt_rr(auth, i)); - if (zone_name != NULL) { - break; - } - } + // Rate limit is not applied to responses with a valid cookie. + if (qdata->params->flags & KNOTD_QUERY_FLAG_COOKIE) { + return state; } - if (rrl_query(ctx->rrl, knotd_qdata_remote_addr(qdata), &req, zone_name, mod) == KNOT_EOK) { + if (rrl_query(ctx->rate_table, knotd_qdata_remote_addr(qdata), mod) == KNOT_EOK) { // Rate limiting not applied. return state; } @@ -139,11 +180,11 @@ static knotd_state_t ratelimit_apply(knotd_state_t state, knot_pkt_t *pkt, // Slip the answer. knotd_mod_stats_incr(mod, qdata->params->thread_id, 0, 0, 1); qdata->err_truncated = true; - return KNOTD_STATE_FAIL; + return ctx->dry_run ? state : KNOTD_STATE_FAIL; } else { // Drop the answer. knotd_mod_stats_incr(mod, qdata->params->thread_id, 1, 0, 1); - return KNOTD_STATE_NOOP; + return ctx->dry_run ? state : KNOTD_STATE_NOOP; } } @@ -151,58 +192,96 @@ static void ctx_free(rrl_ctx_t *ctx) { assert(ctx); - rrl_destroy(ctx->rrl); + free(ctx->thrd_ctx); + rrl_destroy(ctx->rate_table); + rrl_destroy(ctx->time_table); + knotd_conf_free(&ctx->whitelist); free(ctx); } int rrl_load(knotd_mod_t *mod) { - // Create RRL context. rrl_ctx_t *ctx = calloc(1, sizeof(rrl_ctx_t)); if (ctx == NULL) { return KNOT_ENOMEM; } - // Create table. - uint32_t rate = knotd_conf_mod(mod, MOD_RATE_LIMIT).single.integer; - size_t size = knotd_conf_mod(mod, MOD_TBL_SIZE).single.integer; - ctx->rrl = rrl_create(size, rate); - if (ctx->rrl == NULL) { + ctx->dry_run = knotd_conf_mod(mod, MOD_DRY_RUN).single.boolean; + ctx->whitelist = knotd_conf_mod(mod, MOD_WHITELIST); + + ctx->thrd_ctx = calloc(knotd_mod_threads(mod), sizeof(*ctx->thrd_ctx)); + if (ctx->thrd_ctx == NULL) { ctx_free(ctx); return KNOT_ENOMEM; } - // Get slip. - ctx->slip = knotd_conf_mod(mod, MOD_SLIP).single.integer; + size_t size = knotd_conf_mod(mod, MOD_TBL_SIZE).single.integer; + uint32_t log_period = knotd_conf_mod(mod, MOD_LOG_PERIOD).single.integer; + + uint32_t rate_limit = knotd_conf_mod(mod, MOD_RATE_LIMIT).single.integer; + if (rate_limit > 0) { + uint32_t inst_limit = knotd_conf_mod(mod, MOD_INST_LIMIT).single.integer; + ctx->rate_table = rrl_create(size, inst_limit, rate_limit, true, log_period); + if (ctx->rate_table == NULL) { + ctx_free(ctx); + return KNOT_ENOMEM; + } + ctx->slip = knotd_conf_mod(mod, MOD_SLIP).single.integer; + } - // Get whitelist. - ctx->whitelist = knotd_conf_mod(mod, MOD_WHITELIST); + uint32_t time_limit = knotd_conf_mod(mod, MOD_T_RATE_LIMIT).single.integer; + if (time_limit > 0) { + uint32_t inst_limit = knotd_conf_mod(mod, MOD_T_INST_LIMIT).single.integer; + ctx->time_table = rrl_create(size, inst_limit, time_limit, false, log_period); + if (ctx->time_table == NULL) { + ctx_free(ctx); + return KNOT_ENOMEM; + } + } - // Set up statistics counters. int ret = knotd_mod_stats_add(mod, "slipped", 1, NULL); if (ret != KNOT_EOK) { ctx_free(ctx); return ret; } - ret = knotd_mod_stats_add(mod, "dropped", 1, NULL); if (ret != KNOT_EOK) { ctx_free(ctx); return ret; } + ret = knotd_mod_stats_add(mod, "dropped-time", 1, NULL); + if (ret != KNOT_EOK) { + ctx_free(ctx); + return ret; + } + + /* The explicit reference of the AVX2 variant ensures the optimized + * code isn't removed by linker if linking statically. + * Check: nm ./src/.libs/knotd | grep KRU_ + * https://stackoverflow.com/a/28663156/587396 + */ + knotd_mod_log(mod, LOG_DEBUG, "using %s implementation", + KRU.limited == KRU_AVX2.limited ? "optimized" : "generic"); knotd_mod_ctx_set(mod, ctx); - return knotd_mod_hook(mod, KNOTD_STAGE_END, ratelimit_apply); + if (rate_limit > 0) { + knotd_mod_hook(mod, KNOTD_STAGE_BEGIN, ratelimit_apply); + } + + if (time_limit > 0) { + // Note that these two callbacks aren't executed IF PER-ZONE module! + knotd_mod_proto_hook(mod, KNOTD_STAGE_PROTO_BEGIN, protolimit_start); + knotd_mod_proto_hook(mod, KNOTD_STAGE_PROTO_END, protolimit_end); + } + + return KNOT_EOK; } void rrl_unload(knotd_mod_t *mod) { - rrl_ctx_t *ctx = knotd_mod_ctx(mod); - - knotd_conf_free(&ctx->whitelist); - ctx_free(ctx); + ctx_free(knotd_mod_ctx(mod)); } -KNOTD_MOD_API(rrl, KNOTD_MOD_FLAG_SCOPE_ANY, +KNOTD_MOD_API(rrl, KNOTD_MOD_FLAG_SCOPE_ANY | KNOTD_MOD_FLAG_OPT_CONF, rrl_load, rrl_unload, rrl_conf, rrl_conf_check); diff --git a/src/knot/modules/rrl/rrl.rst b/src/knot/modules/rrl/rrl.rst index 0daae16..85c8d35 100644 --- a/src/knot/modules/rrl/rrl.rst +++ b/src/knot/modules/rrl/rrl.rst @@ -4,37 +4,52 @@ ================================ Response rate limiting (RRL) is a method to combat DNS reflection amplification -attacks. These attacks rely on the fact that source address of a UDP query +attacks. These attacks rely on the fact that the source address of a UDP query can be forged, and without a worldwide deployment of `BCP38 `_, such a forgery cannot be prevented. An attacker can use a DNS server (or multiple servers) as an amplification -source and can flood a victim with a large number of unsolicited DNS responses. -The RRL lowers the amplification factor of these attacks by sending some of -the responses as truncated or by dropping them altogether. +source to flood a victim with a large number of unsolicited DNS responses. +RRL lowers the amplification factor of these attacks by sending some +responses as truncated or by dropping them altogether. + +This module can also help protect the server from excessive utilization by +limiting incoming packets (including handshakes) based on consumed time. +If a packet is time rate limited, it's dropped. This function works with +all supported non-UDP transport protocols and cannot be configured per zone. .. NOTE:: - The module introduces two statistics counters. The number of slipped and - dropped responses. + This module introduces three statistics counters: + + - ``slipped`` – The number of slipped UDP responses. + - ``dropped`` – The number of dropped UDP responses due to the rate limit. + - ``dropped-time`` – The number of dropped non-UDP packets due to the time rate limit. .. NOTE:: If the :ref:`Cookies` module is active, RRL is not applied - for responses with a valid DNS cookie. + to UDP responses with a valid DNS cookie. Example ------- -You can enable RRL by setting the module globally or per zone. +You can enable RRL by setting the module globally :: - mod-rrl: - - id: default - rate-limit: 200 # Allow 200 resp/s for each flow - slip: 2 # Approximately every other response slips - template: - id: default - global-module: mod-rrl/default # Enable RRL globally + global-module: mod-rrl # Default module configuration + +or per zone + +:: + + mod-rrl: + - id: custom + rate-limit: 200 + + zone: + - domain: example.com + module: mod-rrl/custom # Custom module configuration Module reference ---------------- @@ -44,9 +59,14 @@ Module reference mod-rrl: - id: STR rate-limit: INT + instant-limit: INT slip: INT + time-rate-limit: INT + time-instant-limit: INT table-size: INT whitelist: ADDR[/INT] | ADDR-ADDR | STR ... + log-period: INT + dry-run: BOOL .. _mod-rrl_id: @@ -60,30 +80,42 @@ A module identifier. rate-limit .......... -Rate limiting is based on the token bucket scheme. A rate basically -represents a number of tokens available each second. Each response is -processed and classified (based on several discriminators, e.g. -source netblock, query type, zone name, rcode, etc.). Classified responses are -then hashed and assigned to a bucket containing number of available -tokens, timestamp and metadata. When available tokens are exhausted, -response is dropped or sent as truncated (see :ref:`mod-rrl_slip`). -Number of available tokens is recalculated each second. +Maximal allowed number of UDP queries per second from a single IPv6 or IPv4 address. -*Required* +Rate limiting is performed for the whole address and several chosen prefixes. +The limits of prefixes are constant multiples of :ref:`mod-rrl_rate-limit`. -.. _mod-rrl_table-size: +The specific prefixes and multipliers, which might be adjusted in the future, are +for IPv6 /128: 1, /64: 2, /56: 3, /48: 4, /32: 64; +for IPv4 /32: 1, /24: 32, /20: 256, /18: 768. -table-size -.......... +With each host/network, a counter of unrestricted responses is associated; +if the counter would exceed its capacity, it is not incremented and the response is restricted. +Counters use exponential decay for lowering their values, +i.e. they are lowered by a constant fraction of their value each millisecond. +The specified rate limit is reached, when the number of queries is the same every millisecond; +sending many queries once a second or even a larger timespan leads to a more strict limiting. + +*Default:* ``20`` + +.. _mod-rrl_instant-limit: + +instant-limit +............. + +Maximal allowed number of queries at a single point in time from a single IPv6 or IPv4 address. +The limits for prefixes use the same multipliers as for :ref:`mod-rrl_rate-limit`. -Size of the hash table in a number of buckets. The larger the hash table, the lesser -the probability of a hash collision, but at the expense of additional memory costs. -Each bucket is estimated roughly to 32 bytes. The size should be selected as -a reasonably large prime due to better hash function distribution properties. -Hash table is internally chained and works well up to a fill rate of 90 %, general -rule of thumb is to select a prime near 1.2 * maximum_qps. +This limit is reached when many queries come from a new host/network, +or after a longer time of inactivity. -*Default:* ``393241`` +The :ref:`mod-rrl_instant-limit` sets the actual capacity of each counter of responses, +and together with the :ref:`mod-rrl_rate-limit` they set the fraction by which the counter +is periodically lowered. +The :ref:`mod-rrl_instant-limit` may be at least :ref:`mod-rrl_rate-limit` **/ 1000**, at which point the +counters are zeroed each millisecond. + +*Default:* ``50`` .. _mod-rrl_slip: @@ -121,6 +153,49 @@ noting, that some responses can't be truncated (e.g. SERVFAIL). *Default:* ``1`` +.. _mod-rrl_time-rate-limit: + +time-rate-limit +............... + +This limit works similarly to :ref:`mod-rrl_rate-limit` but considers the time +consumed (in microseconds) by the remote over non-UDP transport protocols. + +*Default:* ``4000`` (microseconds) + +.. _mod-rrl_time-instant-limit: + +time-instant-limit +.................. + +This limit works similarly to :ref:`mod-rrl_instant-limit` but considers the time +consumed (in microseconds) by the remote over non-UDP transport protocols. + +*Default:* ``5000`` (microseconds) + +.. _mod-rrl_table-size: + +table-size +.......... + +Maximal number of stored hosts/networks with their counters. +The data structure tries to store only the most frequent sources, +so it is safe to set it according to the expected maximal number of limited ones. + +Use `1.4 * maximum_qps / rate-limit`, +where `maximum_qps` is the number of queries which can be handled by the server per second. +There is at most `maximum_qps / rate-limit` limited hosts; +larger networks have higher limits and so require only a fraction of the value (handled by the `1.4` multiplier). +The value will be rounded up to the nearest power of two. + +The same table size is used for both counting-based and time-based limiting; +the maximum number of time-limited hosts is expected to be lower, so it's not typically needed to be considered. +There is at most `1 000 000 * #cpus / time-rate-limit` of them. + +The memory occupied by one table structure is `8 * table-size B`. + +*Default:* ``524288`` + .. _mod-rrl_whitelist: whitelist @@ -131,3 +206,31 @@ or network ranges to exempt from rate limiting. Empty list means that no incoming connection will be white-listed. *Default:* not set + +.. _mod-rrl_log-period: + +log-period +.......... + +Minimal time in milliseconds between two log messages, +or zero to disable logging. + +If a response is limited, the address and the prefix on which it was blocked is logged +and logging is disabled for the `log-period` milliseconds. +As long as limiting is needed, one source is logged each period +and sources with more blocked queries have greater probability to be chosen. + +The approach is used by counting-based and time-based limiting separately, +so you can expect one message per `log-period` from each of them. + +*Default:* ``0`` (disabled) + +.. _mod-rrl_dry-run: + +dry-run +....... + +If enabled, the module doesn't alter any response. Only query classification +is performed with possible statistics counter incrementation. + +*Default:* ``off`` diff --git a/src/knot/modules/stats/stats.c b/src/knot/modules/stats/stats.c index 26262ac..c5b797b 100644 --- a/src/knot/modules/stats/stats.c +++ b/src/knot/modules/stats/stats.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -118,9 +118,11 @@ enum { PROTOCOL_UDP4 = 0, PROTOCOL_TCP4, PROTOCOL_QUIC4, + PROTOCOL_TLS4, PROTOCOL_UDP6, PROTOCOL_TCP6, PROTOCOL_QUIC6, + PROTOCOL_TLS6, PROTOCOL_UDP4_XDP, PROTOCOL_TCP4_XDP, PROTOCOL_QUIC4_XDP, @@ -136,9 +138,11 @@ static char *protocol_to_str(uint32_t idx, uint32_t count) case PROTOCOL_UDP4: return strdup("udp4"); case PROTOCOL_TCP4: return strdup("tcp4"); case PROTOCOL_QUIC4: return strdup("quic4"); + case PROTOCOL_TLS4: return strdup("tls4"); case PROTOCOL_UDP6: return strdup("udp6"); case PROTOCOL_TCP6: return strdup("tcp6"); case PROTOCOL_QUIC6: return strdup("quic6"); + case PROTOCOL_TLS6: return strdup("tls6"); case PROTOCOL_UDP4_XDP: return strdup("udp4-xdp"); case PROTOCOL_TCP4_XDP: return strdup("tcp4-xdp"); case PROTOCOL_QUIC4_XDP: return strdup("quic4-xdp"); @@ -521,6 +525,10 @@ static knotd_state_t update_counters(knotd_state_t state, knot_pkt_t *pkt, knotd_mod_stats_incr(mod, tid, CTR_PROTOCOL, PROTOCOL_QUIC4, 1); } + } else if (qdata->params->proto == KNOTD_QUERY_PROTO_TLS) { + assert(!xdp); + knotd_mod_stats_incr(mod, tid, CTR_PROTOCOL, + PROTOCOL_TLS4, 1); } else { if (xdp) { knotd_mod_stats_incr(mod, tid, CTR_PROTOCOL, @@ -547,6 +555,10 @@ static knotd_state_t update_counters(knotd_state_t state, knot_pkt_t *pkt, knotd_mod_stats_incr(mod, tid, CTR_PROTOCOL, PROTOCOL_QUIC6, 1); } + } else if (qdata->params->proto == KNOTD_QUERY_PROTO_TLS) { + assert(!xdp); + knotd_mod_stats_incr(mod, tid, CTR_PROTOCOL, + PROTOCOL_TLS6, 1); } else { if (xdp) { knotd_mod_stats_incr(mod, tid, CTR_PROTOCOL, diff --git a/src/knot/modules/stats/stats.rst b/src/knot/modules/stats/stats.rst index 8acf1aa..71cf87a 100644 --- a/src/knot/modules/stats/stats.rst +++ b/src/knot/modules/stats/stats.rst @@ -73,9 +73,11 @@ If enabled, all incoming requests are counted by the network protocol: * udp4 - UDP over IPv4 * tcp4 - TCP over IPv4 * quic4 - QUIC over IPv4 +* tls4 - TLS over IPv4 * udp6 - UDP over IPv6 * tcp6 - TCP over IPv6 * quic6 - QUIC over IPv6 +* tls6 - TLS over IPv6 * udp4-xdp - UDP over IPv4 through XDP * tcp4-xdp - TCP over IPv4 through XDP * quic4-xdp - QUIC over IPv4 through XDP diff --git a/src/knot/nameserver/axfr.c b/src/knot/nameserver/axfr.c index dcd62e9..cd9ee32 100644 --- a/src/knot/nameserver/axfr.c +++ b/src/knot/nameserver/axfr.c @@ -121,14 +121,14 @@ static void axfr_answer_finished(knotd_qdata_t *qdata, knot_pkt_t *pkt, int stat xfr_stats_add(&xfr->stats, pkt->size); xfr_stats_end(&xfr->stats); xfr_log_finished(ZONE_NAME(qdata), LOG_OPERATION_AXFR, LOG_DIRECTION_OUT, - REMOTE(qdata), PROTO(qdata), KEY(qdata), &xfr->stats); + REMOTE(qdata), PROTO(qdata), KEY(qdata), "", &xfr->stats); break; default: break; } } -static int axfr_query_check(knotd_qdata_t *qdata) +static knot_layer_state_t axfr_query_check(knotd_qdata_t *qdata) { NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH); NS_NEED_AUTH(qdata, ACL_ACTION_TRANSFER); @@ -187,7 +187,7 @@ static int axfr_query_init(knotd_qdata_t *qdata) return KNOT_EOK; } -int axfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) +knot_layer_state_t axfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) { if (pkt == NULL || qdata == NULL) { return KNOT_STATE_FAIL; diff --git a/src/knot/nameserver/axfr.h b/src/knot/nameserver/axfr.h index 81fcad8..25c5f1c 100644 --- a/src/knot/nameserver/axfr.h +++ b/src/knot/nameserver/axfr.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,7 +21,5 @@ /*! * \brief Process an AXFR query message. - * - * \return KNOT_STATE_* processing states */ -int axfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata); +knot_layer_state_t axfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata); diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c index 51bde97..034fd26 100644 --- a/src/knot/nameserver/internet.c +++ b/src/knot/nameserver/internet.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -286,7 +286,7 @@ static int put_additional(knot_pkt_t *pkt, const knot_rrset_t *rr, return ret; } -static int follow_cname(knot_pkt_t *pkt, uint16_t rrtype, knotd_qdata_t *qdata) +static knotd_in_state_t follow_cname(knot_pkt_t *pkt, uint16_t rrtype, knotd_qdata_t *qdata) { /* CNAME chain processing limit. */ if (++qdata->extra->cname_chain > CNAME_CHAIN_MAX) { @@ -369,7 +369,7 @@ static int follow_cname(knot_pkt_t *pkt, uint16_t rrtype, knotd_qdata_t *qdata) return KNOTD_IN_STATE_FOLLOW; } -static int name_found(knot_pkt_t *pkt, knotd_qdata_t *qdata) +static knotd_in_state_t name_found(knot_pkt_t *pkt, knotd_qdata_t *qdata) { uint16_t qtype = knot_pkt_qtype(pkt); @@ -406,7 +406,7 @@ static int name_found(knot_pkt_t *pkt, knotd_qdata_t *qdata) } } -static int name_not_found(knot_pkt_t *pkt, knotd_qdata_t *qdata) +static knotd_in_state_t name_not_found(knot_pkt_t *pkt, knotd_qdata_t *qdata) { /* Name is covered by wildcard. */ if (qdata->extra->encloser->flags & NODE_FLAGS_WILDCARD_CHILD) { @@ -419,7 +419,7 @@ static int name_not_found(knot_pkt_t *pkt, knotd_qdata_t *qdata) assert(qdata->extra->node != NULL); /* Follow expanded wildcard. */ - int next_state = name_found(pkt, qdata); + knotd_in_state_t next_state = name_found(pkt, qdata); /* Put to wildcard node list. */ if (wildcard_has_visited(qdata, wildcard_node)) { @@ -456,7 +456,8 @@ static int name_not_found(knot_pkt_t *pkt, knotd_qdata_t *qdata) return KNOTD_IN_STATE_MISS; } -static int solve_name(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata) +static knotd_in_state_t solve_name(knotd_in_state_t state, knot_pkt_t *pkt, + knotd_qdata_t *qdata) { int ret = zone_contents_find_dname(qdata->extra->contents, qdata->name, &qdata->extra->node, &qdata->extra->encloser, @@ -475,7 +476,8 @@ static int solve_name(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata) } } -static int solve_answer(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata, void *ctx) +static knotd_in_state_t solve_answer(knotd_in_state_t state, knot_pkt_t *pkt, + knotd_qdata_t *qdata, void *ctx) { int old_state = state; @@ -506,7 +508,8 @@ static int solve_answer(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata, void * return state; } -static int solve_answer_dnssec(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata, void *ctx) +static knotd_in_state_t solve_answer_dnssec(knotd_in_state_t state, knot_pkt_t *pkt, + knotd_qdata_t *qdata, void *ctx) { /* RFC4035, section 3.1 RRSIGs for RRs in ANSWER are mandatory. */ int ret = nsec_append_rrsigs(pkt, qdata, false); @@ -517,7 +520,8 @@ static int solve_answer_dnssec(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata, } } -static int solve_authority(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata, void *ctx) +static knotd_in_state_t solve_authority(knotd_in_state_t state, knot_pkt_t *pkt, + knotd_qdata_t *qdata, void *ctx) { int ret = KNOT_ERROR; const zone_contents_t *zone_contents = qdata->extra->contents; @@ -554,7 +558,8 @@ static int solve_authority(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata, voi } } -static int solve_authority_dnssec(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata, void *ctx) +static knotd_in_state_t solve_authority_dnssec(knotd_in_state_t state, knot_pkt_t *pkt, + knotd_qdata_t *qdata, void *ctx) { int ret = KNOT_ERROR; @@ -591,8 +596,8 @@ static int solve_authority_dnssec(int state, knot_pkt_t *pkt, knotd_qdata_t *qda } } -static int solve_additional(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata, - void *ctx) +static knotd_in_state_t solve_additional(knotd_in_state_t state, knot_pkt_t *pkt, + knotd_qdata_t *qdata, void *ctx) { int ret = KNOT_EOK, rrset_count = pkt->rrset_count; @@ -621,7 +626,8 @@ static int solve_additional(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata, } } -static int solve_additional_dnssec(int state, knot_pkt_t *pkt, knotd_qdata_t *qdata, void *ctx) +static knotd_in_state_t solve_additional_dnssec(knotd_in_state_t state, knot_pkt_t *pkt, + knotd_qdata_t *qdata, void *ctx) { /* RFC4035, section 3.1 RRSIGs for RRs in ADDITIONAL are optional. */ int ret = nsec_append_rrsigs(pkt, qdata, true); @@ -641,9 +647,9 @@ static int solve_additional_dnssec(int state, knot_pkt_t *pkt, knotd_qdata_t *qd return KNOT_STATE_FAIL; \ } -static int answer_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) +static knot_layer_state_t answer_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) { - int state = KNOTD_IN_STATE_BEGIN; + knotd_in_state_t state = KNOTD_IN_STATE_BEGIN; struct query_plan *plan = qdata->extra->zone->query_plan; struct query_step *step; @@ -652,7 +658,8 @@ static int answer_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) /* Resolve PREANSWER. */ if (plan != NULL) { WALK_LIST(step, plan->stage[KNOTD_STAGE_PREANSWER]) { - SOLVE_STEP(step->process, state, step->ctx); + assert(step->type == QUERY_HOOK_TYPE_IN); + SOLVE_STEP(step->in_hook, state, step->ctx); } } @@ -664,7 +671,8 @@ static int answer_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) } if (plan != NULL) { WALK_LIST(step, plan->stage[KNOTD_STAGE_ANSWER]) { - SOLVE_STEP(step->process, state, step->ctx); + assert(step->type == QUERY_HOOK_TYPE_IN); + SOLVE_STEP(step->in_hook, state, step->ctx); } } @@ -676,7 +684,8 @@ static int answer_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) } if (plan != NULL) { WALK_LIST(step, plan->stage[KNOTD_STAGE_AUTHORITY]) { - SOLVE_STEP(step->process, state, step->ctx); + assert(step->type == QUERY_HOOK_TYPE_IN); + SOLVE_STEP(step->in_hook, state, step->ctx); } } @@ -688,7 +697,8 @@ static int answer_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) } if (plan != NULL) { WALK_LIST(step, plan->stage[KNOTD_STAGE_ADDITIONAL]) { - SOLVE_STEP(step->process, state, step->ctx); + assert(step->type == QUERY_HOOK_TYPE_IN); + SOLVE_STEP(step->in_hook, state, step->ctx); } } @@ -698,7 +708,7 @@ static int answer_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) return KNOT_STATE_DONE; } -int internet_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) +knot_layer_state_t internet_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) { if (pkt == NULL || qdata == NULL) { return KNOT_STATE_FAIL; diff --git a/src/knot/nameserver/internet.h b/src/knot/nameserver/internet.h index 52afe62..bb6927d 100644 --- a/src/knot/nameserver/internet.h +++ b/src/knot/nameserver/internet.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,11 +25,8 @@ /*! * \brief Answer query from an IN class zone. - * - * \retval KNOT_STATE_FAIL if it encountered an error. - * \retval KNOT_STATE_DONE if finished. */ -int internet_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata); +knot_layer_state_t internet_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata); /*! \brief Require given QUERY TYPE or return error code. */ #define NS_NEED_QTYPE(qdata, qtype_want, error_rcode) \ @@ -68,12 +65,6 @@ int internet_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata); if (!process_query_acl_check(conf(), (action), (qdata)) || \ process_query_verify(qdata) != KNOT_EOK) { \ return KNOT_STATE_FAIL; \ - } - -/*! \brief Require the zone not to be frozen. */ -#define NS_NEED_NOT_FROZEN(qdata) \ - if ((qdata)->extra->zone->events.ufrozen) { \ - (qdata)->rcode = KNOT_RCODE_REFUSED; \ - (qdata)->rcode_ede = KNOT_EDNS_EDE_NOT_READY; \ - return KNOT_STATE_FAIL; \ + } else { \ + qdata->params->flags |= KNOTD_QUERY_FLAG_AUTHORIZED; \ } diff --git a/src/knot/nameserver/ixfr.c b/src/knot/nameserver/ixfr.c index b57759c..c0e17ea 100644 --- a/src/knot/nameserver/ixfr.c +++ b/src/knot/nameserver/ixfr.c @@ -130,7 +130,7 @@ static int ixfr_load_chsets(journal_read_t **journal_read, zone_t *zone, return journal_read_begin(zone_journal(zone), false, serial_from, journal_read); } -static int ixfr_query_check(knotd_qdata_t *qdata) +static knot_layer_state_t ixfr_query_check(knotd_qdata_t *qdata) { NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH); NS_NEED_AUTH(qdata, ACL_ACTION_TRANSFER); @@ -174,7 +174,7 @@ static void ixfr_answer_finished(knotd_qdata_t *qdata, knot_pkt_t *pkt, int stat xfr_stats_add(&xfr->stats, pkt->size); xfr_stats_end(&xfr->stats); xfr_log_finished(ZONE_NAME(qdata), LOG_OPERATION_IXFR, LOG_DIRECTION_OUT, - REMOTE(qdata), PROTO(qdata), KEY(qdata), &xfr->stats); + REMOTE(qdata), PROTO(qdata), KEY(qdata), "", &xfr->stats); break; default: break; @@ -245,13 +245,13 @@ static int ixfr_answer_init(knotd_qdata_t *qdata, uint32_t *serial_from) return KNOT_EOK; } -static int ixfr_answer_soa(knot_pkt_t *pkt, knotd_qdata_t *qdata) +static knot_layer_state_t ixfr_answer_soa(knot_pkt_t *pkt, knotd_qdata_t *qdata) { assert(pkt); assert(qdata); /* Check query. */ - int state = ixfr_query_check(qdata); + knot_layer_state_t state = ixfr_query_check(qdata); if (state == KNOT_STATE_FAIL) { return state; /* Malformed query. */ } @@ -277,7 +277,7 @@ static int ixfr_answer_soa(knot_pkt_t *pkt, knotd_qdata_t *qdata) return KNOT_STATE_DONE; } -int ixfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) +knot_layer_state_t ixfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) { if (pkt == NULL || qdata == NULL) { return KNOT_STATE_FAIL; diff --git a/src/knot/nameserver/ixfr.h b/src/knot/nameserver/ixfr.h index 3012be1..91ce750 100644 --- a/src/knot/nameserver/ixfr.h +++ b/src/knot/nameserver/ixfr.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -55,9 +55,5 @@ struct ixfr_proc { /*! * \brief IXFR query processing module. - * - * \retval PRODUCE if it has an answer, but not yet finished. - * \retval FAIL if it encountered an error. - * \retval DONE if finished. */ -int ixfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata); +knot_layer_state_t ixfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata); diff --git a/src/knot/nameserver/log.h b/src/knot/nameserver/log.h index 5a5d5f0..373d65a 100644 --- a/src/knot/nameserver/log.h +++ b/src/knot/nameserver/log.h @@ -81,6 +81,8 @@ static inline const char *log_conn_info(knotd_query_proto_t proto, bool pool) return pool ? " TCP/pool" : " TCP"; case KNOTD_QUERY_PROTO_QUIC: return pool ? " QUIC/0-RTT" : " QUIC"; + case KNOTD_QUERY_PROTO_TLS: + return " TLS"; default: return ""; } diff --git a/src/knot/nameserver/notify.c b/src/knot/nameserver/notify.c index eaa305a..5b1593f 100644 --- a/src/knot/nameserver/notify.c +++ b/src/knot/nameserver/notify.c @@ -29,7 +29,7 @@ LOG_DIRECTION_IN, (qdata)->params->remote, (qdata)->params->proto, \ false, (qdata)->sign.tsig_key.name, fmt) -static int notify_check_query(knotd_qdata_t *qdata) +static knot_layer_state_t notify_check_query(knotd_qdata_t *qdata) { NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH); NS_NEED_AUTH(qdata, ACL_ACTION_NOTIFY); @@ -39,14 +39,14 @@ static int notify_check_query(knotd_qdata_t *qdata) return KNOT_STATE_DONE; } -int notify_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) +knot_layer_state_t notify_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) { if (pkt == NULL || qdata == NULL) { return KNOT_STATE_FAIL; } /* Validate notification query. */ - int state = notify_check_query(qdata); + knot_layer_state_t state = notify_check_query(qdata); if (state == KNOT_STATE_FAIL) { switch (qdata->rcode) { case KNOT_RCODE_NOTAUTH: /* Not authorized, already logged. */ diff --git a/src/knot/nameserver/notify.h b/src/knot/nameserver/notify.h index d0bff14..0e60b58 100644 --- a/src/knot/nameserver/notify.h +++ b/src/knot/nameserver/notify.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,8 +21,5 @@ /*! * \brief Answer IN class zone NOTIFY message (RFC1996). - * - * \retval FAIL if it encountered an error. - * \retval DONE if finished. */ -int notify_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata); +knot_layer_state_t notify_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata); diff --git a/src/knot/nameserver/nsec_proofs.c b/src/knot/nameserver/nsec_proofs.c index 71944b1..b67566c 100644 --- a/src/knot/nameserver/nsec_proofs.c +++ b/src/knot/nameserver/nsec_proofs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -121,11 +121,11 @@ static const knot_dname_t *get_next_closer(const knot_dname_t *closest_encloser, size_t ce_labels = knot_dname_labels(closest_encloser, NULL); size_t qname_labels = knot_dname_labels(name, NULL); for (int i = 0; i < (qname_labels - ce_labels - 1); ++i) { - name = knot_wire_next_label(name, NULL); + name = knot_dname_next_label(name); } // the common labels should match - assert(knot_dname_is_equal(knot_wire_next_label(name, NULL), closest_encloser)); + assert(knot_dname_is_equal(knot_dname_next_label(name), closest_encloser)); return name; } diff --git a/src/knot/nameserver/process_query.c b/src/knot/nameserver/process_query.c index 00ec001..beced84 100644 --- a/src/knot/nameserver/process_query.c +++ b/src/knot/nameserver/process_query.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,9 +30,9 @@ #include "knot/nameserver/notify.h" #include "knot/server/server.h" #include "libknot/libknot.h" -#ifdef ENABLE_QUIC -#include "libknot/quic/quic.h" -#endif // ENABLE_QUIC +#include "libknot/quic/quic_conn.h" +#include "libknot/quic/tls_common.h" +#include "libknot/quic/tls.h" #include "contrib/base64.h" #include "contrib/macros.h" #include "contrib/mempattern.h" @@ -147,7 +147,7 @@ static int process_query_in(knot_layer_t *ctx, knot_pkt_t *pkt) /*! * \brief Create a response for a given query in the INTERNET class. */ -static int query_internet(knot_pkt_t *pkt, knot_layer_t *ctx) +static knot_layer_state_t query_internet(knot_pkt_t *pkt, knot_layer_t *ctx) { knotd_qdata_t *data = QUERY_DATA(ctx); @@ -167,7 +167,7 @@ static int query_internet(knot_pkt_t *pkt, knot_layer_t *ctx) /*! * \brief Create a response for a given query in the CHAOS class. */ -static int query_chaos(knot_pkt_t *pkt, knot_layer_t *ctx) +static knot_layer_state_t query_chaos(knot_pkt_t *pkt, knot_layer_t *ctx) { knotd_qdata_t *data = QUERY_DATA(ctx); @@ -203,7 +203,7 @@ static zone_t *answer_zone_find(const knot_pkt_t *query, knot_zonedb_t *zonedb) * records are only present in a parent zone. */ if (qtype == KNOT_RRTYPE_DS) { - const knot_dname_t *parent = knot_wire_next_label(qname, NULL); + const knot_dname_t *parent = knot_dname_next_label(qname); zone = knot_zonedb_find_suffix(zonedb, parent); /* If zone does not exist, search for its parent zone, this will later result to NODATA answer. */ @@ -364,6 +364,7 @@ static int answer_edns_put(knot_pkt_t *resp, knotd_qdata_t *qdata) if (knot_pkt_edns_option(qdata->query, KNOT_EDNS_OPTION_EXPIRE) != NULL && qdata->extra->contents != NULL && !qdata->extra->zone->is_catalog_flag) { int64_t timer = qdata->extra->zone->timers.next_expire; + timer = knot_time_min(timer, qdata->extra->contents->dnssec_expire); // NOOP if zero timer = (timer == 0 ? zone_soa_expire(qdata->extra->zone) : timer - time(NULL)); timer = MAX(timer, 0); uint32_t timer_be; @@ -389,8 +390,8 @@ static int answer_edns_put(knot_pkt_t *resp, knotd_qdata_t *qdata) return ret; } - /* Align the response if QUIC with EDNS. */ - if (qdata->params->proto == KNOTD_QUERY_PROTO_QUIC) { + /* Align the response if QUIC or TLS with EDNS. */ + if (qdata->params->proto == KNOTD_QUERY_PROTO_QUIC || qdata->params->proto == KNOTD_QUERY_PROTO_TLS) { int pad_len = knot_pkt_default_padding_size(resp, &qdata->opt_rr); if (pad_len > -1) { ret = knot_edns_reserve_option(&qdata->opt_rr, KNOT_EDNS_OPTION_PADDING, @@ -506,7 +507,7 @@ static void set_rcode_to_packet(knot_pkt_t *pkt, knotd_qdata_t *qdata) knot_wire_set_rcode(pkt->wire, KNOT_EDNS_RCODE_LO(qdata->rcode)); } -static int process_query_err(knot_layer_t *ctx, knot_pkt_t *pkt) +static knot_layer_state_t process_query_err(knot_layer_t *ctx, knot_pkt_t *pkt) { assert(ctx && pkt); @@ -552,7 +553,8 @@ static int process_query_err(knot_layer_t *ctx, knot_pkt_t *pkt) #define PROCESS_BEGIN(plan, step, next_state, qdata) \ if (plan != NULL) { \ WALK_LIST(step, plan->stage[KNOTD_STAGE_BEGIN]) { \ - next_state = step->process(next_state, pkt, qdata, step->ctx); \ + assert(step->type == QUERY_HOOK_TYPE_GENERAL); \ + next_state = step->general_hook(next_state, pkt, qdata, step->ctx); \ if (next_state == KNOT_STATE_FAIL) { \ goto finish; \ } \ @@ -562,7 +564,8 @@ static int process_query_err(knot_layer_t *ctx, knot_pkt_t *pkt) #define PROCESS_END(plan, step, next_state, qdata) \ if (plan != NULL) { \ WALK_LIST(step, plan->stage[KNOTD_STAGE_END]) { \ - next_state = step->process(next_state, pkt, qdata, step->ctx); \ + assert(step->type == QUERY_HOOK_TYPE_GENERAL); \ + next_state = step->general_hook(next_state, pkt, qdata, step->ctx); \ if (next_state == KNOT_STATE_FAIL) { \ next_state = process_query_err(ctx, pkt); \ } \ @@ -705,43 +708,53 @@ bool process_query_acl_check(conf_t *conf, acl_action_t action, bool automatic = false; bool allowed = false; + struct gnutls_session_int *tls_session; + switch (qdata->params->proto) { + case KNOTD_QUERY_PROTO_QUIC: tls_session = qdata->params->quic_conn->tls_session; break; + case KNOTD_QUERY_PROTO_TLS: tls_session = qdata->params->tls_conn->session; break; + default: tls_session = NULL; + } + if (action != ACL_ACTION_UPDATE) { // ACL_ACTION_QUERY is used for SOA/refresh query. assert(action == ACL_ACTION_QUERY || action == ACL_ACTION_NOTIFY || action == ACL_ACTION_TRANSFER); const yp_name_t *item = (action == ACL_ACTION_NOTIFY) ? C_MASTER : C_NOTIFY; conf_val_t rmts = conf_zone_get(conf, item, zone_name); - allowed = rmt_allowed(conf, &rmts, query_source, &tsig, - qdata->params->quic_conn); + allowed = rmt_allowed(conf, &rmts, query_source, &tsig, tls_session); automatic = allowed; } if (!allowed) { conf_val_t acl = conf_zone_get(conf, C_ACL, zone_name); allowed = acl_allowed(conf, &acl, action, query_source, &tsig, - zone_name, query, qdata->params->quic_conn); + zone_name, query, tls_session); } if (log_enabled_debug()) { int pin_size = 0; -#ifdef ENABLE_QUIC - uint8_t bin_pin[KNOT_QUIC_PIN_LEN], pin[2 * KNOT_QUIC_PIN_LEN]; + uint8_t bin_pin[KNOT_TLS_PIN_LEN], pin[2 * KNOT_TLS_PIN_LEN]; size_t bin_pin_size = sizeof(bin_pin); - knot_quic_conn_pin(qdata->params->quic_conn, bin_pin, &bin_pin_size, false); + knot_tls_pin(tls_session, bin_pin, &bin_pin_size, false); if (bin_pin_size > 0) { pin_size = knot_base64_encode(bin_pin, bin_pin_size, pin, sizeof(pin)); } -#else - uint8_t pin[1]; -#endif // ENABLE_QUIC + + const char *proto_str; + switch (qdata->params->proto) { + case KNOTD_QUERY_PROTO_UDP: proto_str = " UDP"; break; + case KNOTD_QUERY_PROTO_TCP: proto_str = " TCP"; break; + case KNOTD_QUERY_PROTO_QUIC: proto_str = " QUIC"; break; + case KNOTD_QUERY_PROTO_TLS: proto_str = " TLS"; break; + default: proto_str = ""; + } log_zone_debug(zone_name, "ACL, %s, action %s, remote %s%s%s%s%s%.*s%s", allowed ? "allowed" : "denied", (act != NULL) ? act->name : "query", - addr_str, + addr_str, proto_str, (key_name[0] != '\0') ? ", key " : "", (key_name[0] != '\0') ? key_name : "", - (qdata->params->proto == KNOTD_QUERY_PROTO_QUIC) ? ", QUIC" : "", (pin_size > 0) ? " cert-key " : "", (pin_size > 0) ? pin_size : 0, (pin_size > 0) ? (const char *)pin : "", @@ -994,6 +1007,30 @@ int process_query_put_rr(knot_pkt_t *pkt, knotd_qdata_t *qdata, return ret; } +knotd_proto_state_t process_query_proto(knotd_qdata_params_t *params, + const knotd_stage_t stage) +{ + assert(params); + assert(stage == KNOTD_STAGE_PROTO_BEGIN || stage == KNOTD_STAGE_PROTO_END); + + knotd_proto_state_t state = KNOTD_PROTO_STATE_PASS; + + rcu_read_lock(); + + struct query_plan *plan = conf()->query_plan; + if (plan != NULL) { + struct query_step *step; + WALK_LIST(step, plan->stage[stage]) { + assert(step->type == QUERY_HOOK_TYPE_PROTO); + state = step->proto_hook(state, params, step->ctx); + } + } + + rcu_read_unlock(); + + return state; +} + /*! \brief Module implementation. */ const knot_layer_api_t *process_query_layer(void) { diff --git a/src/knot/nameserver/process_query.h b/src/knot/nameserver/process_query.h index 42e66be..c005b58 100644 --- a/src/knot/nameserver/process_query.h +++ b/src/knot/nameserver/process_query.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -106,3 +106,14 @@ int process_query_sign_response(knot_pkt_t *pkt, knotd_qdata_t *qdata); int process_query_put_rr(knot_pkt_t *pkt, knotd_qdata_t *qdata, const knot_rrset_t *rr, const knot_rrset_t *rrsigs, uint16_t compr_hint, uint32_t flags); + +/*! + * \brief Processes all global module protocol callbacks at given stage. + * + * \param params Query processing parameters. + * \param stage Processing stage (KNOTD_STAGE_PROTO_BEGIN or KNOTD_STAGE_PROTO_END). + * + * \return Resulting state. + */ +knotd_proto_state_t process_query_proto(knotd_qdata_params_t *params, + const knotd_stage_t stage); diff --git a/src/knot/nameserver/query_module.c b/src/knot/nameserver/query_module.c index f02ee1b..0708b17 100644 --- a/src/knot/nameserver/query_module.c +++ b/src/knot/nameserver/query_module.c @@ -32,17 +32,6 @@ #include "knot/nameserver/query_module.h" #include "knot/nameserver/process_query.h" -#ifdef HAVE_ATOMIC - #define ATOMIC_ADD(dst, val) __atomic_add_fetch(&(dst), (val), __ATOMIC_RELAXED) - #define ATOMIC_SUB(dst, val) __atomic_sub_fetch(&(dst), (val), __ATOMIC_RELAXED) - #define ATOMIC_SET(dst, val) __atomic_store_n(&(dst), (val), __ATOMIC_RELAXED) -#else - #warning "Statistics data can be inaccurate" - #define ATOMIC_ADD(dst, val) ((dst) += (val)) - #define ATOMIC_SUB(dst, val) ((dst) -= (val)) - #define ATOMIC_SET(dst, val) ((dst) = (val)) -#endif - _public_ int knotd_conf_check_ref(knotd_conf_check_args_t *args) { @@ -79,30 +68,31 @@ void query_plan_free(struct query_plan *plan) free(plan); } -static struct query_step *make_step(query_step_process_f process, void *ctx) +int query_plan_step(struct query_plan *plan, knotd_stage_t stage, + query_hook_type_t type, void *hook, void *ctx) { - struct query_step *step = calloc(1, sizeof(struct query_step)); + struct query_step *step = calloc(1, sizeof(*step)); if (step == NULL) { - return NULL; + return KNOT_ENOMEM; } - step->process = process; + step->type = type; + step->general_hook = hook; step->ctx = ctx; - return step; + add_tail(&plan->stage[stage], &step->node); + + return KNOT_EOK; } -int query_plan_step(struct query_plan *plan, knotd_stage_t stage, - query_step_process_f process, void *ctx) +_public_ +int knotd_mod_proto_hook(knotd_mod_t *mod, knotd_stage_t stage, knotd_mod_proto_hook_f hook) { - struct query_step *step = make_step(process, ctx); - if (step == NULL) { - return KNOT_ENOMEM; + if (stage != KNOTD_STAGE_PROTO_BEGIN && stage != KNOTD_STAGE_PROTO_END) { + return KNOT_EINVAL; } - add_tail(&plan->stage[stage], &step->node); - - return KNOT_EOK; + return query_plan_step(mod->plan, stage, QUERY_HOOK_TYPE_PROTO, hook, mod); } _public_ @@ -112,17 +102,18 @@ int knotd_mod_hook(knotd_mod_t *mod, knotd_stage_t stage, knotd_mod_hook_f hook) return KNOT_EINVAL; } - return query_plan_step(mod->plan, stage, hook, mod); + return query_plan_step(mod->plan, stage, QUERY_HOOK_TYPE_GENERAL, hook, mod); } _public_ int knotd_mod_in_hook(knotd_mod_t *mod, knotd_stage_t stage, knotd_mod_in_hook_f hook) { - if (stage == KNOTD_STAGE_BEGIN || stage == KNOTD_STAGE_END) { + if (stage != KNOTD_STAGE_PREANSWER && stage != KNOTD_STAGE_ANSWER && + stage != KNOTD_STAGE_AUTHORITY && stage != KNOTD_STAGE_ADDITIONAL) { return KNOT_EINVAL; } - return query_plan_step(mod->plan, stage, hook, mod); + return query_plan_step(mod->plan, stage, QUERY_HOOK_TYPE_IN, hook, mod); } knotd_mod_t *query_module_open(conf_t *conf, server_t *server, conf_mod_id_t *mod_id, @@ -313,8 +304,8 @@ int knotd_mod_stats_add(knotd_mod_t *mod, const char *ctr_name, uint32_t idx_cou stats += mod->stats_count; for (unsigned i = 0; i < threads; i++) { - uint64_t *new_vals = realloc(mod->stats_vals[i], - (offset + idx_count) * sizeof(*new_vals)); + knot_atomic_uint64_t *new_vals = realloc(mod->stats_vals[i], + (offset + idx_count) * sizeof(*new_vals)); if (new_vals == NULL) { knotd_mod_stats_free(mod); return KNOT_ENOMEM; @@ -627,6 +618,7 @@ uint32_t knotd_qdata_rtt(knotd_qdata_t *qdata) switch (qdata->params->proto) { case KNOTD_QUERY_PROTO_TCP: + case KNOTD_QUERY_PROTO_TLS: if (qdata->params->xdp_msg != NULL) { #ifdef ENABLE_XDP return qdata->params->measured_rtt; diff --git a/src/knot/nameserver/query_module.h b/src/knot/nameserver/query_module.h index 5cc905b..d403b25 100644 --- a/src/knot/nameserver/query_module.h +++ b/src/knot/nameserver/query_module.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,24 +22,27 @@ #include "knot/dnssec/zone-keys.h" #include "knot/include/module.h" #include "knot/server/server.h" +#include "contrib/atomic.h" #include "contrib/ucw/lists.h" -#ifdef HAVE_ATOMIC - #define ATOMIC_GET(src) __atomic_load_n(&(src), __ATOMIC_RELAXED) -#else - #define ATOMIC_GET(src) (src) -#endif +#define KNOTD_STAGES (KNOTD_STAGE_PROTO_END + 1) -#define KNOTD_STAGES (KNOTD_STAGE_END + 1) +typedef enum { + QUERY_HOOK_TYPE_PROTO, + QUERY_HOOK_TYPE_GENERAL, + QUERY_HOOK_TYPE_IN, +} query_hook_type_t; -typedef unsigned (*query_step_process_f) - (unsigned state, knot_pkt_t *pkt, knotd_qdata_t *qdata, knotd_mod_t *mod); - -/*! \brief Single processing step in query processing. */ +/*! \brief Single processing step in query/module processing. */ struct query_step { node_t node; + query_hook_type_t type; + union { + knotd_mod_proto_hook_f proto_hook; + knotd_mod_hook_f general_hook; + knotd_mod_in_hook_f in_hook; + }; void *ctx; - query_step_process_f process; }; /*! Query plan represents a sequence of steps needed for query processing @@ -58,7 +61,7 @@ void query_plan_free(struct query_plan *plan); /*! \brief Plan another step for given stage. */ int query_plan_step(struct query_plan *plan, knotd_stage_t stage, - query_step_process_f process, void *ctx); + query_hook_type_t type, void *hook, void *ctx); /*! \brief Open query module identified by name. */ knotd_mod_t *query_module_open(conf_t *conf, server_t *server, conf_mod_id_t *mod_id, @@ -91,7 +94,7 @@ struct knotd_mod { zone_keyset_t *keyset; zone_sign_ctx_t *sign_ctx; mod_ctr_t *stats_info; - uint64_t **stats_vals; + knot_atomic_uint64_t **stats_vals; uint32_t stats_count; void *ctx; }; diff --git a/src/knot/nameserver/update.c b/src/knot/nameserver/update.c index 1168c94..ee884fd 100644 --- a/src/knot/nameserver/update.c +++ b/src/knot/nameserver/update.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,12 +22,23 @@ #include "knot/query/requestor.h" #include "contrib/sockaddr.h" #include "libknot/libknot.h" +#include "libknot/quic/quic_conn.h" +#include "libknot/quic/tls.h" static int update_enqueue(zone_t *zone, knotd_qdata_t *qdata) { assert(zone); assert(qdata); + pthread_mutex_lock(&zone->ddns_lock); + if (zone->events.ufrozen && zone->ddns_queue_size >= 8) { + pthread_mutex_unlock(&zone->ddns_lock); + qdata->rcode = KNOT_RCODE_REFUSED; + qdata->rcode_ede = KNOT_EDNS_EDE_NOT_READY; + return KNOT_ELIMIT; + } + pthread_mutex_unlock(&zone->ddns_lock); + /* Create serialized request. */ knot_request_t *req = calloc(1, sizeof(*req)); if (req == NULL) { @@ -63,6 +74,22 @@ static int update_enqueue(zone_t *zone, knotd_qdata_t *qdata) assert(req->sign.tsig_key.algorithm == knot_tsig_rdata_alg(req->query->tsig_rr)); } +#ifdef ENABLE_QUIC + if (qdata->params->quic_conn != NULL) { + req->flags |= KNOT_REQUEST_QUIC; + req->quic_conn = qdata->params->quic_conn; + knot_quic_conn_block(req->quic_conn, true); + assert(qdata->params->quic_stream >= 0); + req->quic_stream = qdata->params->quic_stream; + } else +#endif // ENABLE_QUIC + if (qdata->params->tls_conn != NULL) { + req->flags |= KNOT_REQUEST_TLS; + req->tls_req_ctx.conn = qdata->params->tls_conn; + req->tls_req_ctx.conn->fd_clones_count++; + knot_tls_conn_block(req->tls_req_ctx.conn, true); + } + pthread_mutex_lock(&zone->ddns_lock); /* Enqueue created request. */ @@ -77,10 +104,10 @@ static int update_enqueue(zone_t *zone, knotd_qdata_t *qdata) return KNOT_EOK; } -int update_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) +knot_layer_state_t update_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) { /* DDNS over XDP not supported. */ - if (qdata->params->xdp_msg != NULL || qdata->params->proto == KNOTD_QUERY_PROTO_QUIC) { + if (qdata->params->xdp_msg != NULL) { qdata->rcode = KNOT_RCODE_SERVFAIL; return KNOT_STATE_FAIL; } @@ -95,8 +122,6 @@ int update_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata) NS_NEED_AUTH(qdata, ACL_ACTION_UPDATE); /* Check expiration. */ NS_NEED_ZONE_CONTENTS(qdata); - /* Check frozen zone. */ - NS_NEED_NOT_FROZEN(qdata); /* Store update into DDNS queue. */ int ret = update_enqueue((zone_t *)qdata->extra->zone, qdata); diff --git a/src/knot/nameserver/update.h b/src/knot/nameserver/update.h index 609acd9..430b323 100644 --- a/src/knot/nameserver/update.h +++ b/src/knot/nameserver/update.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,7 +21,5 @@ /*! * \brief UPDATE query processing module. - * - * \return KNOT_STATE_* processing states */ -int update_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata); +knot_layer_state_t update_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata); diff --git a/src/knot/nameserver/xfr.h b/src/knot/nameserver/xfr.h index e6d06b6..fe8a7a8 100644 --- a/src/knot/nameserver/xfr.h +++ b/src/knot/nameserver/xfr.h @@ -38,12 +38,12 @@ static inline void xfr_log_finished(const knot_dname_t *zone, log_operation_t op, log_direction_t dir, const struct sockaddr_storage *remote, knotd_query_proto_t proto, const knot_dname_t *key_name, - const struct xfr_stats *stats) + const char *serial_log, const struct xfr_stats *stats) { ns_log(LOG_INFO, zone, op, dir, remote, proto, false, key_name, - "%sfinished, %0.2f seconds, %u messages, %u bytes", + "%sfinished,%s %0.2f seconds, %u messages, %u bytes", (proto == KNOTD_QUERY_PROTO_QUIC && dir == LOG_DIRECTION_OUT ? "buffering " : ""), - time_diff_ms(&stats->begin, &stats->end) / 1000.0, + serial_log, time_diff_ms(&stats->begin, &stats->end) / 1000.0, stats->messages, stats->bytes); } diff --git a/src/knot/query/quic-requestor.c b/src/knot/query/quic-requestor.c index 62008f9..7492efd 100644 --- a/src/knot/query/quic-requestor.c +++ b/src/knot/query/quic-requestor.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,7 +28,6 @@ #include "knot/conf/conf.h" // please use this only for tiny stuff like quic-log #include "knot/server/handler.h" #include "libknot/error.h" -#include "libknot/quic/quic.h" #define QUIC_BUF_SIZE 4096 @@ -63,6 +62,7 @@ static int quic_exchange(knot_quic_conn_t *conn, knot_quic_reply_t *r, int timeo int64_t quic_timeout_ms = knot_quic_conn_next_timeout(conn); quic_timeout_ms = MIN(quic_timeout_ms, timeout_remain); quic_timeout_ms = MIN(quic_timeout_ms, timeout_ms / 2); + quic_timeout_ms = MAX(quic_timeout_ms, 1); r->in_payload->iov_len = QUIC_BUF_SIZE; @@ -156,7 +156,7 @@ int knot_qreq_connect(struct knot_quic_reply **out, int fd, struct sockaddr_storage *remote, struct sockaddr_storage *local, - const struct knot_quic_creds *local_creds, + const struct knot_creds *local_creds, const uint8_t *peer_pin, uint8_t peer_pin_len, bool *reused_fd, @@ -179,8 +179,7 @@ int knot_qreq_connect(struct knot_quic_reply **out, r->send_reply = qr_send_reply; r->free_reply = qr_free_reply; - struct knot_quic_creds *creds = knot_quic_init_creds_peer(local_creds, - peer_pin, peer_pin_len); + struct knot_creds *creds = knot_creds_init_peer(local_creds, peer_pin, peer_pin_len); if (creds == NULL) { free(r); return KNOT_ENOMEM; @@ -190,7 +189,7 @@ int knot_qreq_connect(struct knot_quic_reply **out, knot_quic_table_t *table = knot_quic_table_new(1, QUIC_BUF_SIZE, QUIC_BUF_SIZE, 0, creds); if (table == NULL) { - knot_quic_free_creds(creds); + knot_creds_free(creds); free(r); return KNOT_ENOMEM; } @@ -294,7 +293,7 @@ void knot_qreq_close(struct knot_quic_reply *r, bool send_close) knot_quic_table_rem(conn, table); knot_quic_cleanup(&conn, 1); if (table != NULL) { - knot_quic_free_creds(table->creds); + knot_creds_free(table->creds); } knot_quic_table_free(table); free(r); diff --git a/src/knot/query/quic-requestor.h b/src/knot/query/quic-requestor.h index b5f479e..083254d 100644 --- a/src/knot/query/quic-requestor.h +++ b/src/knot/query/quic-requestor.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,15 +17,13 @@ #pragma once #include "contrib/sockaddr.h" - -struct knot_quic_creds; -struct knot_quic_reply; +#include "libknot/quic/quic.h" int knot_qreq_connect(struct knot_quic_reply **out, int fd, struct sockaddr_storage *remote, struct sockaddr_storage *local, - const struct knot_quic_creds *local_creds, + const struct knot_creds *local_creds, const uint8_t *peer_pin, uint8_t peer_pin_len, bool *reused_fd, diff --git a/src/knot/query/requestor.c b/src/knot/query/requestor.c index 436f009..125c036 100644 --- a/src/knot/query/requestor.c +++ b/src/knot/query/requestor.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,12 +18,13 @@ #include #include "libknot/attribute.h" +#include "libknot/errcode.h" +#include "libknot/quic/tls.h" #include "knot/common/unreachable.h" #include "knot/query/requestor.h" #ifdef ENABLE_QUIC #include "knot/query/quic-requestor.h" #endif // ENABLE_QUIC -#include "libknot/errcode.h" #include "contrib/conn_pool.h" #include "contrib/mempattern.h" #include "contrib/net.h" @@ -39,6 +40,11 @@ static bool use_quic(knot_request_t *request) return (request->flags & KNOT_REQUEST_QUIC) != 0; } +static bool use_tls(knot_request_t *request) +{ + return (request->flags & KNOT_REQUEST_TLS) != 0; +} + static bool is_answer_to_query(const knot_pkt_t *query, const knot_pkt_t *answer) { return knot_wire_get_id(query->wire) == knot_wire_get_id(answer->wire); @@ -104,6 +110,19 @@ static int request_ensure_connected(knot_request_t *request, bool *reused_fd, in #endif // ENABLE_QUIC } + if (use_tls(request)) { + assert(!use_quic(request)); + + int ret = knot_tls_req_ctx_init(&request->tls_req_ctx, request->fd, + request->creds, request->pin, + request->pin_len, timeout_ms); + if (ret != KNOT_EOK) { + close(request->fd); + request->fd = -1; + return ret; + } + } + return KNOT_EOK; } @@ -124,7 +143,9 @@ static int request_send(knot_request_t *request, int timeout_ms, bool *reused_fd &request->remote : NULL; /* Send query. */ - if (use_quic(request)) { + if (use_tls(request)) { + ret = knot_tls_send_dns(request->tls_req_ctx.conn, wire, wire_len); + } else if (use_quic(request)) { #ifdef ENABLE_QUIC struct iovec tosend = { wire, wire_len }; return knot_qreq_send(request->quic_ctx, &tosend); @@ -162,7 +183,9 @@ static int request_recv(knot_request_t *request, int timeout_ms) } /* Receive it */ - if (use_quic(request)) { + if (use_tls(request)) { + ret = knot_tls_recv_dns(request->tls_req_ctx.conn, resp->wire, resp->max_size); + } else if (use_quic(request)) { #ifdef ENABLE_QUIC struct iovec recvd = { resp->wire, resp->max_size }; ret = knot_qreq_recv(request->quic_ctx, &recvd, timeout_ms); @@ -192,7 +215,7 @@ knot_request_t *knot_request_make_generic(knot_mm_t *mm, const struct sockaddr_storage *remote, const struct sockaddr_storage *source, knot_pkt_t *query, - const struct knot_quic_creds *creds, + const struct knot_creds *creds, const query_edns_data_t *edns, const knot_tsig_key_t *tsig_key, const uint8_t *pin, @@ -232,7 +255,7 @@ knot_request_t *knot_request_make_generic(knot_mm_t *mm, request->edns = edns; request->creds = creds; - if (flags & KNOT_REQUEST_QUIC && pin_len > 0) { + if ((flags & (KNOT_REQUEST_QUIC | KNOT_REQUEST_TLS)) && pin_len > 0) { request->pin_len = pin_len; memcpy(request->pin, pin, pin_len); } @@ -243,12 +266,15 @@ knot_request_t *knot_request_make_generic(knot_mm_t *mm, knot_request_t *knot_request_make(knot_mm_t *mm, const conf_remote_t *remote, knot_pkt_t *query, - const struct knot_quic_creds *creds, + const struct knot_creds *creds, const query_edns_data_t *edns, knot_request_flag_t flags) { if (remote->quic) { + assert(!remote->tls); flags |= KNOT_REQUEST_QUIC; + } else if (remote->tls) { + flags |= KNOT_REQUEST_TLS; } return knot_request_make_generic(mm, &remote->addr, &remote->via, @@ -262,15 +288,25 @@ void knot_request_free(knot_request_t *request, knot_mm_t *mm) return; } - if (request->quic_ctx != NULL) { + if (use_quic(request)) { #ifdef ENABLE_QUIC - knot_qreq_close(request->quic_ctx, true); + if (request->quic_ctx != NULL) { + knot_qreq_close(request->quic_ctx, true); + } + // NOTE synthetic DDNSoQ request is NOOP here #else assert(0); #endif // ENABLE_QUIC + } else if (use_tls(request) && request->tls_req_ctx.conn != NULL) { + knot_tls_req_ctx_deinit(&request->tls_req_ctx); + } else { + assert(request->quic_ctx == NULL); + assert(request->quic_conn == NULL); + assert(request->tls_req_ctx.ctx == NULL); + assert(request->tls_req_ctx.conn == NULL); } - if (request->fd >= 0 && use_tcp(request) && + if (request->fd >= 0 && use_tcp(request) && !use_tls(request) && (request->flags & KNOT_REQUEST_KEEP)) { request->fd = (int)conn_pool_put(global_conn_pool, &request->source, @@ -282,6 +318,7 @@ void knot_request_free(knot_request_t *request, knot_mm_t *mm) } knot_pkt_free(request->query); knot_pkt_free(request->resp); + dnssec_binary_free(&request->sign.tsig_key.secret); tsig_cleanup(&request->tsig); mm_free(mm, request); @@ -351,7 +388,7 @@ static int request_produce(knot_requestor_t *req, knot_request_t *last, if (last->edns != NULL && !last->edns->no_edns) { ret = query_put_edns(last->query, last->edns, - (last->flags & KNOT_REQUEST_QUIC)); + (last->flags & (KNOT_REQUEST_QUIC | KNOT_REQUEST_TLS))); if (ret != KNOT_EOK) { return ret; } @@ -376,6 +413,9 @@ static int request_produce(knot_requestor_t *req, knot_request_t *last, if (last->flags & KNOT_REQUEST_QUIC) { req->layer.flags |= KNOT_REQUESTOR_QUIC; } + if (last->flags & KNOT_REQUEST_TLS) { + req->layer.flags |= KNOT_REQUESTOR_TLS; + } } return ret; diff --git a/src/knot/query/requestor.h b/src/knot/query/requestor.h index 65da1ed..241be04 100644 --- a/src/knot/query/requestor.h +++ b/src/knot/query/requestor.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,26 +23,26 @@ #include "knot/nameserver/tsig_ctx.h" #include "knot/query/layer.h" #include "knot/query/query.h" +#include "knot/query/tls-requestor.h" #include "libknot/mm_ctx.h" #include "libknot/rrtype/tsig.h" -struct knot_quic_creds; -struct knot_quic_reply; - typedef enum { KNOT_REQUEST_NONE = 0, /*!< Empty flag. */ KNOT_REQUEST_UDP = 1 << 0, /*!< Use UDP for requests. */ KNOT_REQUEST_TFO = 1 << 1, /*!< Enable TCP Fast Open for requests. */ KNOT_REQUEST_KEEP = 1 << 2, /*!< Keep upstream TCP connection in pool for later reuse. */ KNOT_REQUEST_QUIC = 1 << 3, /*!< Use QUIC/UDP for requests. */ - KNOT_REQUEST_FWD = 1 << 4, /*!< Forwarded message, don't modify (TSIG, PADDING). */ + KNOT_REQUEST_TLS = 1 << 4, /*!< Use DoT for requests. */ + KNOT_REQUEST_FWD = 1 << 5, /*!< Forwarded message, don't modify (TSIG, PADDING). */ } knot_request_flag_t; typedef enum { KNOT_REQUESTOR_CLOSE = 1 << 0, /*!< Close the connection indication. */ KNOT_REQUESTOR_REUSED = 1 << 1, /*!< Reused FD indication (RO). */ KNOT_REQUESTOR_QUIC = 1 << 2, /*!< QUIC used indication (RO). */ - KNOT_REQUESTOR_IOFAIL = 1 << 3, /*!< Encountered error sending/recving data. */ + KNOT_REQUESTOR_TLS = 1 << 3, /*!< DoT used indication (RO). */ + KNOT_REQUESTOR_IOFAIL = 1 << 4, /*!< Encountered error sending/recving data. */ } knot_requestor_flag_t; /*! \brief Requestor structure. @@ -57,7 +57,14 @@ typedef struct { /*! \brief Request data (socket, payload, response, TSIG and endpoints). */ typedef struct { int fd; - struct knot_quic_reply *quic_ctx; + union { + struct { + struct knot_quic_reply *quic_ctx; + struct knot_quic_conn *quic_conn; + int64_t quic_stream; + }; + knot_tls_req_ctx_t tls_req_ctx; + }; knot_request_flag_t flags; struct sockaddr_storage remote, source; knot_pkt_t *query; @@ -67,11 +74,22 @@ typedef struct { knot_sign_context_t sign; /*!< Required for async. DDNS processing. */ - const struct knot_quic_creds *creds; + const struct knot_creds *creds; size_t pin_len; uint8_t pin[]; } knot_request_t; +static inline knotd_query_proto_t flags2proto(unsigned layer_flags) +{ + knotd_query_proto_t proto = KNOTD_QUERY_PROTO_TCP; + if ((layer_flags & KNOT_REQUESTOR_QUIC)) { + proto = KNOTD_QUERY_PROTO_QUIC; + } else if ((layer_flags & KNOT_REQUESTOR_TLS)) { + proto = KNOTD_QUERY_PROTO_TLS; + } + return proto; +} + /*! * \brief Make request out of endpoints and query. * @@ -92,7 +110,7 @@ knot_request_t *knot_request_make_generic(knot_mm_t *mm, const struct sockaddr_storage *remote, const struct sockaddr_storage *source, knot_pkt_t *query, - const struct knot_quic_creds *creds, + const struct knot_creds *creds, const query_edns_data_t *edns, const knot_tsig_key_t *tsig_key, const uint8_t *pin, @@ -108,7 +126,7 @@ knot_request_t *knot_request_make_generic(knot_mm_t *mm, knot_request_t *knot_request_make(knot_mm_t *mm, const conf_remote_t *remote, knot_pkt_t *query, - const struct knot_quic_creds *creds, + const struct knot_creds *creds, const query_edns_data_t *edns, knot_request_flag_t flags); diff --git a/src/knot/query/tls-requestor.c b/src/knot/query/tls-requestor.c new file mode 100644 index 0000000..e1a2e8e --- /dev/null +++ b/src/knot/query/tls-requestor.c @@ -0,0 +1,59 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include + +#include "knot/query/tls-requestor.h" +#include "libknot/error.h" +#include "libknot/quic/tls.h" + +int knot_tls_req_ctx_init(knot_tls_req_ctx_t *ctx, int fd, + const struct knot_creds *local_creds, + const uint8_t *peer_pin, uint8_t peer_pin_len, + int io_timeout_ms) +{ + struct knot_creds *creds = knot_creds_init_peer(local_creds, peer_pin, peer_pin_len); + if (creds == NULL) { + return KNOT_ENOMEM; + } + + // Use HS = 4x IO timeout, as the RMT IO timeout is usually high. + ctx->ctx = knot_tls_ctx_new(creds, io_timeout_ms, 4 * io_timeout_ms, false); + if (ctx->ctx == NULL) { + knot_creds_free(creds); + return KNOT_ENOMEM; + } + + ctx->conn = knot_tls_conn_new(ctx->ctx, fd); + if (ctx->conn == NULL) { + knot_tls_req_ctx_deinit(ctx); + return KNOT_ERROR; + } + + return KNOT_EOK; +} + +void knot_tls_req_ctx_deinit(knot_tls_req_ctx_t *ctx) +{ + if (ctx != NULL) { + if (ctx->ctx != NULL) { + knot_creds_free(ctx->ctx->creds); + } + knot_tls_conn_del(ctx->conn); + knot_tls_ctx_free(ctx->ctx); + memset(ctx, 0, sizeof(*ctx)); + } +} diff --git a/src/knot/query/tls-requestor.h b/src/knot/query/tls-requestor.h new file mode 100644 index 0000000..535bbe8 --- /dev/null +++ b/src/knot/query/tls-requestor.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#pragma once + +#include + +#include "libknot/quic/tls_common.h" + +/*! + * \brief TLS requestor context envelope, containing TLS general context and TLS connection. + */ +typedef struct knot_tls_req_ctx { + struct knot_tls_ctx *ctx; + struct knot_tls_conn *conn; +} knot_tls_req_ctx_t; + +/*! + * \brief Initialize TLS requestor context. + * + * \param ctx Context structure to be initialized. + * \param fd Opened TCP connection file descriptor. + * \param local_creds Local TLS credentials. + * \param peer_pin TLS peer pin. + * \param peer_pin_len TLS peer pin length. + * \param io_timeout_ms Configured io-timeout for TLS connection. + * + * \return KNOT_E* + */ +int knot_tls_req_ctx_init(knot_tls_req_ctx_t *ctx, int fd, + const struct knot_creds *local_creds, + const uint8_t *peer_pin, uint8_t peer_pin_len, + int io_timeout_ms); + +/*! + * \brief De-initialize TLS requestor context. + */ +void knot_tls_req_ctx_deinit(knot_tls_req_ctx_t *ctx); diff --git a/src/knot/server/handler.c b/src/knot/server/handler.c index ec7377a..bcd0ec5 100644 --- a/src/knot/server/handler.c +++ b/src/knot/server/handler.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -97,7 +97,7 @@ static void handle_quic_stream(knot_quic_conn_t *conn, int64_t stream_id, struct } void handle_quic_streams(knot_quic_conn_t *conn, knotd_qdata_params_t *params, - knot_layer_t *layer, void *msg) + knot_layer_t *layer) { uint8_t ans_buf[KNOT_WIRE_MAX_PKTSIZE]; @@ -108,14 +108,7 @@ void handle_quic_streams(knot_quic_conn_t *conn, knotd_qdata_params_t *params, assert(stream->inbufs != NULL); assert(stream->inbufs->n_inbufs > 0); struct iovec *inbufs = stream->inbufs->inbufs; - if (msg) { -#ifdef ENABLE_XDP - params_xdp_update(params, KNOTD_QUERY_PROTO_QUIC, msg, - knot_quic_conn_rtt(conn), conn); -#endif // ENABLE_XDP - } else { - params_update(params, knot_quic_conn_rtt(conn), conn); - } + params_update_quic(params, knot_quic_conn_rtt(conn), conn, stream_id); // NOTE: only the first msg in the stream is used, the rest is dropped. handle_quic_stream(conn, stream_id, &inbufs[0], layer, params, ans_buf, sizeof(ans_buf)); diff --git a/src/knot/server/handler.h b/src/knot/server/handler.h index 0f29988..4b63a0c 100644 --- a/src/knot/server/handler.h +++ b/src/knot/server/handler.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include "knot/query/layer.h" #include "knot/server/server.h" #include "libknot/xdp/tcp_iobuf.h" +#include "libknot/quic/tls.h" #ifdef ENABLE_QUIC #include "libknot/quic/quic.h" @@ -44,18 +45,33 @@ inline static knotd_qdata_params_t params_init(knotd_query_proto_t proto, .remote = (const struct sockaddr_storage *)remote, .local = (const struct sockaddr_storage *)local, .socket = sock, + .thread_id = thread_id, .server = server, - .thread_id = thread_id + .quic_stream = -1, }; return params; } -inline static void params_update(knotd_qdata_params_t *params, uint32_t rtt, - struct knot_quic_conn *conn) +inline static void params_update_tcp(knotd_qdata_params_t *params, uint32_t rtt) { params->measured_rtt = rtt; +} + +#ifdef ENABLE_QUIC +inline static void params_update_quic(knotd_qdata_params_t *params, uint32_t rtt, + knot_quic_conn_t *conn, int64_t stream_id) +{ params->quic_conn = conn; + params->quic_stream = stream_id; + params->measured_rtt = rtt; +} +#endif // ENABLE_QUIC + +inline static void params_update_tls(knotd_qdata_params_t *params, + knot_tls_conn_t *conn) +{ + params->tls_conn = conn; } #ifdef ENABLE_XDP @@ -64,8 +80,9 @@ inline static knotd_qdata_params_t params_xdp_init(int sock, server_t *server, { knotd_qdata_params_t params = { .socket = sock, + .thread_id = thread_id, .server = server, - .thread_id = thread_id + .quic_stream = -1, }; return params; @@ -73,16 +90,12 @@ inline static knotd_qdata_params_t params_xdp_init(int sock, server_t *server, inline static void params_xdp_update(knotd_qdata_params_t *params, knotd_query_proto_t proto, - struct knot_xdp_msg *msg, - uint32_t rtt, - struct knot_quic_conn *conn) + struct knot_xdp_msg *msg) { params->proto = proto; params->remote = (struct sockaddr_storage *)&msg->ip_from; params->local = (struct sockaddr_storage *)&msg->ip_to; params->xdp_msg = msg; - params->measured_rtt = rtt; - params->quic_conn = conn; } #endif // ENABLE_XDP @@ -107,7 +120,7 @@ void handle_udp_reply(knotd_qdata_params_t *params, knot_layer_t *layer, #ifdef ENABLE_QUIC void handle_quic_streams(knot_quic_conn_t *conn, knotd_qdata_params_t *params, - knot_layer_t *layer, void *msg); + knot_layer_t *layer); #endif // ENABLE_QUIC void log_swept(knot_sweep_stats_t *stats, bool tcp); diff --git a/src/knot/server/quic-handler.c b/src/knot/server/quic-handler.c index 5010213..663167e 100644 --- a/src/knot/server/quic-handler.c +++ b/src/knot/server/quic-handler.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include "contrib/macros.h" #include "contrib/net.h" #include "knot/common/log.h" +#include "knot/nameserver/process_query.h" #include "knot/server/handler.h" #include "knot/server/quic-handler.h" #include "knot/server/server.h" @@ -92,16 +93,22 @@ void quic_handler(knotd_qdata_params_t *params, knot_layer_t *layer, rpl.out_payload->iov_len = 0; // prevent send attempt if uq_alloc_reply is not called at all + if (process_query_proto(params, KNOTD_STAGE_PROTO_BEGIN) == KNOTD_PROTO_STATE_BLOCK) { + return; + } + knot_quic_conn_t *conn = NULL; (void)knot_quic_handle(table, &rpl, idle_close, &conn); if (conn != NULL) { - handle_quic_streams(conn, params, layer, NULL); + handle_quic_streams(conn, params, layer); (void)knot_quic_send(table, conn, &rpl, QUIC_MAX_SEND_PER_RECV, 0); knot_quic_cleanup(&conn, 1); } + + (void)process_query_proto(params, KNOTD_STAGE_PROTO_END); } knot_quic_table_t *quic_make_table(struct server *server) diff --git a/src/knot/server/server.c b/src/knot/server/server.c index dd0b025..0626337 100644 --- a/src/knot/server/server.c +++ b/src/knot/server/server.c @@ -27,8 +27,9 @@ #include "libknot/libknot.h" #include "libknot/yparser/ypschema.h" #include "libknot/xdp.h" +#include "libknot/quic/tls_common.h" #ifdef ENABLE_QUIC -#include "libknot/quic/quic.h" +#include "libknot/quic/quic.h" // knot_quic_session_* #endif // ENABLE_QUIC #include "knot/common/log.h" #include "knot/common/stats.h" @@ -65,6 +66,8 @@ #define SESSION_TICKET_POOL_TIMEOUT (24 * 3600) +#define QUIC_LOG "QUIC/TLS, " + /*! \brief Minimal send/receive buffer sizes. */ enum { UDP_MIN_RCVSIZE = 4096, @@ -236,14 +239,14 @@ static int disable_pmtudisc(int sock, int family) return KNOT_EOK; } -static size_t quic_rmt_count(conf_t *conf) +static size_t quic_rmt_count(conf_t *conf, const yp_name_t *proto) { size_t count = 0; for (conf_iter_t iter = conf_iter(conf, C_RMT); iter.code == KNOT_EOK; conf_iter_next(conf, &iter)) { conf_val_t id = conf_iter_id(conf, &iter); - conf_val_t rmt_quic = conf_id_get(conf, C_RMT, C_QUIC, &id); + conf_val_t rmt_quic = conf_id_get(conf, C_RMT, proto, &id); if (conf_bool(&rmt_quic)) { count++; } @@ -252,14 +255,11 @@ static size_t quic_rmt_count(conf_t *conf) return count; } +#ifdef ENABLE_XDP static iface_t *server_init_xdp_iface(struct sockaddr_storage *addr, bool route_check, bool udp, bool tcp, uint16_t quic, unsigned *thread_id_start, - bool extra_frames) + const knot_xdp_config_t *xdp_config) { -#ifndef ENABLE_XDP - assert(0); - return NULL; -#else conf_xdp_iface_t iface; int ret = conf_xdp_iface(addr, &iface); if (ret != KNOT_EOK) { @@ -296,18 +296,17 @@ static iface_t *server_init_xdp_iface(struct sockaddr_storage *addr, bool route_ xdp_flags |= KNOT_XDP_FILTER_ROUTE; } - knot_xdp_config_t xdp_config = { .extra_frames = extra_frames }; for (int i = 0; i < iface.queues; i++) { knot_xdp_load_bpf_t mode = (i == 0 ? KNOT_XDP_LOAD_BPF_ALWAYS : KNOT_XDP_LOAD_BPF_NEVER); ret = knot_xdp_init(new_if->xdp_sockets + i, iface.name, i, - xdp_flags, iface.port, quic, mode, &xdp_config); + xdp_flags, iface.port, quic, mode, xdp_config); if (ret == -EBUSY && i == 0) { log_notice("XDP interface %s@%u is busy, retrying initialization", iface.name, iface.port); ret = knot_xdp_init(new_if->xdp_sockets + i, iface.name, i, xdp_flags, iface.port, quic, - KNOT_XDP_LOAD_BPF_ALWAYS_UNLOAD, &xdp_config); + KNOT_XDP_LOAD_BPF_ALWAYS_UNLOAD, xdp_config); } if (ret != KNOT_EOK) { log_warning("failed to initialize XDP interface %s@%u, queue %d (%s)", @@ -345,8 +344,8 @@ static iface_t *server_init_xdp_iface(struct sockaddr_storage *addr, bool route_ } return new_if; -#endif } +#endif /*! * \brief Create and initialize new interface. @@ -363,7 +362,7 @@ static iface_t *server_init_xdp_iface(struct sockaddr_storage *addr, bool route_ * \retval Pointer to a new initialized interface. * \retval NULL if error. */ -static iface_t *server_init_iface(struct sockaddr_storage *addr, bool quic, +static iface_t *server_init_iface(struct sockaddr_storage *addr, bool tls, int udp_thread_count, int tcp_thread_count, bool tcp_reuseport, bool socket_affinity) { @@ -380,14 +379,14 @@ static iface_t *server_init_iface(struct sockaddr_storage *addr, bool quic, int udp_socket_count = 1; int udp_bind_flags = 0; - int tcp_socket_count = !quic ? 1 : 0; + int tcp_socket_count = tcp_thread_count > 0 ? 1 : 0; int tcp_bind_flags = 0; #ifdef ENABLE_REUSEPORT udp_socket_count = udp_thread_count; udp_bind_flags |= NET_BIND_MULTIPLE; - if (!quic && tcp_reuseport) { + if (tcp_reuseport) { tcp_socket_count = tcp_thread_count; tcp_bind_flags |= NET_BIND_MULTIPLE; } @@ -459,7 +458,7 @@ static iface_t *server_init_iface(struct sockaddr_storage *addr, bool quic, warn_flag_misc = false; } - if (quic) { + if (tls) { ret = net_cmsg_ecn_enable(sock, addr->ss_family); if (ret != KNOT_EOK && ret != KNOT_ENOTSUP && warn_ecn) { log_warning("failed to enable ECN for QUIC"); @@ -561,7 +560,6 @@ static void log_sock_conf(conf_t *conf) } } -#ifdef ENABLE_QUIC static int check_file(char *path, char *role) { if (path == NULL) { @@ -576,29 +574,29 @@ static int check_file(char *path, char *role) err_str = "invalid file"; } else if (!S_ISREG(st.st_mode)) { err_str = "not a file"; + } else if ((st.st_mode & S_IRUSR) == 0) { + err_str = "not readable"; } else { return KNOT_EOK; } - log_error("QUIC, %s file '%s' (%s)", role, path, err_str); + log_error(QUIC_LOG "%s file '%s' (%s)", role, path, err_str); return KNOT_EINVAL; } -#endif // ENABLE_QUIC -static int init_creds(server_t *server, conf_t *conf) +static int init_creds(conf_t *conf, server_t *server) { -#ifdef ENABLE_QUIC char *cert_file = conf_tls(conf, C_CERT_FILE); char *key_file = conf_tls(conf, C_KEY_FILE); int ret = check_file(cert_file, "certificate"); if (ret != KNOT_EOK) { - return ret; + goto failed; } ret = check_file(key_file, "key"); if (ret != KNOT_EOK) { - return ret; + goto failed; } if (cert_file == NULL) { @@ -606,35 +604,45 @@ static int init_creds(server_t *server, conf_t *conf) char *kasp_dir = conf_db(conf, C_KASP_DB); ret = make_dir(kasp_dir, S_IRWXU | S_IRWXG, true); if (ret != KNOT_EOK) { - log_error("QUIC, failed to create directory '%s'", kasp_dir); + log_error(QUIC_LOG "failed to create directory '%s'", kasp_dir); free(kasp_dir); - return ret; + goto failed; } key_file = abs_path(DFLT_QUIC_KEY_FILE, kasp_dir); free(kasp_dir); - log_debug("QUIC, using self-generated key '%s' with " + log_debug(QUIC_LOG "using self-generated key '%s' with " "one-time certificate", key_file); } - server->quic_creds = knot_quic_init_creds(cert_file, key_file); - free(cert_file); + + uint8_t prev_pin[128]; + size_t prev_pin_len = server_cert_pin(server, prev_pin, sizeof(prev_pin)); + if (server->quic_creds == NULL) { - log_error("QUIC, failed to initialize server credentials with key '%s'", - key_file); - free(key_file); - return KNOT_ERROR; + server->quic_creds = knot_creds_init(key_file, cert_file); + if (server->quic_creds == NULL) { + log_error(QUIC_LOG "failed to initialize server credentials"); + ret = KNOT_ERROR; + goto failed; + } + } else { + ret = knot_creds_update(server->quic_creds, key_file, cert_file); + if (ret != KNOT_EOK) { + goto failed; + } } - free(key_file); - size_t pin_len; uint8_t pin[128]; - if ((pin_len = server_cert_pin(server, pin, sizeof(pin))) > 0) { - log_info("QUIC, certificate public key %.*s", (int)pin_len, pin); + size_t pin_len = server_cert_pin(server, pin, sizeof(pin)); + if (pin_len > 0 && (pin_len != prev_pin_len || memcmp(pin, prev_pin, pin_len) != 0)) { + log_info(QUIC_LOG "certificate public key %.*s", (int)pin_len, pin); } - return KNOT_EOK; -#else - return KNOT_ERROR; -#endif // ENABLE_QUIC + ret = KNOT_EOK; +failed: + free(key_file); + free(cert_file); + + return ret; } /*! \brief Initialize bound sockets according to configuration. */ @@ -646,11 +654,13 @@ static int configure_sockets(conf_t *conf, server_t *s) conf_val_t listen_val = conf_get(conf, C_SRV, C_LISTEN); conf_val_t liquic_val = conf_get(conf, C_SRV, C_LISTEN_QUIC); + conf_val_t listls_val = conf_get(conf, C_SRV, C_LISTEN_TLS); conf_val_t lisxdp_val = conf_get(conf, C_XDP, C_LISTEN); conf_val_t rundir_val = conf_get(conf, C_SRV, C_RUNDIR); uint16_t convent_quic = conf_val_count(&liquic_val); + uint16_t convent_tls = conf_val_count(&listls_val); - if (listen_val.code == KNOT_EOK || liquic_val.code == KNOT_EOK) { + if (listen_val.code == KNOT_EOK || liquic_val.code == KNOT_EOK || listls_val.code == KNOT_EOK) { log_sock_conf(conf); } else if (lisxdp_val.code != KNOT_EOK) { log_warning("no network interface configured"); @@ -676,7 +686,7 @@ static int configure_sockets(conf_t *conf, server_t *s) size_t real_nifs = 0; size_t nifs = conf_val_count(&listen_val) + conf_val_count(&liquic_val) + - conf_val_count(&lisxdp_val); + conf_val_count(&listls_val) + conf_val_count(&lisxdp_val); iface_t *newlist = calloc(nifs, sizeof(*newlist)); if (newlist == NULL) { log_error("failed to allocate memory for network sockets"); @@ -720,32 +730,52 @@ static int configure_sockets(conf_t *conf, server_t *s) free(rundir); return KNOT_ERROR; } - new_if->quic = true; + new_if->tls = true; memcpy(&newlist[real_nifs++], new_if, sizeof(*newlist)); free(new_if); conf_val_next(&liquic_val); } + while (listls_val.code == KNOT_EOK) { + struct sockaddr_storage addr = conf_addr(&listls_val, rundir); + char addr_str[SOCKADDR_STRLEN] = { 0 }; + sockaddr_tostr(addr_str, sizeof(addr_str), &addr); + log_info("binding to TLS interface %s", addr_str); + + iface_t *new_if = server_init_iface(&addr, true, 0, size_tcp, + tcp_reuseport, socket_affinity); + if (new_if == NULL) { + server_deinit_iface_list(newlist, nifs); + free(rundir); + return KNOT_ERROR; + } + new_if->tls = true; + memcpy(&newlist[real_nifs++], new_if, sizeof(*newlist)); + free(new_if); + + conf_val_next(&listls_val); + } free(rundir); /* XDP sockets. */ - bool xdp_udp = conf->cache.xdp_udp; - bool xdp_tcp = conf->cache.xdp_tcp; - uint16_t xdp_quic = conf->cache.xdp_quic; - bool route_check = conf->cache.xdp_route_check; +#ifdef ENABLE_XDP + knot_xdp_config_t xdp_config = { + .ring_size = conf->cache.xdp_ring_size, + .busy_poll_budget = conf->cache.xdp_busypoll_budget, + .busy_poll_timeout = conf->cache.xdp_busypoll_timeout, + }; unsigned thread_id = s->handlers[IO_UDP].handler.unit->size + s->handlers[IO_TCP].handler.unit->size; - conf_val_t extra_frames_val = conf_get(conf, C_XDP, C_EXTRA_FRAMES); - bool extra_frames = conf_bool(&extra_frames_val); while (lisxdp_val.code == KNOT_EOK) { struct sockaddr_storage addr = conf_addr(&lisxdp_val, NULL); char addr_str[SOCKADDR_STRLEN] = { 0 }; sockaddr_tostr(addr_str, sizeof(addr_str), &addr); log_info("binding to XDP interface %s", addr_str); - iface_t *new_if = server_init_xdp_iface(&addr, route_check, xdp_udp, - xdp_tcp, xdp_quic, &thread_id, - extra_frames); + iface_t *new_if = server_init_xdp_iface(&addr, conf->cache.xdp_route_check, + conf->cache.xdp_udp, conf->cache.xdp_tcp, + conf->cache.xdp_quic, &thread_id, + &xdp_config); if (new_if == NULL) { server_deinit_iface_list(newlist, nifs); return KNOT_ERROR; @@ -755,13 +785,16 @@ static int configure_sockets(conf_t *conf, server_t *s) conf_val_next(&lisxdp_val); } +#endif + assert(real_nifs <= nifs); nifs = real_nifs; /* QUIC credentials initialization. */ - s->quic_active = xdp_quic > 0 || convent_quic > 0 || quic_rmt_count(conf) > 0; - if (s->quic_active) { - if (init_creds(s, conf) != KNOT_EOK) { + s->quic_active = conf->cache.xdp_quic > 0 || convent_quic > 0 || quic_rmt_count(conf, C_QUIC) > 0; + s->tls_active = convent_tls > 0 || quic_rmt_count(conf, C_TLS) > 0; + if (s->quic_active || s->tls_active) { + if (init_creds(conf, s) != KNOT_EOK) { server_deinit_iface_list(newlist, nifs); return KNOT_ERROR; } @@ -810,6 +843,8 @@ int server_init(server_t *server, int bg_workers) return ret; } + pthread_rwlock_init(&server->ctl_lock, NULL); + zone_backups_init(&server->backup_ctxs); char *catalog_dir = conf_db(conf(), C_CATALOG_DB); @@ -864,6 +899,9 @@ void server_deinit(server_t *server) /* Free remaining events. */ evsched_deinit(&server->sched); + /* Deinit locks. */ + pthread_rwlock_destroy(&server->ctl_lock); + /* Free catalog zone context. */ catalog_update_clear(&server->catalog_upd); catalog_update_deinit(&server->catalog_upd); @@ -885,9 +923,7 @@ void server_deinit(server_t *server) global_sessticket_pool = NULL; knot_unreachables_deinit(&global_unreachables); -#if defined ENABLE_QUIC - knot_quic_free_creds(server->quic_creds); -#endif // ENABLE_QUIC + knot_creds_free(server->quic_creds); } static int server_init_handler(server_t *server, int index, int thread_count, @@ -1058,9 +1094,10 @@ static bool listen_changed(conf_t *conf, server_t *server) conf_val_t listen_val = conf_get(conf, C_SRV, C_LISTEN); conf_val_t liquic_val = conf_get(conf, C_SRV, C_LISTEN_QUIC); + conf_val_t listls_val = conf_get(conf, C_SRV, C_LISTEN_TLS); conf_val_t lisxdp_val = conf_get(conf, C_XDP, C_LISTEN); size_t new_count = conf_val_count(&listen_val) + conf_val_count(&liquic_val) + - conf_val_count(&lisxdp_val); + conf_val_count(&listls_val) + conf_val_count(&lisxdp_val); size_t old_count = server->n_ifaces; if (new_count != old_count) { return true; @@ -1075,7 +1112,9 @@ static bool listen_changed(conf_t *conf, server_t *server) struct sockaddr_storage addr = conf_addr(&listen_val, rundir); bool found = false; for (size_t i = 0; i < server->n_ifaces; i++) { - if (sockaddr_cmp(&addr, &server->ifaces[i].addr, false) == 0) { + iface_t *iface = &server->ifaces[i]; + if (sockaddr_cmp(&addr, &iface->addr, false) == 0 && + !iface->tls && iface->fd_xdp_count == 0) { matches++; found = true; break; @@ -1090,7 +1129,9 @@ static bool listen_changed(conf_t *conf, server_t *server) struct sockaddr_storage addr = conf_addr(&liquic_val, rundir); bool found = false; for (size_t i = 0; i < server->n_ifaces; i++) { - if (sockaddr_cmp(&addr, &server->ifaces[i].addr, false) == 0) { + iface_t *iface = &server->ifaces[i]; + if (sockaddr_cmp(&addr, &iface->addr, false) == 0 && + iface->tls && iface->fd_udp_count > 0) { matches++; found = true; break; @@ -1101,13 +1142,32 @@ static bool listen_changed(conf_t *conf, server_t *server) } conf_val_next(&liquic_val); } + while (listls_val.code == KNOT_EOK) { + struct sockaddr_storage addr = conf_addr(&listls_val, rundir); + bool found = false; + for (size_t i = 0; i < server->n_ifaces; i++) { + iface_t *iface = &server->ifaces[i]; + if (sockaddr_cmp(&addr, &iface->addr, false) == 0 && + iface->tls && iface->fd_tcp_count > 0) { + matches++; + found = true; + break; + } + } + if (!found) { + break; + } + conf_val_next(&listls_val); + } free(rundir); while (lisxdp_val.code == KNOT_EOK) { struct sockaddr_storage addr = conf_addr(&lisxdp_val, NULL); bool found = false; for (size_t i = 0; i < server->n_ifaces; i++) { - if (sockaddr_cmp(&addr, &server->ifaces[i].addr, false) == 0) { + iface_t *iface = &server->ifaces[i]; + if (sockaddr_cmp(&addr, &iface->addr, false) == 0 && + iface->fd_xdp_count > 0) { matches++; found = true; break; @@ -1137,6 +1197,9 @@ static void warn_server_reconfigure(conf_t *conf, server_t *server) static bool warn_xdp_tcp = true; static bool warn_xdp_quic = true; static bool warn_route_check = true; + static bool warn_ring_size = true; + static bool warn_busypoll_budget = true; + static bool warn_busypoll_timeout = true; static bool warn_rmt_pool_limit = true; if (warn_tcp_reuseport && conf->cache.srv_tcp_reuseport != conf_get_bool(conf, C_SRV, C_TCP_REUSEPORT)) { @@ -1165,7 +1228,7 @@ static void warn_server_reconfigure(conf_t *conf, server_t *server) } if (warn_listen && server->ifaces != NULL && listen_changed(conf, server)) { - log_warning(msg, "listen(-xdp,-quic)"); + log_warning(msg, "listen(-xdp,-quic,-tls)"); warn_listen = false; } @@ -1195,6 +1258,21 @@ static void warn_server_reconfigure(conf_t *conf, server_t *server) warn_route_check = false; } + if (warn_ring_size && conf->cache.xdp_ring_size != conf_get_int(conf, C_XDP, C_RING_SIZE)) { + log_warning(msg, &C_RING_SIZE[1]); + warn_ring_size = false; + } + + if (warn_busypoll_budget && conf->cache.xdp_busypoll_budget != conf_get_int(conf, C_XDP, C_BUSYPOLL_BUDGET)) { + log_warning(msg, &C_BUSYPOLL_BUDGET[1]); + warn_busypoll_budget = false; + } + + if (warn_busypoll_timeout && conf->cache.xdp_busypoll_timeout != conf_get_int(conf, C_XDP, C_BUSYPOLL_TIMEOUT)) { + log_warning(msg, &C_BUSYPOLL_TIMEOUT[1]); + warn_busypoll_timeout = false; + } + if (warn_rmt_pool_limit && global_conn_pool != NULL && global_conn_pool->capacity != conf_get_int(conf, C_SRV, C_RMT_POOL_LIMIT)) { log_warning(msg, &C_RMT_POOL_LIMIT[1]); @@ -1395,7 +1473,7 @@ static int reconfigure_remote_pool(conf_t *conf, server_t *server) #ifdef ENABLE_QUIC if (global_sessticket_pool == NULL && server->quic_active) { - size_t rmt_count = quic_rmt_count(conf); + size_t rmt_count = quic_rmt_count(conf, C_QUIC); if (rmt_count > 0) { size_t max_tickets = conf_bg_threads(conf) * rmt_count * 2; // Two addresses per remote. conn_pool_t *new_pool = @@ -1456,6 +1534,12 @@ int server_reconfigure(conf_t *conf, server_t *server) if (conf_lmdb_readers(conf) > CONF_MAX_DB_READERS) { log_warning("config, exceeded number of database readers"); } + } else { + /* Reconfigure TLS credentials. */ + if ((ret = init_creds(conf, server)) != KNOT_EOK) { + log_error("failed to reconfigure server credentials (%s)", + knot_strerror(ret)); + } } /* Reconfigure journal DB. */ @@ -1515,14 +1599,13 @@ void server_update_zones(conf_t *conf, server_t *server, reload_t mode) size_t server_cert_pin(server_t *server, uint8_t *out, size_t out_size) { -#ifdef ENABLE_QUIC int pin_size = 0; - uint8_t bin_pin[KNOT_QUIC_PIN_LEN]; + uint8_t bin_pin[KNOT_TLS_PIN_LEN]; size_t bin_pin_size = sizeof(bin_pin); gnutls_x509_crt_t cert = NULL; if (server->quic_creds != NULL && - knot_quic_creds_cert(server->quic_creds, &cert) == KNOT_EOK && + knot_creds_cert(server->quic_creds, &cert) == KNOT_EOK && gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, bin_pin, &bin_pin_size) == GNUTLS_E_SUCCESS) { pin_size = knot_base64_encode(bin_pin, bin_pin_size, out, out_size); @@ -1530,7 +1613,4 @@ size_t server_cert_pin(server_t *server, uint8_t *out, size_t out_size) gnutls_x509_crt_deinit(cert); return (pin_size >= 0) ? pin_size : 0; -#else - return 0; -#endif // ENABLE_QUIC } diff --git a/src/knot/server/server.h b/src/knot/server/server.h index e72e6de..fae06d6 100644 --- a/src/knot/server/server.h +++ b/src/knot/server/server.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,8 +16,7 @@ #pragma once -#include - +#include "contrib/atomic.h" #include "knot/conf/conf.h" #include "knot/catalog/catalog_update.h" #include "knot/common/evsched.h" @@ -32,7 +31,7 @@ struct server; struct knot_xdp_socket; -struct knot_quic_creds; +struct knot_creds; /*! * \brief I/O handler structure. @@ -75,7 +74,7 @@ typedef struct { unsigned fd_xdp_count; unsigned xdp_first_thread_id; bool anyaddr; - bool quic; + bool tls; struct knot_xdp_socket **xdp_sockets; struct sockaddr_storage addr; } iface_t; @@ -120,16 +119,20 @@ typedef struct server { iface_t *ifaces; size_t n_ifaces; bool quic_active; + bool tls_active; + + /*! \brief Mutex protecting simultaneous access from concurrent CTL threads. */ + pthread_rwlock_t ctl_lock; /*! \brief Pending changes to catalog member zones, update indication. */ catalog_update_t catalog_upd; - atomic_bool catalog_upd_signal; + knot_atomic_bool catalog_upd_signal; /*! \brief Context of pending zones' backup. */ zone_backup_ctxs_t backup_ctxs; /*! \brief Crendentials context for QUIC. */ - struct knot_quic_creds *quic_creds; + struct knot_creds *quic_creds; } server_t; /*! diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c index 305b2f4..7af2f58 100644 --- a/src/knot/server/tcp-handler.c +++ b/src/knot/server/tcp-handler.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,6 +36,7 @@ #include "knot/common/fdset.h" #include "knot/nameserver/process_query.h" #include "knot/query/layer.h" +#include "libknot/quic/tls.h" #include "contrib/macros.h" #include "contrib/mempattern.h" #include "contrib/net.h" @@ -57,6 +58,7 @@ typedef struct tcp_context { unsigned max_worker_fds; /*!< Max TCP clients per worker configuration + no. of ifaces. */ int idle_timeout; /*!< [s] TCP idle timeout configuration. */ int io_timeout; /*!< [ms] TCP send/recv timeout configuration. */ + struct knot_tls_ctx *tls_ctx; /*!< DoT answering context. */ } tcp_context_t; #define TCP_SWEEP_INTERVAL 2 /*!< [secs] granularity of connection sweeping. */ @@ -76,11 +78,22 @@ static void update_tcp_conf(tcp_context_t *tcp) tcp->idle_timeout = pconf->cache.srv_tcp_idle_timeout; tcp->io_timeout = pconf->cache.srv_tcp_io_timeout; rcu_read_unlock(); + + if (tcp->tls_ctx != NULL) { + tcp->tls_ctx->io_timeout = tcp->io_timeout; + } +} + +static void free_tls_ctx(fdset_t *set, int idx) +{ + void *tls_conn = *fdset_ctx2(set, idx); + knot_tls_conn_del(tls_conn); } /*! \brief Sweep TCP connection. */ -static fdset_sweep_state_t tcp_sweep(fdset_t *set, int fd, _unused_ void *data) +static fdset_sweep_state_t tcp_sweep(fdset_t *set, int idx, _unused_ void *data) { + const int fd = fdset_get_fd(set, idx); assert(set && fd >= 0); /* Best-effort, name and shame. */ @@ -92,6 +105,8 @@ static fdset_sweep_state_t tcp_sweep(fdset_t *set, int fd, _unused_ void *data) log_notice("TCP, terminated inactive client, address %s", addr_str); } + free_tls_ctx(set, idx); + return FDSET_SWEEP; } @@ -107,15 +122,14 @@ static void tcp_log_error(const struct sockaddr_storage *ss, const char *operati } static unsigned tcp_set_ifaces(const iface_t *ifaces, size_t n_ifaces, - fdset_t *fds, int thread_id) + fdset_t *fds, int thread_id, bool *tls) { if (n_ifaces == 0) { return 0; } for (const iface_t *i = ifaces; i != ifaces + n_ifaces; i++) { - if (i->fd_tcp_count == 0 || i->quic) { // Ignore XDP and QUIC interfaces. - assert(i->fd_xdp_count > 0 || i->quic); + if (i->fd_xdp_count > 0 || i->fd_tcp_count == 0) { // Ignore XDP and QUIC interfaces. continue; } @@ -133,31 +147,44 @@ static unsigned tcp_set_ifaces(const iface_t *ifaces, size_t n_ifaces, if (ret < 0) { return 0; } + if (i->tls) { + *tls = true; + } } return fdset_get_length(fds); } -static int tcp_handle(tcp_context_t *tcp, int fd, const sockaddr_t *remote, - const sockaddr_t *local, struct iovec *rx, struct iovec *tx) +static int tcp_handle(tcp_context_t *tcp, knotd_qdata_params_t *params, + struct iovec *rx, struct iovec *tx) { - /* Create query processing parameter. */ - knotd_qdata_params_t params = params_init(KNOTD_QUERY_PROTO_TCP, remote, local, - fd, tcp->server, tcp->thread_id); - rx->iov_len = KNOT_WIRE_MAX_PKTSIZE; tx->iov_len = KNOT_WIRE_MAX_PKTSIZE; /* Receive data. */ - int recv = net_dns_tcp_recv(fd, rx->iov_base, rx->iov_len, tcp->io_timeout); + int recv; + if (params->tls_conn != NULL) { + int ret = knot_tls_handshake(params->tls_conn, true); + switch (ret) { + case KNOT_EAGAIN: // Unfinished handshake, continue later. + return KNOT_EOK; + case KNOT_EOK: // Finished handshake, continue with receiving message. + recv = knot_tls_recv_dns(params->tls_conn, rx->iov_base, rx->iov_len); + break; + default: // E.g. handshake timeout. + return ret; + } + } else { + recv = net_dns_tcp_recv(params->socket, rx->iov_base, rx->iov_len, tcp->io_timeout); + } if (recv > 0) { rx->iov_len = recv; } else { - tcp_log_error(params.remote, "receive", recv); + tcp_log_error(params->remote, "receive", recv); return KNOT_EOF; } - handle_query(¶ms, &tcp->layer, rx, NULL); + handle_query(params, &tcp->layer, rx, NULL); /* Resolve until NOOP or finished. */ knot_pkt_t *ans = knot_pkt_new(tx->iov_base, tx->iov_len, tcp->layer.mm); @@ -165,10 +192,15 @@ static int tcp_handle(tcp_context_t *tcp, int fd, const sockaddr_t *remote, knot_layer_produce(&tcp->layer, ans); /* Send, if response generation passed and wasn't ignored. */ if (ans->size > 0 && send_state(tcp->layer.state)) { - int sent = net_dns_tcp_send(fd, ans->wire, ans->size, - tcp->io_timeout, NULL); + int sent; + if (params->tls_conn != NULL) { + sent = knot_tls_send_dns(params->tls_conn, ans->wire, ans->size); + } else { + sent = net_dns_tcp_send(params->socket, ans->wire, ans->size, + tcp->io_timeout, NULL); + } if (sent != ans->size) { - tcp_log_error(params.remote, "send", sent); + tcp_log_error(params->remote, "send", sent); handle_finish(&tcp->layer); return KNOT_EOF; } @@ -222,12 +254,42 @@ static int tcp_event_serve(tcp_context_t *tcp, unsigned i, const iface_t *iface) } } - int ret = tcp_handle(tcp, fd, remote, local, &tcp->iov[0], &tcp->iov[1]); + knotd_qdata_params_t params = params_init(iface->tls ? KNOTD_QUERY_PROTO_TLS + : KNOTD_QUERY_PROTO_TCP, + remote, local, fd, tcp->server, + tcp->thread_id); + + // NOTE there is no way to avoid calling accept() on unwanted connections: + // - it's not possible to read out the remote IP beforehand + // - there is no way to pull it out of the queue + // So we just accept() those connection (possibly going ahead with the handshake) + // and close it immediately. + if (process_query_proto(¶ms, KNOTD_STAGE_PROTO_BEGIN) == KNOTD_PROTO_STATE_BLOCK) { + return KNOT_EDENIED; // results in closing connection + } + + /* Establish a TLS session. */ + if (iface->tls) { + assert(tcp->tls_ctx != NULL); + knot_tls_conn_t *tls_conn = *fdset_ctx2(&tcp->set, i); + if (tls_conn == NULL) { + tls_conn = knot_tls_conn_new(tcp->tls_ctx, fd); + if (tls_conn == NULL) { + return KNOT_ENOMEM; + } + *fdset_ctx2(&tcp->set, i) = tls_conn; + } + params_update_tls(¶ms, tls_conn); + } + + int ret = tcp_handle(tcp, ¶ms, &tcp->iov[0], &tcp->iov[1]); if (ret == KNOT_EOK) { /* Update socket activity timer. */ (void)fdset_set_watchdog(&tcp->set, i, tcp->idle_timeout); } + (void)process_query_proto(¶ms, KNOTD_STAGE_PROTO_END); + return ret; } @@ -273,6 +335,7 @@ static void tcp_wait_for_events(tcp_context_t *tcp) /* Evaluate. */ if (should_close) { + free_tls_ctx(set, idx); fdset_it_remove(&it); } } @@ -325,13 +388,15 @@ int tcp_master(dthread_t *thread) /* Prepare initial buffer for listening and bound sockets. */ if (fdset_init(&tcp.set, FDSET_RESIZE_STEP) != KNOT_EOK) { + ret = KNOT_ENOMEM; goto finish; } /* Set descriptors for the configured interfaces. */ + bool tls = false; tcp.client_threshold = tcp_set_ifaces(handler->server->ifaces, handler->server->n_ifaces, - &tcp.set, thread_id); + &tcp.set, thread_id, &tls); if (tcp.client_threshold == 0) { goto finish; /* Terminate on zero interfaces. */ } @@ -341,6 +406,17 @@ int tcp_master(dthread_t *thread) update_sweep_timer(&next_sweep); update_tcp_conf(&tcp); + /* Initialize TLS context. */ + if (tls) { + // Set the HS timeout to 8x the RMT IO one as the HS duration can be up to 4*roundtrip. + tcp.tls_ctx = knot_tls_ctx_new(handler->server->quic_creds, + tcp.io_timeout, 8 * tcp.io_timeout, true); + if (tcp.tls_ctx == NULL) { + ret = KNOT_ENOMEM; + goto finish; + } + } + for (;;) { /* Check for cancellation. */ if (dt_is_cancelled(thread)) { @@ -359,6 +435,7 @@ int tcp_master(dthread_t *thread) } finish: + knot_tls_ctx_free(tcp.tls_ctx); free(tcp.iov[0].iov_base); free(tcp.iov[1].iov_base); mp_delete(mm.ctx); diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c index e54ce2c..c5166f9 100644 --- a/src/knot/server/udp-handler.c +++ b/src/knot/server/udp-handler.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -73,9 +73,15 @@ typedef struct { static void udp_handler(udp_context_t *udp, knotd_qdata_params_t *params, struct iovec *rx, struct iovec *tx) { + if (process_query_proto(params, KNOTD_STAGE_PROTO_BEGIN) == KNOTD_PROTO_STATE_BLOCK) { + return; + } + // Prepare a reply. struct sockaddr_storage proxied_remote; handle_udp_reply(params, &udp->layer, rx, tx, &proxied_remote); + + (void)process_query_proto(params, KNOTD_STAGE_PROTO_END); } typedef struct { @@ -153,7 +159,7 @@ void cmsg_handle(const struct msghdr *rx, struct msghdr *tx, } struct cmsghdr *cmsg = CMSG_FIRSTHDR(tx); - if (iface->quic) { + if (iface->tls) { *p_ecn = NULL; while (cmsg != NULL) { cmsg_handle_ecn(p_ecn, cmsg); @@ -246,9 +252,9 @@ static void udp_msg_handle(udp_context_t *ctx, const iface_t *iface, void *d) /* Process received pkt. */ knotd_qdata_params_t params = params_init( - iface->quic ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_UDP, + iface->tls ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_UDP, &rq->addr, local, rq->fd, ctx->server, ctx->thread_id); - if (iface->quic) { + if (iface->tls) { #ifdef ENABLE_QUIC quic_handler(¶ms, &ctx->layer, ctx->quic_idle_close, ctx->quic_table, &rq->iov[RX], &rq->msg[TX], p_ecn); @@ -357,9 +363,9 @@ static void udp_mmsg_handle(udp_context_t *ctx, const iface_t *iface, void *d) const sockaddr_t *local = local_addr(&ctx->local, iface); knotd_qdata_params_t params = params_init( - iface->quic ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_UDP, + iface->tls ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_UDP, &rq->addrs[i], local, rq->fd, ctx->server, ctx->thread_id); - if (iface->quic) { + if (iface->tls) { #ifdef ENABLE_QUIC quic_handler(¶ms, &ctx->layer, ctx->quic_idle_close, ctx->quic_table, rx->msg_iov, tx, p_ecn); @@ -432,7 +438,7 @@ static int xdp_mmsg_recv(_unused_ int fd, void *d) static void xdp_mmsg_handle(udp_context_t *ctx, _unused_ const iface_t *iface, void *d) { - assert(!iface->quic); + assert(!iface->tls); xdp_handle_msgs(d, &ctx->layer, ctx->server, ctx->thread_id); } @@ -482,7 +488,6 @@ static int iface_udp_fd(const iface_t *iface, int thread_id, bool xdp_thread, #endif } else { // UDP thread. if (iface->fd_udp_count == 0) { // No UDP interfaces. - assert(iface->fd_xdp_count > 0); return -1; } #ifdef ENABLE_REUSEPORT @@ -508,7 +513,7 @@ static unsigned udp_set_ifaces(const server_t *server, size_t n_ifaces, fdset_t #ifndef ENABLE_REUSEPORT /* If loadbalanced SO_REUSEPORT isn't available, ensure that * just one (first) UDP worker handles the QUIC sockets. */ - if (i->quic && thread_id > 0) { + if (i->tls && thread_id > 0) { continue; } #endif @@ -520,7 +525,7 @@ static unsigned udp_set_ifaces(const server_t *server, size_t n_ifaces, fdset_t if (ret < 0) { return 0; } - if (i->quic) { + if (i->tls) { *quic = true; } } diff --git a/src/knot/server/xdp-handler.c b/src/knot/server/xdp-handler.c index ae8512d..403bb70 100644 --- a/src/knot/server/xdp-handler.c +++ b/src/knot/server/xdp-handler.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include #include +#include "knot/nameserver/process_query.h" #include "knot/server/handler.h" #include "knot/server/quic-handler.h" #include "knot/server/xdp-handler.h" @@ -196,6 +197,12 @@ static void handle_udp(xdp_handle_ctx_t *ctx, knot_layer_t *layer, continue; } + params_xdp_update(params, KNOTD_QUERY_PROTO_UDP, msg_recv); + + if (process_query_proto(params, KNOTD_STAGE_PROTO_BEGIN) == KNOTD_PROTO_STATE_BLOCK) { + continue; + } + // Try to allocate a buffer for a reply. if (knot_xdp_reply_alloc(ctx->sock, msg_recv, msg_send) != KNOT_EOK) { if (log_enabled_debug()) { @@ -206,36 +213,50 @@ static void handle_udp(xdp_handle_ctx_t *ctx, knot_layer_t *layer, ctx->msg_udp_count++; // Prepare a reply. - params_xdp_update(params, KNOTD_QUERY_PROTO_UDP, msg_recv, 0, NULL); handle_udp_reply(params, layer, &msg_recv->payload, &msg_send->payload, &proxied_remote); + + (void)process_query_proto(params, KNOTD_STAGE_PROTO_END); } } static void handle_tcp(xdp_handle_ctx_t *ctx, knot_layer_t *layer, knotd_qdata_params_t *params) { - int ret = knot_tcp_recv(ctx->relays, ctx->msg_recv, ctx->msg_recv_count, - ctx->tcp_table, ctx->syn_table, XDP_TCP_IGNORE_NONE); - if (ret != KNOT_EOK) { - if (log_enabled_debug()) { - log_debug("TCP/XDP, failed to process some packets (%s)", knot_strerror(ret)); - } - return; - } else if (knot_tcp_relay_empty(&ctx->relays[0])) { // no TCP traffic - return; - } uint8_t ans_buf[KNOT_WIRE_MAX_PKTSIZE]; for (uint32_t i = 0; i < ctx->msg_recv_count; i++) { + knot_xdp_msg_t *msg_recv = &ctx->msg_recv[i]; knot_tcp_relay_t *rl = &ctx->relays[i]; + if (!(msg_recv->flags & KNOT_XDP_MSG_TCP)) { + continue; + } + + params_xdp_update(params, KNOTD_QUERY_PROTO_TCP, msg_recv); + + if (process_query_proto(params, KNOTD_STAGE_PROTO_BEGIN) == KNOTD_PROTO_STATE_BLOCK) { + continue; + } + + int ret = knot_tcp_recv(rl, msg_recv, ctx->tcp_table, + ctx->syn_table, XDP_TCP_IGNORE_NONE); + if (ret != KNOT_EOK) { + if (log_enabled_debug()) { + log_debug("TCP/XDP, failed to process some packets (%s)", + knot_strerror(ret)); + } + continue; + } else if (knot_tcp_relay_empty(rl)) { + continue; + } + + params_update_tcp(params, rl->conn->establish_rtt); + // Process all complete DNS queries in one TCP stream. for (size_t j = 0; rl->inbf != NULL && j < rl->inbf->n_inbufs; j++) { // Consume the query. - params_xdp_update(params, KNOTD_QUERY_PROTO_TCP, ctx->msg_recv, - rl->conn->establish_rtt, NULL); struct iovec *inbufs = rl->inbf->inbufs; handle_query(params, layer, &inbufs[j], NULL); @@ -253,6 +274,8 @@ static void handle_tcp(xdp_handle_ctx_t *ctx, knot_layer_t *layer, handle_finish(layer); } + + (void)process_query_proto(params, KNOTD_STAGE_PROTO_END); } } @@ -274,6 +297,12 @@ static void handle_quic(xdp_handle_ctx_t *ctx, knot_layer_t *layer, continue; } + params_xdp_update(params, KNOTD_QUERY_PROTO_QUIC, msg_recv); + + if (process_query_proto(params, KNOTD_STAGE_PROTO_BEGIN) == KNOTD_PROTO_STATE_BLOCK) { + continue; + } + knot_quic_reply_t *reply = &ctx->quic_replies[i]; knot_xdp_msg_t *msg_out = &ctx->msg_send_udp[i]; @@ -289,7 +318,9 @@ static void handle_quic(xdp_handle_ctx_t *ctx, knot_layer_t *layer, &ctx->quic_relays[i]); knot_quic_conn_t *conn = ctx->quic_relays[i]; - handle_quic_streams(conn, params, layer, &ctx->msg_recv[i]); + handle_quic_streams(conn, params, layer); + + (void)process_query_proto(params, KNOTD_STAGE_PROTO_END); } #else (void)(ctx); diff --git a/src/knot/updates/acl.c b/src/knot/updates/acl.c index d297747..456e8bb 100644 --- a/src/knot/updates/acl.c +++ b/src/knot/updates/acl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,16 +18,13 @@ #include "contrib/string.h" #include "contrib/wire_ctx.h" -#ifdef ENABLE_QUIC -#include "libknot/quic/quic.h" -#endif // ENABLE_QUIC static bool cert_pin_check(const uint8_t *session_pin, size_t session_pin_size, conf_val_t *pins) { if (pins->code == KNOT_ENOENT) { // No certificate pin authentication required. return true; - } else if (session_pin_size == 0) { // Not a QUIC connection. + } else if (session_pin_size == 0) { // Not a TLS/QUIC connection. return false; } @@ -283,20 +280,15 @@ static bool check_addr_key(conf_t *conf, conf_val_t *addr_val, conf_val_t *key_v bool acl_allowed(conf_t *conf, conf_val_t *acl, acl_action_t action, const struct sockaddr_storage *addr, knot_tsig_key_t *tsig, const knot_dname_t *zone_name, knot_pkt_t *query, - struct knot_quic_conn *conn) + struct gnutls_session_int *tls_session) { if (acl == NULL || addr == NULL || tsig == NULL) { return false; } -#ifdef ENABLE_QUIC - uint8_t session_pin[KNOT_QUIC_PIN_LEN]; + uint8_t session_pin[KNOT_TLS_PIN_LEN]; size_t session_pin_size = sizeof(session_pin); - knot_quic_conn_pin(conn, session_pin, &session_pin_size, false); -#else - uint8_t session_pin[1]; - size_t session_pin_size = 0; -#endif // ENABLE_QUIC + knot_tls_pin(tls_session, session_pin, &session_pin_size, false); bool forward = false; if (action == ACL_ACTION_UPDATE) { @@ -392,20 +384,15 @@ next_acl: } bool rmt_allowed(conf_t *conf, conf_val_t *rmts, const struct sockaddr_storage *addr, - knot_tsig_key_t *tsig, struct knot_quic_conn *conn) + knot_tsig_key_t *tsig, struct gnutls_session_int *tls_session) { if (!conf->cache.srv_auto_acl) { return false; } -#ifdef ENABLE_QUIC - uint8_t session_pin[KNOT_QUIC_PIN_LEN]; + uint8_t session_pin[KNOT_TLS_PIN_LEN]; size_t session_pin_size = sizeof(session_pin); - knot_quic_conn_pin(conn, session_pin, &session_pin_size, false); -#else - uint8_t session_pin[1]; - size_t session_pin_size = 0; -#endif // ENABLE_QUIC + knot_tls_pin(tls_session, session_pin, &session_pin_size, false); conf_mix_iter_t iter; conf_mix_iter_init(conf, rmts, &iter); diff --git a/src/knot/updates/acl.h b/src/knot/updates/acl.h index 88d7de5..5072a29 100644 --- a/src/knot/updates/acl.h +++ b/src/knot/updates/acl.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ #include #include +#include "libknot/quic/tls_common.h" #include "libknot/tsig.h" #include "knot/conf/conf.h" @@ -51,21 +52,21 @@ typedef enum { * * If a proper ACL rule is found and tsig.name is not empty, tsig.secret is filled. * - * \param conf Configuration. - * \param acl Pointer to ACL config multivalued identifier. - * \param action ACL action. - * \param addr IP address. - * \param tsig TSIG parameters. - * \param zone_name Zone name. - * \param query Update query. - * \param conn Possible QUIC connection. + * \param conf Configuration. + * \param acl Pointer to ACL config multivalued identifier. + * \param action ACL action. + * \param addr IP address. + * \param tsig TSIG parameters. + * \param zone_name Zone name. + * \param query Update query. + * \param tls_session Possible TLS session. * * \retval True if authenticated. */ bool acl_allowed(conf_t *conf, conf_val_t *acl, acl_action_t action, const struct sockaddr_storage *addr, knot_tsig_key_t *tsig, const knot_dname_t *zone_name, knot_pkt_t *query, - struct knot_quic_conn *conn); + struct gnutls_session_int *tls_session); /*! * \brief Checks if the address and/or tsig key matches a remote from the list. @@ -75,13 +76,13 @@ bool acl_allowed(conf_t *conf, conf_val_t *acl, acl_action_t action, * * If a proper REMOTE is found and tsig.name is not empty, tsig.secret is filled. * - * \param conf Configuration. - * \param rmts Pointer to REMOTE config multivalued identifier. - * \param addr IP address. - * \param tsig TSIG parameters. - * \param conn Possible QUIC connection. + * \param conf Configuration. + * \param rmts Pointer to REMOTE config multivalued identifier. + * \param addr IP address. + * \param tsig TSIG parameters. + * \param tls_session Possible TLS session. * * \retval True if authenticated. */ bool rmt_allowed(conf_t *conf, conf_val_t *rmts, const struct sockaddr_storage *addr, - knot_tsig_key_t *tsig, struct knot_quic_conn *conn); + knot_tsig_key_t *tsig, struct gnutls_session_int *tls_session); diff --git a/src/knot/updates/ddns.c b/src/knot/updates/ddns.c index 5ab858f..47e3fc5 100644 --- a/src/knot/updates/ddns.c +++ b/src/knot/updates/ddns.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -266,21 +266,41 @@ static bool node_contains_rr(const zone_node_t *node, /*!< \brief Returns true if CNAME is in this node. */ static bool adding_to_cname(const knot_dname_t *owner, + zone_update_t *update, const zone_node_t *node) { if (node == NULL) { - // Node did not exist before update. + // Node did not exist before update, juch check DNAMEs above. + + while ((owner = knot_dname_next_label(owner)) != NULL && + (node = zone_update_get_node(update, owner)) == NULL); + + for ( ; node != NULL; node = node->parent) { + knot_rrset_t dname = node_rrset(node, KNOT_RRTYPE_DNAME); + if (!knot_rrset_empty(&dname)) { + // DNAME above + return true; + } + } + return false; } knot_rrset_t cname = node_rrset(node, KNOT_RRTYPE_CNAME); - if (knot_rrset_empty(&cname)) { - // Node did not contain CNAME before update. - return false; + if (!knot_rrset_empty(&cname)) { + // CNAME present + return true; } - // CNAME present - return true; + while ((node = node->parent) != NULL) { + knot_rrset_t dname = node_rrset(node, KNOT_RRTYPE_DNAME); + if (!knot_rrset_empty(&dname)) { + // DNAME above + return true; + } + } + + return false; } /*!< \brief Used to ignore SOA deletions and SOAs with lower serial than zone. */ @@ -315,12 +335,29 @@ static int add_rr_to_changeset(const knot_rrset_t *rr, zone_update_t *update) return zone_update_add(update, rr); } -/*!< \brief Processes CNAME addition (replace or ignore) */ +int node_empty_cb(zone_node_t *node, _unused_ void *ctx) +{ + return node_empty(node) ? KNOT_EOK : KNOT_ESEMCHECK; +} + +bool subtree_empty(zone_contents_t *zone, const zone_node_t *node) +{ + if (node == NULL) { + return true; + } + int ret = zone_tree_sub_apply(zone->nodes, node->owner, true, node_empty_cb, NULL); + return (ret == KNOT_EOK); +} + +/*!< \brief Processes CNAME/DNAME addition (replace or ignore) */ static int process_add_cname(const zone_node_t *node, const knot_rrset_t *rr, + uint16_t type, zone_update_t *update) { - knot_rrset_t cname = node_rrset(node, KNOT_RRTYPE_CNAME); + assert(type == KNOT_RRTYPE_CNAME || type == KNOT_RRTYPE_DNAME); + + knot_rrset_t cname = node_rrset(node, type); if (!knot_rrset_empty(&cname)) { // If they are identical, ignore. if (knot_rrset_equal(&cname, rr, true)) { @@ -333,40 +370,24 @@ static int process_add_cname(const zone_node_t *node, } return add_rr_to_changeset(rr, update); - } else if (!node_empty(node)) { + } else if (type == KNOT_RRTYPE_CNAME && !node_empty(node)) { // Other occupied node => ignore. return KNOT_EOK; + } else if (type == KNOT_RRTYPE_DNAME && !subtree_empty(update->new_cont, node)) { + // Equivalent to above, ignore. + return KNOT_EOK; + } else if (type == KNOT_RRTYPE_DNAME && node_rrtype_exists(node, KNOT_RRTYPE_CNAME)) { + // RFC 6672 §5.2. + return KNOT_EOK; + } else if (type == KNOT_RRTYPE_CNAME && adding_to_cname(rr->owner, update, node)) { + // DNAME exists above CNAME, ignore. + return KNOT_EOK; } else { // Can add. return add_rr_to_changeset(rr, update); } } -/*!< \brief Processes NSEC3PARAM addition (ignore when not removed, or non-apex) */ -static int process_add_nsec3param(const zone_node_t *node, - const knot_rrset_t *rr, - zone_update_t *update) -{ - if (node == NULL || !node_rrtype_exists(node, KNOT_RRTYPE_SOA)) { - // Ignore non-apex additions - char *owner = knot_dname_to_str_alloc(rr->owner); - log_warning("DDNS, refusing to add NSEC3PARAM to non-apex " - "node '%s'", owner); - free(owner); - return KNOT_EDENIED; - } - knot_rrset_t param = node_rrset(node, KNOT_RRTYPE_NSEC3PARAM); - if (knot_rrset_empty(¶m)) { - return add_rr_to_changeset(rr, update); - } - - char *owner = knot_dname_to_str_alloc(rr->owner); - log_warning("DDNS, refusing to add second NSEC3PARAM to node '%s'", owner); - free(owner); - - return KNOT_EOK; -} - /*! * \brief Processes SOA addition (ignore when non-apex), lower serials * dropped before. @@ -395,7 +416,7 @@ static int process_add_normal(const zone_node_t *node, const knot_rrset_t *rr, zone_update_t *update) { - if (adding_to_cname(rr->owner, node)) { + if (adding_to_cname(rr->owner, update, node)) { // Adding RR to CNAME node, ignore. return KNOT_EOK; } @@ -415,11 +436,10 @@ static int process_add(const knot_rrset_t *rr, { switch(rr->type) { case KNOT_RRTYPE_CNAME: - return process_add_cname(node, rr, update); + case KNOT_RRTYPE_DNAME: + return process_add_cname(node, rr, rr->type, update); case KNOT_RRTYPE_SOA: return process_add_soa(node, rr, update); - case KNOT_RRTYPE_NSEC3PARAM: - return process_add_nsec3param(node, rr, update); default: return process_add_normal(node, rr, update); } @@ -531,49 +551,32 @@ static int process_remove(const knot_rrset_t *rr, } } -/*!< \brief Checks whether addition has not violated DNAME rules. */ -static bool sem_check(const knot_rrset_t *rr, const zone_node_t *zone_node, - zone_update_t *update) -{ - const zone_node_t *added_node = zone_contents_find_node(update->new_cont, rr->owner); - - // we do this sem check AFTER adding the RR, so the node must exist - assert(added_node != NULL); - - for (const zone_node_t *parent = added_node->parent; - parent != NULL; parent = parent->parent) { - if (node_rrtype_exists(parent, KNOT_RRTYPE_DNAME)) { - // Parent has DNAME RRSet, refuse update - return false; - } - } - - if (rr->type != KNOT_RRTYPE_DNAME || zone_node == NULL) { - return true; - } - - // Check that we have not created node with DNAME children. - if (zone_node->children > 0) { - // Updated node has children and DNAME was added, refuse update - return false; - } - - return true; -} - /*!< \brief Checks whether we can accept this RR. */ static int check_update(const knot_rrset_t *rrset, const knot_pkt_t *query, - uint16_t *rcode) + const zone_contents_t *zone, uint16_t *rcode) { /* Accept both subdomain and dname match. */ const knot_dname_t *owner = rrset->owner; const knot_dname_t *qname = knot_pkt_qname(query); + assert(knot_dname_is_equal(qname, zone->apex->owner)); const int in_bailiwick = knot_dname_in_bailiwick(owner, qname); if (in_bailiwick < 0) { *rcode = KNOT_RCODE_NOTZONE; return KNOT_EOUTOFZONE; } + if (rrset->type == KNOT_RRTYPE_NSEC3PARAM) { + if (!knot_dname_is_equal(rrset->owner, zone->apex->owner)) { + log_warning("DDNS, refusing to add NSEC3PARAM to non-apex node"); + *rcode = KNOT_RCODE_REFUSED; + return KNOT_EDENIED; + } else if (node_rrtype_exists(zone->apex, rrset->type)) { + log_warning("DDNS, refusing to add second NSEC3PARAM to zone apex"); + *rcode = KNOT_RCODE_REFUSED; + return KNOT_EDENIED; + } + } + if (rrset->rclass == knot_pkt_qclass(query)) { if (knot_rrtype_is_metatype(rrset->type)) { *rcode = KNOT_RCODE_FORMERR; @@ -605,13 +608,7 @@ static int process_rr(const knot_rrset_t *rr, zone_update_t *update) const zone_node_t *node = zone_update_get_node(update, rr->owner); if (is_addition(rr)) { - int ret = process_add(rr, node, update); - if (ret == KNOT_EOK) { - if (!sem_check(rr, node, update)) { - return KNOT_EDENIED; - } - } - return ret; + return process_add(rr, node, update); } else if (is_removal(rr)) { return process_remove(rr, node, update); } else { @@ -660,6 +657,27 @@ int ddns_process_prereqs(const knot_pkt_t *query, zone_update_t *update, return ret; } +int ddns_precheck_update(const knot_pkt_t *query, zone_update_t *update, + uint16_t *rcode) +{ + if (query == NULL || rcode == NULL || update == NULL) { + return KNOT_EINVAL; + } + + // Check all RRs in the authority section. + const knot_pktsection_t *authority = knot_pkt_section(query, KNOT_AUTHORITY); + const knot_rrset_t *authority_rr = (authority->count > 0) ? knot_pkt_rr(authority, 0) : NULL; + for (uint16_t i = 0; i < authority->count; ++i) { + int ret = check_update(&authority_rr[i], query, update->new_cont, rcode); + if (ret != KNOT_EOK) { + assert(*rcode != KNOT_RCODE_NOERROR); + return ret; + } + } + + return KNOT_EOK; +} + int ddns_process_update(const knot_pkt_t *query, zone_update_t *update, uint16_t *rcode) { @@ -677,18 +695,11 @@ int ddns_process_update(const knot_pkt_t *query, zone_update_t *update, const knot_rrset_t *authority_rr = (authority->count > 0) ? knot_pkt_rr(authority, 0) : NULL; for (uint16_t i = 0; i < authority->count; ++i) { const knot_rrset_t *rr = &authority_rr[i]; - // Check if RR is correct. - int ret = check_update(rr, query, rcode); - if (ret != KNOT_EOK) { - assert(*rcode != KNOT_RCODE_NOERROR); - return ret; - } - if (skip_soa(rr, sn_old)) { continue; } - ret = process_rr(rr, update); + int ret = process_rr(rr, update); if (ret != KNOT_EOK) { *rcode = ret_to_rcode(ret); return ret; diff --git a/src/knot/updates/ddns.h b/src/knot/updates/ddns.h index d5661f5..40f1b37 100644 --- a/src/knot/updates/ddns.h +++ b/src/knot/updates/ddns.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +31,18 @@ int ddns_process_prereqs(const knot_pkt_t *query, zone_update_t *update, uint16_t *rcode); +/*! + * \brief Performs a pre-check of the update'S sanity. + * + * \param query DNS message containing the update. + * \param update Zone to be checked. + * \param rcode Returned DNS RCODE. + * + * \return KNOT_E* + */ +int ddns_precheck_update(const knot_pkt_t *query, zone_update_t *update, + uint16_t *rcode); + /*! * \brief Processes DNS update and creates a changeset out of it. Zone is left * intact. diff --git a/src/knot/updates/zone-update.c b/src/knot/updates/zone-update.c index 73c9558..4b65a2c 100644 --- a/src/knot/updates/zone-update.c +++ b/src/knot/updates/zone-update.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,8 +19,8 @@ #include #include "knot/catalog/interpret.h" +#include "knot/common/dbus.h" #include "knot/common/log.h" -#include "knot/common/systemd.h" #include "knot/dnssec/zone-events.h" #include "knot/server/server.h" #include "knot/updates/zone-update.h" @@ -942,26 +942,10 @@ int zone_update_commit(conf_t *conf, zone_update_t *update) val = conf_zone_get(conf, C_DNSSEC_VALIDATION, update->zone->name); if (conf_bool(&val)) { bool incr_valid = update->flags & UPDATE_INCREMENTAL; - const char *msg_valid = incr_valid ? "incremental " : ""; - - ret = knot_dnssec_validate_zone(update, conf, 0, incr_valid); + ret = knot_dnssec_validate_zone(update, conf, 0, incr_valid, true); if (ret != KNOT_EOK) { - log_zone_error(update->zone->name, "DNSSEC, %svalidation failed (%s)", - msg_valid, knot_strerror(ret)); - char type_str[16]; - knot_dname_txt_storage_t name_str; - if (knot_dname_to_str(name_str, update->validation_hint.node, sizeof(name_str)) != NULL && - knot_rrtype_to_string(update->validation_hint.rrtype, type_str, sizeof(type_str)) >= 0) { - log_zone_error(update->zone->name, "DNSSEC, validation hint: %s %s", - name_str, type_str); - } discard_adds_tree(update); - if (conf->cache.srv_dbus_event & DBUS_EVENT_ZONE_INVALID) { - systemd_emit_zone_invalid(update->zone->name); - } return ret; - } else { - log_zone_info(update->zone->name, "DNSSEC, %svalidation successful", msg_valid); } } @@ -1023,8 +1007,8 @@ int zone_update_commit(conf_t *conf, zone_update_t *update) } if (conf->cache.srv_dbus_event & DBUS_EVENT_ZONE_UPDATED) { - systemd_emit_zone_updated(update->zone->name, - zone_contents_serial(update->zone->contents)); + dbus_emit_zone_updated(update->zone->name, + zone_contents_serial(update->zone->contents)); } memset(update, 0, sizeof(*update)); diff --git a/src/knot/updates/zone-update.h b/src/knot/updates/zone-update.h index 0499d72..814d0ec 100644 --- a/src/knot/updates/zone-update.h +++ b/src/knot/updates/zone-update.h @@ -25,7 +25,9 @@ typedef struct { knot_dname_storage_t next; const knot_dname_t *node; + uint32_t remaining_secs; uint16_t rrtype; + int warning; } dnssec_validation_hint_t; /*! \brief Structure for zone contents updating / querying. */ diff --git a/src/knot/zone/backup.c b/src/knot/zone/backup.c index 36fd577..5c3038a 100644 --- a/src/knot/zone/backup.c +++ b/src/knot/zone/backup.c @@ -85,6 +85,7 @@ int zone_backup_init(bool restore_mode, knot_backup_params_t filters, bool force ctx->restore_mode = restore_mode; ctx->backup_params = filters; ctx->in_backup = 0; // Just to be sure. + ctx->arch_match = true; ctx->forced = forced; ctx->backup_format = BACKUP_VERSION; ctx->backup_global = false; @@ -105,6 +106,11 @@ int zone_backup_init(bool restore_mode, knot_backup_params_t filters, bool force // For restore, check that there are all required data components in the backup. if (restore_mode) { + if (!ctx->arch_match && filters & BACKUP_PARAM_DB) { + free(ctx); + return KNOT_ECPUCOMPAT; + } + // '+kaspdb' in backup provides data also for '+keysonly' restore. knot_backup_params_t available = ctx->in_backup | ((bool)(ctx->in_backup & BACKUP_PARAM_KASPDB) * BACKUP_PARAM_KEYSONLY); @@ -369,7 +375,7 @@ static int backup_keystore(conf_t *conf, zone_t *zone, zone_backup_ctx_t *ctx) return ret; } if (backend_type == KEYSTORE_BACKEND_PKCS11) { - log_zone_notice(zone->name, "private keys from PKCS #11 aren't subject of backup/restore"); + log_zone_notice(zone->name, "private keys from PKCS #11 are not subject of backup/restore"); (void)dnssec_keystore_deinit(from); return KNOT_EOK; } diff --git a/src/knot/zone/backup.h b/src/knot/zone/backup.h index 9f2660d..ad0c954 100644 --- a/src/knot/zone/backup.h +++ b/src/knot/zone/backup.h @@ -57,6 +57,11 @@ typedef enum { BACKUP_PARAM_TIMERS | BACKUP_PARAM_KASPDB | \ BACKUP_PARAM_CATALOG) +/*! \bref Backup components using LMDB databases. */ +#define BACKUP_PARAM_DB (BACKUP_PARAM_JOURNAL | BACKUP_PARAM_TIMERS | \ + BACKUP_PARAM_KASPDB | BACKUP_PARAM_KEYSONLY | \ + BACKUP_PARAM_CATALOG) + typedef struct { const char *name; knot_backup_params_t param; @@ -70,6 +75,7 @@ typedef struct zone_backup_ctx { bool forced; // if true, the force flag has been set knot_backup_params_t backup_params; // bit-mapped list of backup components knot_backup_params_t in_backup; // bit-mapped list of components available in backup + bool arch_match; // match of the system and the backup architectures bool backup_global; // perform global backup for all zones ssize_t readers; // when decremented to 0, all zones done, free this context pthread_mutex_t readers_mutex; // mutex covering readers counter diff --git a/src/knot/zone/backup_dir.c b/src/knot/zone/backup_dir.c index 7bf9fd5..b382258 100644 --- a/src/knot/zone/backup_dir.c +++ b/src/knot/zone/backup_dir.c @@ -28,11 +28,21 @@ #include "contrib/getline.h" #include "knot/common/log.h" +#ifdef ENDIANITY_LITTLE + #define ENDIAN_STR "LE" +#else + #define ENDIAN_STR "BE" +#endif +#define _STR(x) #x +#define STR(x) _STR(x) +#define KNOT_ARCH STR(__LONG_WIDTH__) ENDIAN_STR + #define LABEL_FILE "knot_backup.label" #define LOCK_FILE "lock.knot_backup" #define LABEL_FILE_HEAD "label: Knot DNS Backup\n" #define LABEL_FILE_FORMAT "backup_format: %d\n" +#define LABEL_FILE_ARCH "architecture: " #define LABEL_FILE_PARAMS "parameters: " #define LABEL_FILE_BACKUPDIR "backupdir " #define LABEL_FILE_TIME_FORMAT "%Y-%m-%d %H:%M:%S %Z" @@ -49,6 +59,7 @@ static const char *label_file_name = LABEL_FILE; static const char *lock_file_name = LOCK_FILE; static const char *label_file_head = LABEL_FILE_HEAD; +static const char *label_file_arch = KNOT_ARCH; static void get_full_path(zone_backup_ctx_t *ctx, const char *filename, char *full_path, size_t full_path_size) @@ -125,6 +136,9 @@ static int make_label_file(zone_backup_ctx_t *ctx) localtime_r(&now, &tm); strftime(finished_time, sizeof(finished_time), LABEL_FILE_TIME_FORMAT, &tm); + int lmdb_major, lmdb_minor, lmdb_patch; + (void)mdb_version(&lmdb_major, &lmdb_minor, &lmdb_patch); + // Print the label contents. char params_str[PARAMS_MAX_LENGTH]; print_params(params_str, ctx->backup_params); @@ -135,10 +149,14 @@ static int make_label_file(zone_backup_ctx_t *ctx) "started_time: %s\n" "finished_time: %s\n" "knot_version: %s\n" + "lmdb_version: %d.%d.%d\n" + LABEL_FILE_ARCH "%s\n" LABEL_FILE_PARAMS "%s+" LABEL_FILE_BACKUPDIR "%s\n" "zone_count: %d\n", label_file_head, - ctx->backup_format, ident, started_time, finished_time, PACKAGE_VERSION, + ctx->backup_format, ident, started_time, finished_time, + PACKAGE_VERSION, + lmdb_major, lmdb_minor, lmdb_patch, label_file_arch, params_str, ctx->backup_dir, ctx->zone_count); @@ -199,6 +217,7 @@ static int get_backup_format(zone_backup_ctx_t *ctx) unsigned int remain = 3; // Bit-mapped "punch card" for lines to get data from. while (remain > 0 && knot_getline(&line, &line_size, file) != -1) { int value; + char str[8]; if (sscanf(line, LABEL_FILE_FORMAT, &value) != 0) { if (value >= BACKUP_FORMAT_TERM) { ret = KNOT_ENOTSUP; @@ -212,6 +231,11 @@ static int get_backup_format(zone_backup_ctx_t *ctx) continue; } } + if (sscanf(line, LABEL_FILE_ARCH "%7s\n", str) != 0 && + strcmp(str, label_file_arch) != 0) { + ctx->arch_match = false; + continue; + } if (strncmp(line, LABEL_FILE_PARAMS, sizeof(LABEL_FILE_PARAMS) - 1) == 0) { ctx->in_backup = parse_params(line + sizeof(LABEL_FILE_PARAMS) - 1); remain &= ~2; @@ -240,6 +264,22 @@ int backupdir_init(zone_backup_ctx_t *ctx) return KNOT_ENOTDIR; } } else { + if (ctx->forced) { + if (stat(ctx->backup_dir, &sb) == 0) { + int ret2 = remove_path(ctx->backup_dir, S_ISDIR(sb.st_mode)); + if (ret2 != KNOT_EOK) { + return ret2; + } + } else if (errno != ENOENT) { + return knot_map_errno(); + } else if (lstat(ctx->backup_dir, &sb) == 0 && S_ISLNK(sb.st_mode)) { + // Stale symlink. + if (unlink(ctx->backup_dir) != 0) { + return knot_map_errno(); + } + } // Omitting lstat() failure check, make_dir() will do it. + } + ret = make_dir(ctx->backup_dir, S_IRWXU | S_IRWXG, true); if (ret != KNOT_EOK) { return ret; diff --git a/src/knot/zone/contents.c b/src/knot/zone/contents.c index cba13e8..262136b 100644 --- a/src/knot/zone/contents.c +++ b/src/knot/zone/contents.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -106,6 +106,12 @@ static zone_node_t *get_nsec3_node(const zone_contents_t *zone, return zone_tree_get(zone->nsec3_nodes, name); } +// UBSAN type punning workaround +static zone_node_t *node_new_for_contents_wrap(const uint8_t *owner, void *contents) +{ + return node_new_for_contents(owner, contents); +} + static int insert_rr(zone_contents_t *z, const knot_rrset_t *rr, zone_node_t **n) { if (knot_rrset_empty(rr)) { @@ -114,7 +120,7 @@ static int insert_rr(zone_contents_t *z, const knot_rrset_t *rr, zone_node_t **n if (*n == NULL) { int ret = zone_tree_add_node(zone_contents_tree_for_rr(z, rr), z->apex, rr->owner, - (zone_tree_new_node_cb_t)node_new_for_contents, z, n); + node_new_for_contents_wrap, z, n); if (ret != KNOT_EOK) { return ret; } diff --git a/src/knot/zone/contents.h b/src/knot/zone/contents.h index 8f1f160..f344c97 100644 --- a/src/knot/zone/contents.h +++ b/src/knot/zone/contents.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,6 +16,7 @@ #pragma once +#include "contrib/time.h" #include "libdnssec/nsec.h" #include "libknot/rrtype/nsec3param.h" #include "knot/zone/node.h" @@ -38,6 +39,7 @@ typedef struct zone_contents { size_t size; uint32_t max_ttl; bool dnssec; + knot_time_t dnssec_expire; } zone_contents_t; /*! diff --git a/src/knot/zone/digest.c b/src/knot/zone/digest.c index b961f15..a4d50ce 100644 --- a/src/knot/zone/digest.c +++ b/src/knot/zone/digest.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -60,7 +60,7 @@ static int digest_rrset(knot_rrset_t *rrset, const zone_node_t *node, void *vctx } } - size_t buf_req = knot_rrset_size(rrset); + size_t buf_req = knot_rrset_size_estimate(rrset); if (buf_req > ctx->buf_size) { uint8_t *newbuf = realloc(ctx->buf, buf_req); if (newbuf == NULL) { @@ -71,7 +71,7 @@ static int digest_rrset(knot_rrset_t *rrset, const zone_node_t *node, void *vctx } int ret = knot_rrset_to_wire_extra(rrset, ctx->buf, ctx->buf_size, 0, - NULL, KNOT_PF_ORIGTTL | KNOT_PF_BUFENOUGH); + NULL, KNOT_PF_ORIGTTL); // cleanup apex RRSIGs mess if (node == ctx->apex && rrset->type == KNOT_RRTYPE_RRSIG) { diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c index 92ad29c..3d085d8 100644 --- a/src/knot/zone/semantic-check.c +++ b/src/knot/zone/semantic-check.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,8 @@ static const char *error_messages[SEM_ERR_UNKNOWN + 1] = { [SEM_ERR_SOA_NONE] = "missing SOA at the zone apex", + [SEM_ERR_SOA_MULTIPLE] = + "multiple SOA records", [SEM_ERR_CNAME_EXTRA_RECORDS] = "another record exists beside CNAME", @@ -516,7 +518,7 @@ static sem_error_t err_dnssec2sem(int ret, uint16_t rrtype, char *info, size_t l static int verify_dnssec(zone_contents_t *zone, sem_handler_t *handler, time_t time) { zone_update_t fake_up = { .new_cont = zone, }; - int ret = knot_dnssec_validate_zone(&fake_up, NULL, time, false); + int ret = knot_dnssec_validate_zone(&fake_up, NULL, time, false, false); if (fake_up.validation_hint.node != NULL) { // validation found an issue char info[64] = ""; sem_error_t err = err_dnssec2sem(ret, fake_up.validation_hint.rrtype, info, sizeof(info)); diff --git a/src/knot/zone/semantic-check.h b/src/knot/zone/semantic-check.h index 230c709..a0b1d21 100644 --- a/src/knot/zone/semantic-check.h +++ b/src/knot/zone/semantic-check.h @@ -35,6 +35,7 @@ typedef enum { typedef enum { // Mandatory checks. SEM_ERR_SOA_NONE, + SEM_ERR_SOA_MULTIPLE, SEM_ERR_CNAME_EXTRA_RECORDS, SEM_ERR_CNAME_MULTIPLE, diff --git a/src/knot/zone/zone-tree.c b/src/knot/zone/zone-tree.c index 87dde18..c3f79e7 100644 --- a/src/knot/zone/zone-tree.c +++ b/src/knot/zone/zone-tree.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -241,7 +241,7 @@ int zone_tree_add_node(zone_tree_t *tree, zone_node_t *apex, const knot_dname_t return ret; } zone_node_t *parent = NULL; - ret = zone_tree_add_node(tree, apex, knot_wire_next_label(dname, NULL), new_cb, new_cb_ctx, &parent); + ret = zone_tree_add_node(tree, apex, knot_dname_next_label(dname), new_cb, new_cb_ctx, &parent); if (ret != KNOT_EOK) { return ret; } diff --git a/src/knot/zone/zone.c b/src/knot/zone/zone.c index 7c84202..06a8a90 100644 --- a/src/knot/zone/zone.c +++ b/src/knot/zone/zone.c @@ -180,6 +180,7 @@ zone_t* zone_new(const knot_dname_t *name) zone->ddns_queue_size = 0; init_list(&zone->ddns_queue); + pthread_mutex_init(&zone->cu_lock, NULL); knot_sem_init(&zone->cow_lock, 1); // Preferred master lock @@ -222,6 +223,7 @@ void zone_free(zone_t **zone_ptr) free_ddns_queue(zone); pthread_mutex_destroy(&zone->ddns_lock); + pthread_mutex_destroy(&zone->cu_lock); knot_sem_destroy(&zone->cow_lock); /* Control update. */ @@ -273,6 +275,12 @@ void zone_reset(conf_t *conf, zone_t *zone) } \ } +// UBSAN type punning workaround +static bool dname_cmp_sweep_wrap(const uint8_t *zone, void *data) +{ + return knot_dname_cmp((const knot_dname_t *)zone, (const knot_dname_t *)data) != 0; +} + int selective_zone_purge(conf_t *conf, zone_t *zone, purge_flag_t params) { if (conf == NULL || zone == NULL) { @@ -291,7 +299,7 @@ int selective_zone_purge(conf_t *conf, zone_t *zone, purge_flag_t params) zone_timers_sanitize(conf, zone); zone->zonefile.bootstrap_cnt = 0; ret = zone_timers_sweep(&zone->server->timerdb, - (sweep_cb)knot_dname_cmp, zone->name); + dname_cmp_sweep_wrap, zone->name); RETURN_IF_FAILED("timers", KNOT_ENOENT); } diff --git a/src/knot/zone/zone.h b/src/knot/zone/zone.h index 0527c85..a6046de 100644 --- a/src/knot/zone/zone.h +++ b/src/knot/zone/zone.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,6 +16,7 @@ #pragma once +#include "contrib/atomic.h" #include "contrib/semaphore.h" #include "knot/catalog/catalog_update.h" #include "knot/conf/conf.h" @@ -114,6 +115,7 @@ typedef struct zone /*! \brief Control update context. */ struct zone_update *control_update; + pthread_mutex_t cu_lock; /*! \brief Ensue one COW transaction on zone's trees at a time. */ knot_sem_t cow_lock; @@ -122,7 +124,7 @@ typedef struct zone struct server *server; /*! \brief Zone backup context (NULL unless backup pending). */ - struct zone_backup_ctx *backup_ctx; + knot_atomic_ptr_t backup_ctx; /*! \brief Catalog-generate feature. */ knot_dname_t *catalog_gen; diff --git a/src/knot/zone/zonedb-load.c b/src/knot/zone/zonedb-load.c index d8acd0b..52d9b0f 100644 --- a/src/knot/zone/zonedb-load.c +++ b/src/knot/zone/zonedb-load.c @@ -510,7 +510,7 @@ static knot_zonedb_t *create_zonedb(conf_t *conf, server_t *server, reload_t mod if (forw == NULL) { knot_dname_txt_storage_t forw_str; (void)knot_dname_to_str(forw_str, forw_name, sizeof(forw_str)); - log_zone_warning(z->name, "zone to reverse %s doesn't exist", + log_zone_warning(z->name, "zone to reverse %s does not exist", forw_str); } else { z->reverse_from = forw; @@ -587,6 +587,12 @@ catalog_only: } } +// UBSAN type punning workaround +static void zone_contents_deep_free_wrap(void *contents) +{ + zone_contents_deep_free((zone_contents_t *)contents); +} + void zonedb_reload(conf_t *conf, server_t *server, reload_t mode) { if (conf == NULL || server == NULL) { @@ -625,7 +631,7 @@ void zonedb_reload(conf_t *conf, server_t *server, reload_t mode) /* Wait for readers to finish reading old zone database. */ synchronize_rcu(); - ptrlist_free_custom(&contents_tofree, NULL, (ptrlist_free_cb)zone_contents_deep_free); + ptrlist_free_custom(&contents_tofree, NULL, zone_contents_deep_free_wrap); /* Remove old zone DB. */ remove_old_zonedb(conf, db_old, server, mode); diff --git a/src/knot/zone/zonedb.c b/src/knot/zone/zonedb.c index 98cade5..b0388c7 100644 --- a/src/knot/zone/zonedb.c +++ b/src/knot/zone/zonedb.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -153,7 +153,7 @@ zone_t *knot_zonedb_find_suffix(knot_zonedb_t *db, const knot_dname_t *zone_name return NULL; } - zone_name = knot_wire_next_label(zone_name, NULL); + zone_name = knot_dname_next_label(zone_name); } } diff --git a/src/knot/zone/zonefile.c b/src/knot/zone/zonefile.c index ed075b6..9d0bf97 100644 --- a/src/knot/zone/zonefile.c +++ b/src/knot/zone/zonefile.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -81,12 +81,6 @@ int zcreator_step(zcreator_t *zc, const knot_rrset_t *rr) return KNOT_EINVAL; } - if (rr->type == KNOT_RRTYPE_SOA && - node_rrtype_exists(zc->z->apex, KNOT_RRTYPE_SOA)) { - // Ignore extra SOA - return KNOT_EOK; - } - zone_node_t *node = NULL; int ret = zone_contents_add_rr(zc->z, rr, &node); if (ret != KNOT_EOK) { @@ -219,10 +213,11 @@ zone_contents_t *zonefile_load(zloader_t *loader) goto fail; } - if (!node_rrtype_exists(loader->creator->z->apex, KNOT_RRTYPE_SOA)) { + knot_rdataset_t *soa = node_rdataset(zc->z->apex, KNOT_RRTYPE_SOA); + if (soa == NULL || soa->count != 1) { + sem_error_t code = (soa == NULL) ? SEM_ERR_SOA_NONE : SEM_ERR_SOA_MULTIPLE; loader->err_handler->error = true; - loader->err_handler->cb(loader->err_handler, zc->z, NULL, - SEM_ERR_SOA_NONE, NULL); + loader->err_handler->cb(loader->err_handler, zc->z, NULL, code, NULL); goto fail; } diff --git a/src/libdnssec/key/algorithm.c b/src/libdnssec/key/algorithm.c index a9bc3ee..d242442 100644 --- a/src/libdnssec/key/algorithm.c +++ b/src/libdnssec/key/algorithm.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -93,11 +93,9 @@ gnutls_pk_algorithm_t algorithm_to_gnutls(dnssec_key_algorithm_t dnssec) return GNUTLS_PK_RSA; case DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256: case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384: - return GNUTLS_PK_EC; -#ifdef HAVE_ED25519 + return GNUTLS_PK_ECDSA; case DNSSEC_KEY_ALGORITHM_ED25519: return GNUTLS_PK_EDDSA_ED25519; -#endif #ifdef HAVE_ED448 case DNSSEC_KEY_ALGORITHM_ED448: return GNUTLS_PK_EDDSA_ED448; @@ -119,11 +117,7 @@ bool dnssec_algorithm_reproducible(dnssec_key_algorithm_t algorithm, bool enable return true; // those are always reproducible case DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256: case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384: -#ifdef HAVE_GNUTLS_REPRODUCIBLE - return enabled; // Reproducible only if GnuTLS supports && enabled -#else - return false; -#endif + return enabled; // reproducible only if GnuTLS supports && enabled default: return false; } diff --git a/src/libdnssec/key/convert.c b/src/libdnssec/key/convert.c index 56168f7..d06c25e 100644 --- a/src/libdnssec/key/convert.c +++ b/src/libdnssec/key/convert.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -104,20 +104,16 @@ static size_t ecdsa_curve_point_size(gnutls_ecc_curve_t curve) } } -#if defined(HAVE_ED25519) || defined(HAVE_ED448) static size_t eddsa_curve_point_size(gnutls_ecc_curve_t curve) { switch (curve) { -#ifdef HAVE_ED25519 case GNUTLS_ECC_CURVE_ED25519: return 32; -#endif #ifdef HAVE_ED448 case GNUTLS_ECC_CURVE_ED448: return 57; #endif default: return 0; } } -#endif /*! * Convert ECDSA public key to DNSSEC format. @@ -157,7 +153,6 @@ static int ecdsa_pubkey_to_rdata(gnutls_pubkey_t key, dnssec_binary_t *rdata) /*! * Convert EDDSA public key to DNSSEC format. */ -#if defined(HAVE_ED25519) || defined(HAVE_ED448) static int eddsa_pubkey_to_rdata(gnutls_pubkey_t key, dnssec_binary_t *rdata) { assert(key); @@ -187,7 +182,6 @@ static int eddsa_pubkey_to_rdata(gnutls_pubkey_t key, dnssec_binary_t *rdata) return DNSSEC_EOK; } -#endif /* -- crypto to DNSSEC ------------------------------------------------------*/ @@ -248,20 +242,16 @@ static gnutls_ecc_curve_t ecdsa_curve_from_rdata_size(size_t rdata_size) /*! * Get EDDSA curve based on DNSKEY RDATA size. */ -#if defined(HAVE_ED25519) || defined(HAVE_ED448) static gnutls_ecc_curve_t eddsa_curve_from_rdata_size(size_t rdata_size) { switch (rdata_size) { -#ifdef HAVE_ED25519 case 32: return GNUTLS_ECC_CURVE_ED25519; -#endif #ifdef HAVE_ED448 case 57: return GNUTLS_ECC_CURVE_ED448; #endif default: return GNUTLS_ECC_CURVE_INVALID; } } -#endif /*! * Convert ECDSA key in DNSSEC format to crypto key. @@ -296,7 +286,6 @@ static int ecdsa_rdata_to_pubkey(const dnssec_binary_t *rdata, gnutls_pubkey_t k /*! * Convert EDDSA key in DNSSEC format to crypto key. */ -#if defined(HAVE_ED25519) || defined(HAVE_ED448) static int eddsa_rdata_to_pubkey(const dnssec_binary_t *rdata, gnutls_pubkey_t key) { assert(rdata); @@ -320,7 +309,6 @@ static int eddsa_rdata_to_pubkey(const dnssec_binary_t *rdata, gnutls_pubkey_t k return DNSSEC_EOK; } -#endif /* -- internal API --------------------------------------------------------- */ @@ -339,10 +327,8 @@ int convert_pubkey_to_dnskey(gnutls_pubkey_t key, dnssec_binary_t *rdata) switch ((gnutls_pk_algorithm_t)algorithm) { case GNUTLS_PK_RSA: return rsa_pubkey_to_rdata(key, rdata); - case GNUTLS_PK_EC: return ecdsa_pubkey_to_rdata(key, rdata); -#ifdef HAVE_ED25519 + case GNUTLS_PK_ECDSA: return ecdsa_pubkey_to_rdata(key, rdata); case GNUTLS_PK_EDDSA_ED25519: return eddsa_pubkey_to_rdata(key, rdata); -#endif #ifdef HAVE_ED448 case GNUTLS_PK_EDDSA_ED448: return eddsa_pubkey_to_rdata(key, rdata); #endif @@ -363,10 +349,8 @@ int convert_dnskey_to_pubkey(uint8_t algorithm, const dnssec_binary_t *rdata, switch(gnutls_alg) { case GNUTLS_PK_RSA: return rsa_rdata_to_pubkey(rdata, key); - case GNUTLS_PK_EC: return ecdsa_rdata_to_pubkey(rdata, key); -#ifdef HAVE_ED25519 + case GNUTLS_PK_ECDSA: return ecdsa_rdata_to_pubkey(rdata, key); case GNUTLS_PK_EDDSA_ED25519: return eddsa_rdata_to_pubkey(rdata, key); -#endif #ifdef HAVE_ED448 case GNUTLS_PK_EDDSA_ED448: return eddsa_rdata_to_pubkey(rdata, key); #endif diff --git a/src/libdnssec/pem.c b/src/libdnssec/pem.c index fa463f6..41fd855 100644 --- a/src/libdnssec/pem.c +++ b/src/libdnssec/pem.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -130,29 +130,10 @@ int dnssec_pem_from_x509(gnutls_x509_privkey_t key, dnssec_binary_t *pem) static int privkey_export_x509(gnutls_privkey_t key, gnutls_x509_privkey_t *_key) { -#ifdef HAVE_EXPORT_X509 if (gnutls_privkey_export_x509(key, _key) != GNUTLS_E_SUCCESS) { return DNSSEC_KEY_EXPORT_ERROR; } -#else // Needed for GnuTLS < 3.4.0 (CentOS 7) - struct privkey { // Extracted needed items only! - gnutls_privkey_type_t type; - gnutls_pk_algorithm_t pk_algorithm; - gnutls_x509_privkey_t x509; - }; - struct privkey *pkey = (struct privkey *)key; - assert(pkey->type == GNUTLS_PRIVKEY_X509); - - if (gnutls_x509_privkey_init(_key) != GNUTLS_E_SUCCESS) { - return DNSSEC_KEY_EXPORT_ERROR; - } - - if (gnutls_x509_privkey_cpy(*_key, pkey->x509) != GNUTLS_E_SUCCESS) { - gnutls_x509_privkey_deinit(*_key); - return DNSSEC_KEY_EXPORT_ERROR; - } -#endif return DNSSEC_EOK; } diff --git a/src/libdnssec/sign/sign.c b/src/libdnssec/sign/sign.c index 3a7bcba..727f650 100644 --- a/src/libdnssec/sign/sign.c +++ b/src/libdnssec/sign/sign.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -202,34 +202,6 @@ static const algorithm_functions_t *get_functions(const dnssec_key_t *key) } } -#ifndef HAVE_SIGN_DATA2 -/*! - * Get digest algorithm used with a given key. - */ -static gnutls_digest_algorithm_t get_digest_algorithm(const dnssec_key_t *key) -{ - uint8_t algorithm = dnssec_key_get_algorithm(key); - - switch ((dnssec_key_algorithm_t)algorithm) { - case DNSSEC_KEY_ALGORITHM_RSA_SHA1: - case DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3: - return GNUTLS_DIG_SHA1; - case DNSSEC_KEY_ALGORITHM_RSA_SHA256: - case DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256: - return GNUTLS_DIG_SHA256; - case DNSSEC_KEY_ALGORITHM_RSA_SHA512: - return GNUTLS_DIG_SHA512; - case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384: - return GNUTLS_DIG_SHA384; - case DNSSEC_KEY_ALGORITHM_ED25519: - case DNSSEC_KEY_ALGORITHM_ED448: - return GNUTLS_DIG_SHA512; - default: - return GNUTLS_DIG_UNKNOWN; - } -} -#endif - static gnutls_sign_algorithm_t algo_dnssec2gnutls(dnssec_key_algorithm_t algorithm) { switch (algorithm) { @@ -244,10 +216,8 @@ static gnutls_sign_algorithm_t algo_dnssec2gnutls(dnssec_key_algorithm_t algorit return GNUTLS_SIGN_RSA_SHA512; case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384: return GNUTLS_SIGN_ECDSA_SHA384; -#ifdef HAVE_ED25519 case DNSSEC_KEY_ALGORITHM_ED25519: return GNUTLS_SIGN_EDDSA_ED25519; -#endif #ifdef HAVE_ED448 case DNSSEC_KEY_ALGORITHM_ED448: return GNUTLS_SIGN_EDDSA_ED448; @@ -356,24 +326,15 @@ int dnssec_sign_write(dnssec_sign_ctx_t *ctx, dnssec_sign_flags_t flags, dnssec_ }; unsigned gnutls_flags = 0; -#ifdef HAVE_GNUTLS_REPRODUCIBLE if (flags & DNSSEC_SIGN_REPRODUCIBLE) { gnutls_flags |= GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE; } -#endif assert(ctx->key->private_key); _cleanup_datum_ gnutls_datum_t raw = { 0 }; -#ifdef HAVE_SIGN_DATA2 int result = gnutls_privkey_sign_data2(ctx->key->private_key, ctx->sign_algorithm, gnutls_flags, &data, &raw); -#else - gnutls_digest_algorithm_t digest_algorithm = get_digest_algorithm(ctx->key); - int result = gnutls_privkey_sign_data(ctx->key->private_key, - digest_algorithm, - gnutls_flags, &data, &raw); -#endif if (result < 0) { return DNSSEC_SIGN_ERROR; } diff --git a/src/libdnssec/version.h b/src/libdnssec/version.h index e72e2bd..cd5bad2 100644 --- a/src/libdnssec/version.h +++ b/src/libdnssec/version.h @@ -17,8 +17,8 @@ #pragma once #define DNSSEC_VERSION_MAJOR 3 -#define DNSSEC_VERSION_MINOR 3 -#define DNSSEC_VERSION_PATCH 0x09 +#define DNSSEC_VERSION_MINOR 4 +#define DNSSEC_VERSION_PATCH 0x00 #define DNSSEC_VERSION_HEX ((DNSSEC_VERSION_MAJOR << 16) | \ (DNSSEC_VERSION_MINOR << 8) | \ diff --git a/src/libknot/Makefile.inc b/src/libknot/Makefile.inc index f62d836..d09ff55 100755 --- a/src/libknot/Makefile.inc +++ b/src/libknot/Makefile.inc @@ -37,6 +37,8 @@ nobase_include_libknot_HEADERS = \ libknot/packet/wire.h \ libknot/probe/data.h \ libknot/probe/probe.h \ + libknot/quic/tls.h \ + libknot/quic/tls_common.h \ libknot/rdata.h \ libknot/rdataset.h \ libknot/rrset-dump.h \ @@ -78,6 +80,8 @@ libknot_la_SOURCES = \ libknot/packet/rrset-wire.c \ libknot/probe/data.c \ libknot/probe/probe.c \ + libknot/quic/tls.c \ + libknot/quic/tls_common.c \ libknot/rdataset.c \ libknot/rrset-dump.c \ libknot/rrset.c \ diff --git a/src/libknot/attribute.h b/src/libknot/attribute.h index 525aef3..ce464fc 100644 --- a/src/libknot/attribute.h +++ b/src/libknot/attribute.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,17 +35,19 @@ /*! \brief GNU C function attributes. */ #if __GNUC__ >= 3 -#define _pure_ __attribute__ ((pure)) -#define _const_ __attribute__ ((const)) -#define _noreturn_ __attribute__ ((noreturn)) -#define _malloc_ __attribute__ ((malloc)) -#define _mustcheck_ __attribute__ ((warn_unused_result)) +#define _pure_ __attribute__ ((pure)) +#define _const_ __attribute__ ((const)) +#define _noreturn_ __attribute__ ((noreturn)) +#define _malloc_ __attribute__ ((malloc)) +#define _mustcheck_ __attribute__ ((warn_unused_result)) +#define _nonnull_(...) __attribute__ ((nonnull(__VA_ARGS__))) #else #define _pure_ #define _const_ #define _noreturn_ #define _malloc_ #define _mustcheck_ +#define _nonnull_ #endif /*! @} */ diff --git a/src/libknot/control/control.c b/src/libknot/control/control.c index 671896f..8cddd5d 100644 --- a/src/libknot/control/control.c +++ b/src/libknot/control/control.c @@ -36,9 +36,6 @@ #define CTL_BUFF_SIZE (256 * 1024) #endif -/*! Listen backlog size. */ -#define DEFAULT_LISTEN_BACKLOG 5 - /*! Default socket operations timeout in milliseconds. */ #define DEFAULT_TIMEOUT (30 * 1000) @@ -165,6 +162,18 @@ knot_ctl_t* knot_ctl_alloc(void) return ctx; } +_public_ +knot_ctl_t* knot_ctl_clone(knot_ctl_t *ctx) +{ + knot_ctl_t *res = knot_ctl_alloc(); + if (res != NULL) { + res->timeout = ctx->timeout; + res->sock = ctx->sock; + ctx->sock = -1; + } + return res; +} + _public_ void knot_ctl_free(knot_ctl_t *ctx) { @@ -194,13 +203,7 @@ void knot_ctl_set_timeout(knot_ctl_t *ctx, int timeout_ms) } _public_ -int knot_ctl_bind(knot_ctl_t *ctx, const char *path) -{ - return knot_ctl_bind2(ctx, path, DEFAULT_LISTEN_BACKLOG); -} - -_public_ -int knot_ctl_bind2(knot_ctl_t *ctx, const char *path, unsigned backlog) +int knot_ctl_bind(knot_ctl_t *ctx, const char *path, unsigned backlog) { if (ctx == NULL || path == NULL) { return KNOT_EINVAL; diff --git a/src/libknot/control/control.h b/src/libknot/control/control.h index 8ab1e10..f110e3f 100644 --- a/src/libknot/control/control.h +++ b/src/libknot/control/control.h @@ -64,6 +64,18 @@ typedef struct knot_ctl knot_ctl_t; */ knot_ctl_t* knot_ctl_alloc(void); +/*! + * \brief Allocates a control context based on an existing one. + * + * \param[in,out] ctx Original control context. + * + * \note The listen_sock is kept at the original, the current sock is taken + * by the clone and RESET in the original! + * + * \return Control context or NULL. + */ +knot_ctl_t* knot_ctl_clone(knot_ctl_t *ctx); + /*! * Deallocates a control context. * @@ -86,17 +98,13 @@ void knot_ctl_set_timeout(knot_ctl_t *ctx, int timeout_ms); * * \note Server operation. * - * \param[in] ctx Control context. - * \param[in] path Control UNIX socket path. + * \param[in] ctx Control context. + * \param[in] path Control UNIX socket path. + * \param[in] backlog Socket listen backlog size. * * \return Error code, KNOT_EOK if successful. */ -int knot_ctl_bind(knot_ctl_t *ctx, const char *path); - -/*! - * Same as knot_ctl_bind() with socket backlog specification. - */ -int knot_ctl_bind2(knot_ctl_t *ctx, const char *path, unsigned backlog); +int knot_ctl_bind(knot_ctl_t *ctx, const char *path, unsigned backlog); /*! * Unbinds a control socket. diff --git a/src/libknot/dname.c b/src/libknot/dname.c index 31b8a5f..d166f8d 100644 --- a/src/libknot/dname.c +++ b/src/libknot/dname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -62,11 +62,11 @@ static int dname_align(const uint8_t **d1, uint8_t d1_labels, assert(d1 && d2); for (unsigned j = d1_labels; j < d2_labels; ++j) { - *d2 = knot_wire_next_label(*d2, NULL); + *d2 = knot_dname_next_label(*d2); } for (unsigned j = d2_labels; j < d1_labels; ++j) { - *d1 = knot_wire_next_label(*d1, NULL); + *d1 = knot_dname_next_label(*d1); } return (d1_labels < d2_labels) ? d1_labels : d2_labels; @@ -190,7 +190,7 @@ _public_ int knot_dname_unpack(uint8_t *dst, const knot_dname_t *src, size_t maxlen, const uint8_t *pkt) { - if (dst == NULL || src == NULL) { + if (dst == NULL || src == NULL || pkt == NULL) { return KNOT_EINVAL; } @@ -533,7 +533,7 @@ size_t knot_dname_size(const knot_dname_t *name) _public_ size_t knot_dname_realsize(const knot_dname_t *name, const uint8_t *pkt) { - if (name == NULL) { + if (name == NULL || pkt == NULL) { return 0; } @@ -573,8 +573,8 @@ size_t knot_dname_matched_labels(const knot_dname_t *d1, const knot_dname_t *d2) } /* Next label. */ - d1 = knot_wire_next_label(d1, NULL); - d2 = knot_wire_next_label(d2, NULL); + d1 = knot_dname_next_label(d1); + d2 = knot_dname_next_label(d2); --common; } @@ -596,7 +596,7 @@ knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name, unsigned label } size_t prefix_lbs = dname_lbs - labels; - size_t prefix_len = knot_dname_prefixlen(name, prefix_lbs, NULL); + size_t prefix_len = knot_dname_prefixlen(name, prefix_lbs); size_t suffix_len = knot_dname_size(suffix); if (prefix_len == 0 || suffix_len == 0) { return NULL; @@ -614,7 +614,7 @@ knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name, unsigned label while (prefix_lbs > 0) { memcpy(dst, name, *name + 1); dst += *name + 1; - name = knot_wire_next_label(name, NULL); + name = knot_dname_next_label(name); --prefix_lbs; } @@ -622,7 +622,7 @@ knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name, unsigned label while (*suffix != '\0') { memcpy(dst, suffix, *suffix + 1); dst += *suffix + 1; - suffix = knot_wire_next_label(suffix, NULL); + suffix = knot_dname_next_label(suffix); } *dst = '\0'; @@ -684,8 +684,8 @@ inline static bool dname_is_equal(const knot_dname_t *d1, const knot_dname_t *d2 while (*d1 != '\0' || *d2 != '\0') { if (label_is_equal(d1, d2, no_case)) { - d1 = knot_wire_next_label(d1, NULL); - d2 = knot_wire_next_label(d2, NULL); + d1 = knot_dname_next_label(d1); + d2 = knot_dname_next_label(d2); } else { return false; } @@ -707,7 +707,7 @@ bool knot_dname_is_case_equal(const knot_dname_t *d1, const knot_dname_t *d2) } _public_ -size_t knot_dname_prefixlen(const uint8_t *name, unsigned nlabels, const uint8_t *pkt) +size_t knot_dname_prefixlen(const uint8_t *name, unsigned nlabels) { if (name == NULL) { return 0; @@ -718,13 +718,10 @@ size_t knot_dname_prefixlen(const uint8_t *name, unsigned nlabels, const uint8_t return 0; } - /* Seek first real label occurrence. */ - name = knot_wire_seek_label(name, pkt); - size_t len = 0; while (*name != '\0') { len += *name + 1; - name = knot_wire_next_label(name, pkt); + name = knot_dname_next_label(name); if (--nlabels == 0) { /* Count N first labels only. */ break; } @@ -743,7 +740,8 @@ size_t knot_dname_labels(const uint8_t *name, const uint8_t *pkt) size_t count = 0; while (*name != '\0') { ++count; - name = knot_wire_next_label(name, pkt); + name = (pkt == NULL) ? knot_dname_next_label(name) : + knot_wire_next_label(name, pkt); if (name == NULL) { return 0; } @@ -794,7 +792,7 @@ int knot_dname_in_bailiwick(const knot_dname_t *name, const knot_dname_t *bailiw } for (int i = 0; i < label_diff; ++i) { - name = knot_wire_next_label(name, NULL); + name = knot_dname_next_label(name); } return knot_dname_is_equal(name, bailiwick) ? label_diff : KNOT_EOUTOFZONE; diff --git a/src/libknot/dname.h b/src/libknot/dname.h index 5733de9..6d72f90 100644 --- a/src/libknot/dname.h +++ b/src/libknot/dname.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -48,7 +48,7 @@ typedef char knot_dname_txt_storage_t[KNOT_DNAME_TXT_MAXLEN + 1]; * * \param name Name on the wire. * \param endp Name boundary. - * \param pkt Wire. + * \param pkt Wire (can be NULL if not compressed). * * \retval (compressed) size of the domain name. * \retval KNOT_EINVAL @@ -195,7 +195,7 @@ size_t knot_dname_size(const knot_dname_t *name); * \brief Returns full size of the given domain name (expanded compression ptrs). * * \param name Domain name to get the size of. - * \param pkt Related packet (or NULL if unpacked) + * \param pkt Related packet. * * \retval size of the domain name. * \retval 0 if invalid argument. @@ -295,12 +295,11 @@ bool knot_dname_is_case_equal(const knot_dname_t *d1, const knot_dname_t *d2); * * \param name Domain name. * \param nlabels First N labels. - * \param pkt Related packet (or NULL if not compressed). * * \return Length of the prefix. */ _pure_ -size_t knot_dname_prefixlen(const uint8_t *name, unsigned nlabels, const uint8_t *pkt); +size_t knot_dname_prefixlen(const uint8_t *name, unsigned nlabels); /*! * \brief Return number of labels in the domain name. diff --git a/src/libknot/errcode.h b/src/libknot/errcode.h index 6ec4a94..3ee326c 100644 --- a/src/libknot/errcode.h +++ b/src/libknot/errcode.h @@ -110,6 +110,7 @@ enum knot_error { KNOT_EBADCERTKEY, KNOT_EFACCES, KNOT_EBACKUPDATA, + KNOT_ECPUCOMPAT, KNOT_GENERAL_ERROR = -900, @@ -121,6 +122,7 @@ enum knot_error { KNOT_NET_EADDR, KNOT_NET_ESOCKET, KNOT_NET_ECONNECT, + KNOT_NET_EHSHAKE, KNOT_NET_ESEND, KNOT_NET_ERECV, KNOT_NET_ETIMEOUT, @@ -176,6 +178,7 @@ enum knot_error { KNOT_NO_PUBLIC_KEY, KNOT_NO_PRIVATE_KEY, KNOT_NO_READY_KEY, + KNOT_ESOON_EXPIRE, KNOT_DNSSEC_EKEYTAG_LIMIT, KNOT_DNSSEC_EXTRA_NSEC, diff --git a/src/libknot/error.c b/src/libknot/error.c index ae9b973..59f0a7a 100644 --- a/src/libknot/error.c +++ b/src/libknot/error.c @@ -109,6 +109,7 @@ static const struct error errors[] = { { KNOT_EBADCERTKEY, "unknown certificate key" }, { KNOT_EFACCES, "file permission denied" }, { KNOT_EBACKUPDATA, "requested data not in backup" }, + { KNOT_ECPUCOMPAT, "incompatible CPU architecture" }, { KNOT_GENERAL_ERROR, "unknown general error" }, @@ -120,6 +121,7 @@ static const struct error errors[] = { { KNOT_NET_EADDR, "bad address or host name" }, { KNOT_NET_ESOCKET, "can't create socket" }, { KNOT_NET_ECONNECT, "can't connect" }, + { KNOT_NET_EHSHAKE, "handshake failed" }, { KNOT_NET_ESEND, "can't send data" }, { KNOT_NET_ERECV, "can't receive data" }, { KNOT_NET_ETIMEOUT, "network timeout" }, @@ -175,6 +177,7 @@ static const struct error errors[] = { { KNOT_NO_PUBLIC_KEY, "no public key" }, { KNOT_NO_PRIVATE_KEY, "no private key" }, { KNOT_NO_READY_KEY, "no key ready for submission" }, + { KNOT_ESOON_EXPIRE, "oncoming RRSIG expiration" }, { KNOT_DNSSEC_EKEYTAG_LIMIT, "many keys with equal keytag" }, { KNOT_DNSSEC_EXTRA_NSEC, "superfluous NSEC(3)" }, diff --git a/src/libknot/packet/pkt.h b/src/libknot/packet/pkt.h index 383f55e..da69c8c 100644 --- a/src/libknot/packet/pkt.h +++ b/src/libknot/packet/pkt.h @@ -52,7 +52,6 @@ enum { KNOT_PF_NOCANON = 1 << 5, /*!< Don't canonicalize rrsets during parsing. */ KNOT_PF_ORIGTTL = 1 << 6, /*!< Write RRSIGs with their original TTL. */ KNOT_PF_SOAMINTTL = 1 << 7, /*!< Write SOA with its minimum-ttl as TTL. */ - KNOT_PF_BUFENOUGH = 1 << 8, /*!< The output buffer is big enough for the output. */ }; typedef struct knot_pkt knot_pkt_t; diff --git a/src/libknot/packet/rrset-wire.c b/src/libknot/packet/rrset-wire.c index ef3a068..1d4f78e 100644 --- a/src/libknot/packet/rrset-wire.c +++ b/src/libknot/packet/rrset-wire.c @@ -73,6 +73,7 @@ static bool dname_equal_wire(const knot_dname_t *d1, const knot_dname_t *d2, { assert(d1); assert(d2); + assert(wire); d2 = knot_wire_seek_label(d2, wire); @@ -80,7 +81,7 @@ static bool dname_equal_wire(const knot_dname_t *d1, const knot_dname_t *d2, if (!label_is_equal(d1, d2)) { return false; } - d1 = knot_wire_next_label(d1, NULL); + d1 = knot_dname_next_label(d1); d2 = knot_wire_next_label(d2, wire); } @@ -170,7 +171,7 @@ static int write_rdata_naptr_header(const uint8_t **src, size_t *src_avail, written += (len); \ } -#define CHECK_NEXT_LABEL(res) \ +#define CHECK_WIRE_NEXT_LABEL(res) \ if (res == NULL) { return KNOT_EINVAL; } /*! @@ -201,7 +202,7 @@ static int compr_put_dname(const knot_dname_t *dname, uint8_t *dst, uint16_t max int suffix_labels = compr->suffix.labels; while (suffix_labels > name_labels) { suffix = knot_wire_next_label(suffix, compr->wire); - CHECK_NEXT_LABEL(suffix); + CHECK_WIRE_NEXT_LABEL(suffix); --suffix_labels; } @@ -210,8 +211,7 @@ static int compr_put_dname(const knot_dname_t *dname, uint8_t *dst, uint16_t max uint16_t written = 0; while (name_labels > suffix_labels) { WRITE_LABEL(dst, written, dname, max, (*dname + 1)); - dname = knot_wire_next_label(dname, NULL); - CHECK_NEXT_LABEL(dname); + dname = knot_dname_next_label(dname); --name_labels; } @@ -221,10 +221,9 @@ static int compr_put_dname(const knot_dname_t *dname, uint8_t *dst, uint16_t max const knot_dname_t *compr_ptr = suffix; while (dname[0] != '\0') { // Next labels. - const knot_dname_t *next_dname = knot_wire_next_label(dname, NULL); - CHECK_NEXT_LABEL(next_dname); + const knot_dname_t *next_dname = knot_dname_next_label(dname); const knot_dname_t *next_suffix = knot_wire_next_label(suffix, compr->wire); - CHECK_NEXT_LABEL(next_suffix); + CHECK_WIRE_NEXT_LABEL(next_suffix); // Two labels match, extend suffix length. if (!label_is_equal(dname, suffix)) { @@ -495,7 +494,7 @@ static int write_rr(const knot_rrset_t *rrset, uint16_t rrset_index, _public_ int knot_rrset_to_wire_extra(const knot_rrset_t *rrset, uint8_t *wire, - uint16_t max_size, uint16_t rotate, + uint32_t max_size, uint16_t rotate, knot_compr_t *compr, uint16_t flags) { if (rrset == NULL || wire == NULL) { @@ -511,11 +510,6 @@ int knot_rrset_to_wire_extra(const knot_rrset_t *rrset, uint8_t *wire, uint8_t *write = wire; size_t capacity = max_size; - // FIXME remove this and make the max_size parameter uint32_t in next major libknot release! - if ((flags & KNOT_PF_BUFENOUGH)) { - capacity = SIZE_MAX; - } - uint16_t count = rrset->rrs.count; knot_rdata_t *rdata = rotate > 1 ? knot_rdataset_at(&rrset->rrs, rotate - 1) : rrset->rrs.rdata; for (int i = rotate; i < count + rotate; i++) { diff --git a/src/libknot/packet/rrset-wire.h b/src/libknot/packet/rrset-wire.h index 3be0cba..3247df8 100644 --- a/src/libknot/packet/rrset-wire.h +++ b/src/libknot/packet/rrset-wire.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -41,12 +41,12 @@ * \return Output size, negative number on error (KNOT_E*). */ int knot_rrset_to_wire_extra(const knot_rrset_t *rrset, uint8_t *wire, - uint16_t max_size, uint16_t rotate, + uint32_t max_size, uint16_t rotate, knot_compr_t *compr, uint16_t flags); /*! \brief Same as knot_rrset_to_wire_extra but without rrset rotation and flags. */ static inline int knot_rrset_to_wire(const knot_rrset_t *rrset, uint8_t *wire, - uint16_t max_size, knot_compr_t *compr) + uint32_t max_size, knot_compr_t *compr) { return knot_rrset_to_wire_extra(rrset, wire, max_size, 0, compr, 0); } diff --git a/src/libknot/packet/wire.h b/src/libknot/packet/wire.h index 630cd83..cff4b21 100644 --- a/src/libknot/packet/wire.h +++ b/src/libknot/packet/wire.h @@ -1025,13 +1025,11 @@ static inline uint16_t knot_wire_get_pointer(const uint8_t *pos) return (knot_wire_read_u16(pos) - KNOT_WIRE_PTR_BASE); // Return offset. } -_pure_ _mustcheck_ +_pure_ _mustcheck_ _nonnull_(2) static inline const uint8_t *knot_wire_seek_label(const uint8_t *lp, const uint8_t *wire) { + assert(wire); while (knot_wire_is_pointer(lp)) { - if (!wire) { - return NULL; - } const uint8_t *new_lp = wire + knot_wire_get_pointer(lp); if (new_lp >= lp) { assert(0); @@ -1042,12 +1040,21 @@ static inline const uint8_t *knot_wire_seek_label(const uint8_t *lp, const uint8 return lp; } -_pure_ _mustcheck_ +_pure_ _mustcheck_ _nonnull_(1, 2) static inline const uint8_t *knot_wire_next_label(const uint8_t *lp, const uint8_t *wire) { - if (!lp || !lp[0]) /* No label after final label. */ - return NULL; + assert(lp); + assert(lp[0] > 0); // Not a terminal label. return knot_wire_seek_label(lp + (lp[0] + sizeof(uint8_t)), wire); } +_pure_ _mustcheck_ _nonnull_(1) +static inline const uint8_t *knot_dname_next_label(const uint8_t *lp) +{ + assert(lp); + assert(lp[0] > 0); // Not a terminal label. + assert(!knot_wire_is_pointer(lp)); + return lp + (lp[0] + sizeof(uint8_t)); +} + /*! @} */ diff --git a/src/libknot/quic/quic.c b/src/libknot/quic/quic.c index f9d1d1d..4eb84c3 100644 --- a/src/libknot/quic/quic.c +++ b/src/libknot/quic/quic.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,7 +33,6 @@ #include "contrib/macros.h" #include "contrib/sockaddr.h" -#include "contrib/string.h" #include "contrib/ucw/lists.h" #include "libknot/endian.h" #include "libdnssec/error.h" @@ -58,19 +57,6 @@ #define TLS_CALLBACK_ERR (-1) -const gnutls_datum_t doq_alpn = { - (unsigned char *)"doq", 3 -}; - -typedef struct knot_quic_creds { - gnutls_certificate_credentials_t tls_cert; - gnutls_anti_replay_t tls_anti_replay; - gnutls_datum_t tls_ticket_key; - bool peer; - uint8_t peer_pin_len; - uint8_t peer_pin[]; -} knot_quic_creds_t; - typedef struct knot_quic_session { node_t n; gnutls_datum_t tls_session; @@ -153,223 +139,6 @@ session_free: return ret; } -static int tls_anti_replay_db_add_func(void *dbf, time_t exp_time, - const gnutls_datum_t *key, - const gnutls_datum_t *data) -{ - return 0; -} - -static void tls_session_ticket_key_free(gnutls_datum_t *ticket) -{ - gnutls_memset(ticket->data, 0, ticket->size); - gnutls_free(ticket->data); -} - -static int self_key(gnutls_x509_privkey_t *privkey, const char *key_file) -{ - gnutls_datum_t data = { 0 }; - - int ret = gnutls_x509_privkey_init(privkey); - if (ret != GNUTLS_E_SUCCESS) { - return ret; - } - - int fd = open(key_file, O_RDONLY); - if (fd != -1) { - struct stat stat; - if (fstat(fd, &stat) != 0 || - (data.data = gnutls_malloc(stat.st_size)) == NULL || - read(fd, data.data, stat.st_size) != stat.st_size) { - ret = GNUTLS_E_KEYFILE_ERROR; - goto finish; - } - - data.size = stat.st_size; - ret = gnutls_x509_privkey_import_pkcs8(*privkey, &data, GNUTLS_X509_FMT_PEM, - NULL, GNUTLS_PKCS_PLAIN); - if (ret != GNUTLS_E_SUCCESS) { - goto finish; - } - } else { - ret = gnutls_x509_privkey_generate(*privkey, GNUTLS_PK_EDDSA_ED25519, - GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_ED25519), 0); - if (ret != GNUTLS_E_SUCCESS) { - goto finish; - } - - ret = gnutls_x509_privkey_export2_pkcs8(*privkey, GNUTLS_X509_FMT_PEM, NULL, - GNUTLS_PKCS_PLAIN, &data); - if (ret != GNUTLS_E_SUCCESS || - (fd = open(key_file, O_WRONLY | O_CREAT, 0600)) == -1 || - write(fd, data.data, data.size) != data.size) { - ret = GNUTLS_E_KEYFILE_ERROR; - goto finish; - } - } - -finish: - close(fd); - gnutls_free(data.data); - if (ret != GNUTLS_E_SUCCESS) { - gnutls_x509_privkey_deinit(*privkey); - *privkey = NULL; - } - return ret; -} - -static int self_signed_cert(gnutls_certificate_credentials_t tls_cert, - const char *key_file) -{ - gnutls_x509_privkey_t privkey = NULL; - gnutls_x509_crt_t cert = NULL; - - char *hostname = sockaddr_hostname(); - if (hostname == NULL) { - return GNUTLS_E_MEMORY_ERROR; - } - - int ret; - uint8_t serial[16]; - gnutls_rnd(GNUTLS_RND_NONCE, serial, sizeof(serial)); - // Clear the left-most bit to be a positive number (two's complement form). - serial[0] &= 0x7F; - -#define CHK(cmd) if ((ret = (cmd)) != GNUTLS_E_SUCCESS) { goto finish; } -#define NOW_DAYS(days) (time(NULL) + 24 * 3600 * (days)) - - CHK(self_key(&privkey, key_file)); - - CHK(gnutls_x509_crt_init(&cert)); - CHK(gnutls_x509_crt_set_version(cert, 3)); - CHK(gnutls_x509_crt_set_serial(cert, serial, sizeof(serial))); - CHK(gnutls_x509_crt_set_activation_time(cert, NOW_DAYS(-1))); - CHK(gnutls_x509_crt_set_expiration_time(cert, NOW_DAYS(10 * 365))); - CHK(gnutls_x509_crt_set_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, - hostname, strlen(hostname))); - CHK(gnutls_x509_crt_set_key(cert, privkey)); - CHK(gnutls_x509_crt_sign2(cert, cert, privkey, GNUTLS_DIG_SHA512, 0)); - - ret = gnutls_certificate_set_x509_key(tls_cert, &cert, 1, privkey); - -finish: - free(hostname); - gnutls_x509_crt_deinit(cert); - gnutls_x509_privkey_deinit(privkey); - - return ret; -} - -_public_ -struct knot_quic_creds *knot_quic_init_creds(const char *cert_file, - const char *key_file) -{ - knot_quic_creds_t *creds = calloc(1, sizeof(*creds)); - if (creds == NULL) { - return NULL; - } - - int ret = gnutls_certificate_allocate_credentials(&creds->tls_cert); - if (ret != GNUTLS_E_SUCCESS) { - goto fail; - } - - ret = gnutls_anti_replay_init(&creds->tls_anti_replay); - if (ret != GNUTLS_E_SUCCESS) { - goto fail; - } - gnutls_anti_replay_set_add_function(creds->tls_anti_replay, tls_anti_replay_db_add_func); - gnutls_anti_replay_set_ptr(creds->tls_anti_replay, NULL); - - if (cert_file != NULL) { - ret = gnutls_certificate_set_x509_key_file(creds->tls_cert, - cert_file, key_file, - GNUTLS_X509_FMT_PEM); - } else { - ret = self_signed_cert(creds->tls_cert, key_file); - } - if (ret != GNUTLS_E_SUCCESS) { - goto fail; - } - - ret = gnutls_session_ticket_key_generate(&creds->tls_ticket_key); - if (ret != GNUTLS_E_SUCCESS) { - goto fail; - } - - return creds; -fail: - knot_quic_free_creds(creds); - return NULL; -} - -_public_ -struct knot_quic_creds *knot_quic_init_creds_peer(const struct knot_quic_creds *local_creds, - const uint8_t *peer_pin, - uint8_t peer_pin_len) -{ - knot_quic_creds_t *creds = calloc(1, sizeof(*creds) + peer_pin_len); - if (creds == NULL) { - return NULL; - } - - if (local_creds != NULL) { - creds->peer = true; - creds->tls_cert = local_creds->tls_cert; - } else { - int ret = gnutls_certificate_allocate_credentials(&creds->tls_cert); - if (ret != GNUTLS_E_SUCCESS) { - free(creds); - return NULL; - } - } - - if (peer_pin_len > 0 && peer_pin != NULL) { - memcpy(creds->peer_pin, peer_pin, peer_pin_len); - creds->peer_pin_len = peer_pin_len; - } - - return creds; -} - -_public_ -int knot_quic_creds_cert(struct knot_quic_creds *creds, struct gnutls_x509_crt_int **cert) -{ - if (creds == NULL || cert == NULL) { - return KNOT_EINVAL; - } - - gnutls_x509_crt_t *certs; - unsigned cert_count; - int ret = gnutls_certificate_get_x509_crt(creds->tls_cert, 0, &certs, &cert_count); - if (ret == GNUTLS_E_SUCCESS) { - if (cert_count == 0) { - gnutls_x509_crt_deinit(*certs); - return KNOT_ENOENT; - } - *cert = *certs; - free(certs); - } - return ret; -} - -_public_ -void knot_quic_free_creds(struct knot_quic_creds *creds) -{ - if (creds == NULL) { - return; - } - - if (!creds->peer && creds->tls_cert != NULL) { - gnutls_certificate_free_credentials(creds->tls_cert); - } - gnutls_anti_replay_deinit(creds->tls_anti_replay); - if (creds->tls_ticket_key.data != NULL) { - tls_session_ticket_key_free(&creds->tls_ticket_key); - } - free(creds); -} - static ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref) { return ((knot_quic_conn_t *)conn_ref->user_data)->conn; @@ -377,51 +146,31 @@ static ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref) static int tls_init_conn_session(knot_quic_conn_t *conn, bool server) { - if (gnutls_init(&conn->tls_session, (server ? GNUTLS_SERVER : GNUTLS_CLIENT) | - GNUTLS_ENABLE_EARLY_DATA | GNUTLS_NO_AUTO_SEND_TICKET | - GNUTLS_NO_END_OF_EARLY_DATA) != GNUTLS_E_SUCCESS) { - return TLS_CALLBACK_ERR; - } - - gnutls_certificate_send_x509_rdn_sequence(conn->tls_session, 1); - gnutls_certificate_server_set_request(conn->tls_session, GNUTLS_CERT_REQUEST); - - if (gnutls_priority_set_direct(conn->tls_session, QUIC_PRIORITIES, - NULL) != GNUTLS_E_SUCCESS) { + int ret = knot_tls_session(&conn->tls_session, conn->quic_table->creds, + conn->quic_table->priority, "\x03""doq", + true, server); + if (ret != KNOT_EOK) { return TLS_CALLBACK_ERR; } - if (server && gnutls_session_ticket_enable_server(conn->tls_session, - &conn->quic_table->creds->tls_ticket_key) != GNUTLS_E_SUCCESS) { - return TLS_CALLBACK_ERR; + if (server) { + ret = ngtcp2_crypto_gnutls_configure_server_session(conn->tls_session); + } else { + ret = ngtcp2_crypto_gnutls_configure_client_session(conn->tls_session); } - - int ret = ngtcp2_crypto_gnutls_configure_server_session(conn->tls_session); - if (ret != 0) { + if (ret != NGTCP2_NO_ERROR) { return TLS_CALLBACK_ERR; } - gnutls_record_set_max_early_data_size(conn->tls_session, 0xffffffffu); - conn->conn_ref = (nc_conn_ref_placeholder_t) { .get_conn = get_conn, .user_data = conn }; - _Static_assert(sizeof(nc_conn_ref_placeholder_t) == sizeof(ngtcp2_crypto_conn_ref), "invalid placeholder for conn_ref"); + _Static_assert(sizeof(nc_conn_ref_placeholder_t) == sizeof(ngtcp2_crypto_conn_ref), + "invalid placeholder for conn_ref"); gnutls_session_set_ptr(conn->tls_session, &conn->conn_ref); - if (server) { - gnutls_anti_replay_enable(conn->tls_session, conn->quic_table->creds->tls_anti_replay); - - } - if (gnutls_credentials_set(conn->tls_session, GNUTLS_CRD_CERTIFICATE, - conn->quic_table->creds->tls_cert) != GNUTLS_E_SUCCESS) { - return TLS_CALLBACK_ERR; - } - - gnutls_alpn_set_protocols(conn->tls_session, &doq_alpn, 1, GNUTLS_ALPN_MANDATORY); - ngtcp2_conn_set_tls_native_handle(conn->conn, conn->tls_session); return KNOT_EOK; @@ -477,54 +226,6 @@ uint16_t knot_quic_conn_local_port(knot_quic_conn_t *conn) return ((const struct sockaddr_in6 *)path->local.addr)->sin6_port; } -_public_ -void knot_quic_conn_pin(knot_quic_conn_t *conn, uint8_t *pin, size_t *pin_size, bool local) -{ - if (conn == NULL) { - goto error; - } - - const gnutls_datum_t *data = NULL; - if (local) { - data = gnutls_certificate_get_ours(conn->tls_session); - } else { - unsigned count = 0; - data = gnutls_certificate_get_peers(conn->tls_session, &count); - if (count == 0) { - goto error; - } - } - if (data == NULL) { - goto error; - } - - gnutls_x509_crt_t cert; - int ret = gnutls_x509_crt_init(&cert); - if (ret != GNUTLS_E_SUCCESS) { - goto error; - } - - ret = gnutls_x509_crt_import(cert, data, GNUTLS_X509_FMT_DER); - if (ret != GNUTLS_E_SUCCESS) { - gnutls_x509_crt_deinit(cert); - goto error; - } - - ret = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, pin, pin_size); - if (ret != GNUTLS_E_SUCCESS) { - gnutls_x509_crt_deinit(cert); - goto error; - } - - gnutls_x509_crt_deinit(cert); - - return; -error: - if (pin_size != NULL) { - *pin_size = 0; - } -} - static void knot_quic_rand_cb(uint8_t *dest, size_t destlen, const ngtcp2_rand_ctx *rand_ctx) { (void)rand_ctx; @@ -602,18 +303,8 @@ static int handshake_completed_cb(ngtcp2_conn *conn, void *user_data) ctx->flags |= KNOT_QUIC_CONN_HANDSHAKE_DONE; if (!ngtcp2_conn_is_server(conn)) { - knot_quic_creds_t *creds = ctx->quic_table->creds; - if (creds->peer_pin_len == 0) { - return 0; - } - uint8_t pin[KNOT_QUIC_PIN_LEN]; - size_t pin_size = sizeof(pin); - knot_quic_conn_pin(ctx, pin, &pin_size, false); - if (pin_size != creds->peer_pin_len || - const_time_memcmp(pin, creds->peer_pin, pin_size) != 0) { - return NGTCP2_ERR_CALLBACK_FAILURE; - } - return 0; + return knot_tls_pin_check(ctx->tls_session, ctx->quic_table->creds) + == KNOT_EOK ? 0 : NGTCP2_ERR_CALLBACK_FAILURE; } if (gnutls_session_ticket_send(ctx->tls_session, 1, 0) != GNUTLS_E_SUCCESS) { @@ -945,6 +636,10 @@ int knot_quic_handle(knot_quic_table_t *table, knot_quic_reply_t *reply, goto finish; } + if (conn != NULL && (conn->flags & KNOT_QUIC_CONN_BLOCKED)) { + return KNOT_EOK; + } + ngtcp2_path path; path.remote.addr = (struct sockaddr *)reply->ip_rem; path.remote.addrlen = addr_len((struct sockaddr_in6 *)reply->ip_rem); @@ -1249,6 +944,8 @@ int knot_quic_send(knot_quic_table_t *quic_table, knot_quic_conn_t *conn, return KNOT_EINVAL; } else if (reply->handle_ret < 0) { return reply->handle_ret; + } else if ((conn->flags & KNOT_QUIC_CONN_BLOCKED) && !(flags & KNOT_QUIC_SEND_IGNORE_BLOCKED)) { + return KNOT_EOK; } else if (reply->handle_ret > 0) { return send_special(quic_table, reply, conn); } else if (conn == NULL) { diff --git a/src/libknot/quic/quic.h b/src/libknot/quic/quic.h index 29a02e0..b4acb33 100644 --- a/src/libknot/quic/quic.h +++ b/src/libknot/quic/quic.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,20 +29,18 @@ #include #include "libknot/quic/quic_conn.h" - -#define KNOT_QUIC_PIN_LEN 32 +#include "libknot/quic/tls_common.h" #define KNOT_QUIC_HANDLE_RET_CLOSE 2000 // RFC 9250 #define KNOT_QUIC_ERR_EXCESSIVE_LOAD 0x4 -struct gnutls_x509_crt_int; -struct knot_quic_creds; struct knot_quic_session; typedef enum { KNOT_QUIC_SEND_IGNORE_LASTBYTE = (1 << 0), + KNOT_QUIC_SEND_IGNORE_BLOCKED = (1 << 1), } knot_quic_send_flag_t; typedef struct knot_quic_reply { @@ -86,45 +84,6 @@ struct knot_quic_session *knot_quic_session_save(knot_quic_conn_t *conn); */ int knot_quic_session_load(knot_quic_conn_t *conn, struct knot_quic_session *session); -/*! - * \brief Init server TLS certificate for DoQ. - * - * \param cert_file X509 certificate PEM file path/name (NULL if auto-generated). - * \param key_file Key PEM file path/name. - * - * \return Initialized creds. - */ -struct knot_quic_creds *knot_quic_init_creds(const char *cert_file, - const char *key_file); - -/*! - * \brief Init peer TLS certificate for DoQ. - * - * \param local_creds Local credentials if server. - * \param peer_pin Optional peer certificate pin to check. - * \param peer_pin_len Length of the peer pin. Set 0 if not specified. - * - * \return Initialized creds. - */ -struct knot_quic_creds *knot_quic_init_creds_peer(const struct knot_quic_creds *local_creds, - const uint8_t *peer_pin, - uint8_t peer_pin_len); - -/*! - * \brief Gets the certificate from credentials. - * - * \param creds TLS credentials. - * \param cert Output certificate. - * - * \return KNOT_E* - */ -int knot_quic_creds_cert(struct knot_quic_creds *creds, struct gnutls_x509_crt_int **cert); - -/*! - * \brief Deinit server TLS certificate for DoQ. - */ -void knot_quic_free_creds(struct knot_quic_creds *creds); - /*! * \brief Returns timeout value for the connection. */ @@ -155,18 +114,6 @@ uint32_t knot_quic_conn_rtt(knot_quic_conn_t *conn); */ uint16_t knot_quic_conn_local_port(knot_quic_conn_t *conn); -/*! - * \brief Gets local or remote certificate pin. - * - * \note Zero output pin_size value means no certificate available or error. - * - * \param conn QUIC connection. - * \param pin Output certificate pin. - * \param pin_size Input size of the storage / output size of the stored pin. - * \param local Local or remote certificate indication. - */ -void knot_quic_conn_pin(knot_quic_conn_t *conn, uint8_t *pin, size_t *pin_size, bool local); - /*! * \brief Create new outgoing QUIC connection. * diff --git a/src/libknot/quic/quic_conn.c b/src/libknot/quic/quic_conn.c index 6616573..1a3b9df 100644 --- a/src/libknot/quic/quic_conn.c +++ b/src/libknot/quic/quic_conn.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include "libdnssec/random.h" #include "libknot/attribute.h" #include "libknot/error.h" +#include "libknot/quic/tls_common.h" #include "libknot/quic/quic.h" #include "libknot/xdp/tcp_iobuf.h" #include "libknot/wire.h" @@ -45,7 +46,7 @@ static int cmp_expiry_heap_nodes(void *c1, void *c2) _public_ knot_quic_table_t *knot_quic_table_new(size_t max_conns, size_t max_ibufs, size_t max_obufs, - size_t udp_payload, struct knot_quic_creds *creds) + size_t udp_payload, struct knot_creds *creds) { size_t table_size = max_conns * BUCKETS_PER_CONNS; @@ -61,9 +62,17 @@ knot_quic_table_t *knot_quic_table_new(size_t max_conns, size_t max_ibufs, size_ res->obufs_max = max_obufs; res->udp_payload_limit = udp_payload; + int ret = gnutls_priority_init2(&res->priority, KNOT_TLS_PRIORITIES, NULL, + GNUTLS_PRIORITY_INIT_DEF_APPEND); + if (ret != GNUTLS_E_SUCCESS) { + free(res); + return NULL; + } + res->expiry_heap = malloc(sizeof(struct heap)); if (res->expiry_heap == NULL || !heap_init(res->expiry_heap, cmp_expiry_heap_nodes, 0)) { free(res->expiry_heap); + gnutls_priority_deinit(res->priority); free(res); return NULL; } @@ -92,6 +101,7 @@ void knot_quic_table_free(knot_quic_table_t *table) assert(table->ibufs_size == 0); assert(table->obufs_size == 0); + gnutls_priority_deinit(table->priority); heap_deinit(table->expiry_heap); free(table->expiry_heap); free(table); @@ -118,7 +128,9 @@ void knot_quic_table_sweep(knot_quic_table_t *table, struct knot_quic_reply *swe while (!EMPTY_HEAP(table->expiry_heap)) { knot_quic_conn_t *c = *(knot_quic_conn_t **)HHEAD(table->expiry_heap); - if (table->usage > table->max_conns) { + if ((c->flags & KNOT_QUIC_CONN_BLOCKED)) { + break; // highly inprobable + } else if (table->usage > table->max_conns) { knot_sweep_stats_incr(stats, KNOT_SWEEP_CTR_LIMIT_CONN); send_excessive_load(c, sweep_reply, table); knot_quic_table_rem(c, table); @@ -476,7 +488,7 @@ uint8_t *knot_quic_stream_add_data(knot_quic_conn_t *conn, int64_t stream_id, add_tail((list_t *)&s->outbufs, (node_t *)obuf); s->obufs_size += obuf->len; conn->obufs_size += obuf->len; - conn->quic_table->obufs_size += obuf->len; + ATOMIC_ADD(conn->quic_table->obufs_size, obuf->len); return obuf->buf + prefix; } @@ -497,7 +509,7 @@ void knot_quic_stream_ack_data(knot_quic_conn_t *conn, int64_t stream_id, assert(HEAD(*obs) != first); // help CLANG analyzer understand what rem_node did and that further usage of HEAD(*obs) is safe s->obufs_size -= first->len; conn->obufs_size -= first->len; - conn->quic_table->obufs_size -= first->len; + ATOMIC_SUB(conn->quic_table->obufs_size, first->len); s->first_offset += first->len; free(first); if (s->unsent_obuf == first) { @@ -555,6 +567,19 @@ void knot_quic_stream_mark_sent(knot_quic_conn_t *conn, int64_t stream_id, } } +_public_ +void knot_quic_conn_block(knot_quic_conn_t *conn, bool block) +{ + if (block) { + conn->flags |= KNOT_QUIC_CONN_BLOCKED; + conn->next_expiry = UINT64_MAX; + conn_heap_reschedule(conn, conn->quic_table); + } else { + conn->flags &= ~KNOT_QUIC_CONN_BLOCKED; + quic_conn_mark_used(conn, conn->quic_table); + } +} + _public_ void knot_quic_cleanup(knot_quic_conn_t *conns[], size_t n_conns) { diff --git a/src/libknot/quic/quic_conn.h b/src/libknot/quic/quic_conn.h index 64ead51..49e0631 100644 --- a/src/libknot/quic/quic_conn.h +++ b/src/libknot/quic/quic_conn.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,10 +29,13 @@ #include #include +#include "contrib/atomic.h" + #define MAX_STREAMS_PER_CONN 10 // this limits the number of un-finished streams per conn (i.e. if response has been recvd with FIN, it doesn't count) +struct gnutls_priority_st; struct ngtcp2_cid; // declaration taken from wherever in ngtcp2 -struct knot_quic_creds; +struct knot_creds; struct knot_quic_reply; struct knot_sweep_stats; @@ -70,6 +73,7 @@ typedef struct { typedef enum { KNOT_QUIC_CONN_HANDSHAKE_DONE = (1 << 0), KNOT_QUIC_CONN_SESSION_TAKEN = (1 << 1), + KNOT_QUIC_CONN_BLOCKED = (1 << 2), } knot_quic_conn_flag_t; typedef struct knot_quic_conn { @@ -111,12 +115,13 @@ typedef struct knot_quic_table { size_t ibufs_max; size_t obufs_max; size_t ibufs_size; - size_t obufs_size; + knot_atomic_size_t obufs_size; size_t udp_payload_limit; // for simplicity not distinguishing IPv4/6 void (*log_cb)(const char *); const char *qlog_dir; uint64_t hash_secret[4]; - struct knot_quic_creds *creds; + struct knot_creds *creds; + struct gnutls_priority_st *priority; struct heap *expiry_heap; knot_quic_cid_t *conns[]; } knot_quic_table_t; @@ -133,7 +138,7 @@ typedef struct knot_quic_table { * \return Allocated table, or NULL. */ knot_quic_table_t *knot_quic_table_new(size_t max_conns, size_t max_ibufs, size_t max_obufs, - size_t udp_payload, struct knot_quic_creds *creds); + size_t udp_payload, struct knot_creds *creds); /*! * \brief Free QUIC table including its contents. @@ -305,6 +310,11 @@ void knot_quic_stream_ack_data(knot_quic_conn_t *conn, int64_t stream_id, void knot_quic_stream_mark_sent(knot_quic_conn_t *conn, int64_t stream_id, size_t amount_sent); +/*! + * \brief (Un)block the connection for incoming/outgoing traffic and sweep. + */ +void knot_quic_conn_block(knot_quic_conn_t *conn, bool block); + /*! * \brief Free rest of resources of closed conns. * diff --git a/src/libknot/quic/tls.c b/src/libknot/quic/tls.c new file mode 100644 index 0000000..01172df --- /dev/null +++ b/src/libknot/quic/tls.c @@ -0,0 +1,262 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "libknot/quic/tls.h" + +#include "contrib/macros.h" +#include "contrib/time.h" +#include "libknot/attribute.h" +#include "libknot/error.h" +#include "libknot/quic/tls_common.h" + +_public_ +knot_tls_ctx_t *knot_tls_ctx_new(struct knot_creds *creds, unsigned io_timeout, + unsigned hs_timeout, bool server) +{ + knot_tls_ctx_t *res = calloc(1, sizeof(*res)); + if (res == NULL) { + return NULL; + } + + res->creds = creds; + res->handshake_timeout = hs_timeout; + res->io_timeout = io_timeout; + res->server = server; + + int ret = gnutls_priority_init2(&res->priority, KNOT_TLS_PRIORITIES, NULL, + GNUTLS_PRIORITY_INIT_DEF_APPEND); + if (ret != GNUTLS_E_SUCCESS) { + free(res); + return NULL; + } + + return res; +} + +_public_ +void knot_tls_ctx_free(knot_tls_ctx_t *ctx) +{ + if (ctx != NULL) { + gnutls_priority_deinit(ctx->priority); + free(ctx); + } +} + +_public_ +knot_tls_conn_t *knot_tls_conn_new(knot_tls_ctx_t *ctx, int sock_fd) +{ + knot_tls_conn_t *res = calloc(1, sizeof(*res)); + if (res == NULL) { + return NULL; + } + res->ctx = ctx; + res->fd = sock_fd; + + int ret = knot_tls_session(&res->session, ctx->creds, ctx->priority, + "\x03""dot", false, ctx->server); + if (ret != KNOT_EOK) { + goto fail; + } + + gnutls_transport_set_int(res->session, sock_fd); // Use internal recv/send/poll. + gnutls_handshake_set_timeout(res->session, ctx->handshake_timeout); + + return res; +fail: + gnutls_deinit(res->session); + free(res); + return NULL; +} + +_public_ +void knot_tls_conn_del(knot_tls_conn_t *conn) +{ + if (conn != NULL && conn->fd_clones_count-- < 1) { + gnutls_deinit(conn->session); + free(conn); + } +} + +_public_ +int knot_tls_handshake(knot_tls_conn_t *conn, bool oneshot) +{ + if (conn->flags & (KNOT_TLS_CONN_HANDSHAKE_DONE | KNOT_TLS_CONN_BLOCKED)) { + return KNOT_EOK; + } + + /* Check if NB socket is writeable. */ + int opt; + socklen_t opt_len = sizeof(opt); + int ret = getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len); + if (ret < 0 || opt == ECONNREFUSED) { + return KNOT_NET_ECONNECT; + } + + gnutls_record_set_timeout(conn->session, conn->ctx->io_timeout); + do { + ret = gnutls_handshake(conn->session); + } while (!oneshot && ret < 0 && gnutls_error_is_fatal(ret) == 0); + + switch (ret) { + case GNUTLS_E_SUCCESS: + conn->flags |= KNOT_TLS_CONN_HANDSHAKE_DONE; + return knot_tls_pin_check(conn->session, conn->ctx->creds); + case GNUTLS_E_TIMEDOUT: + return KNOT_NET_ETIMEOUT; + default: + if (gnutls_error_is_fatal(ret) == 0) { + return KNOT_EAGAIN; + } else { + return KNOT_NET_EHSHAKE; + } + } +} + +#define TIMEOUT_CTX_INIT \ + struct timespec begin, end; \ + if (*timeout_ptr > 0) { \ + clock_gettime(CLOCK_MONOTONIC, &begin); \ + } + +#define TIMEOUT_CTX_UPDATE \ + if (*timeout_ptr > 0) { \ + clock_gettime(CLOCK_MONOTONIC, &end); \ + int running_ms = time_diff_ms(&begin, &end); \ + *timeout_ptr = MAX(*timeout_ptr - running_ms, 0); \ + } + +static ssize_t recv_data(knot_tls_conn_t *conn, void *data, size_t size, int *timeout_ptr) +{ + gnutls_record_set_timeout(conn->session, *timeout_ptr); + + size_t total = 0; + ssize_t res; + while (total < size) { + TIMEOUT_CTX_INIT + res = gnutls_record_recv(conn->session, data + total, size - total); + if (res > 0) { + total += res; + } else if (res == 0) { + return KNOT_ECONNRESET; + } else if (gnutls_error_is_fatal(res) != 0) { + return KNOT_NET_ERECV; + } + TIMEOUT_CTX_UPDATE + gnutls_record_set_timeout(conn->session, *timeout_ptr); + } + + assert(total == size); + return size; +} + +_public_ +ssize_t knot_tls_recv_dns(knot_tls_conn_t *conn, void *data, size_t size) +{ + if (conn == NULL || data == NULL) { + return KNOT_EINVAL; + } + + if (conn->flags & KNOT_TLS_CONN_BLOCKED) { + return 0; + } + + ssize_t ret = knot_tls_handshake(conn, false); + if (ret != KNOT_EOK) { + return ret; + } + + int timeout = conn->ctx->io_timeout; + + uint16_t msg_len; + ret = recv_data(conn, &msg_len, sizeof(msg_len), &timeout); + if (ret != sizeof(msg_len)) { + return ret; + } + + msg_len = ntohs(msg_len); + if (size < msg_len) { + return KNOT_ESPACE; + } + + ret = recv_data(conn, data, msg_len, &timeout); + if (ret != size) { + return ret; + } + + return msg_len; +} + +_public_ +ssize_t knot_tls_send_dns(knot_tls_conn_t *conn, void *data, size_t size) +{ + if (conn == NULL || data == NULL || size > UINT16_MAX) { + return KNOT_EINVAL; + } + + ssize_t res = knot_tls_handshake(conn, false); + if (res != KNOT_EOK) { + return res; + } + + // Enable data buffering. + gnutls_record_cork(conn->session); + + uint16_t msg_len = htons(size); + res = gnutls_record_send(conn->session, &msg_len, sizeof(msg_len)); + if (res != sizeof(msg_len)) { + return KNOT_NET_ESEND; + } + + res = gnutls_record_send(conn->session, data, size); + if (res != size) { + return KNOT_NET_ESEND; + } + + int timeout = conn->ctx->io_timeout, *timeout_ptr = &timeout; + gnutls_record_set_timeout(conn->session, timeout); + + // Send the buffered data. + while (gnutls_record_check_corked(conn->session) > 0) { + TIMEOUT_CTX_INIT + int ret = gnutls_record_uncork(conn->session, 0); + if (ret < 0 && gnutls_error_is_fatal(ret) != 0) { + return ret == GNUTLS_E_TIMEDOUT ? KNOT_ETIMEOUT : + KNOT_NET_ESEND; + } + TIMEOUT_CTX_UPDATE + gnutls_record_set_timeout(conn->session, timeout); + } + + return size; +} + +_public_ +void knot_tls_conn_block(knot_tls_conn_t *conn, bool block) +{ + if (block) { + conn->flags |= KNOT_TLS_CONN_BLOCKED; + } else { + conn->flags &= ~KNOT_TLS_CONN_BLOCKED; + } +} diff --git a/src/libknot/quic/tls.h b/src/libknot/quic/tls.h new file mode 100644 index 0000000..7801ca8 --- /dev/null +++ b/src/libknot/quic/tls.h @@ -0,0 +1,135 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +/*! + * \file + * + * \brief Pure TLS functionality. + * + * \addtogroup quic + * @{ + */ + +#pragma once + +#include +#include +#include + +struct gnutls_priority_st; + +typedef enum { + KNOT_TLS_CONN_HANDSHAKE_DONE = (1 << 0), + KNOT_TLS_CONN_SESSION_TAKEN = (1 << 1), // unused, to be implemeted later + KNOT_TLS_CONN_BLOCKED = (1 << 2), +} knot_tls_conn_flag_t; + +typedef struct knot_tls_ctx { + struct knot_creds *creds; + struct gnutls_priority_st *priority; + unsigned handshake_timeout; + unsigned io_timeout; + bool server; +} knot_tls_ctx_t; + +typedef struct knot_tls_conn { + struct gnutls_session_int *session; + struct knot_tls_ctx *ctx; + int fd; + unsigned fd_clones_count; + knot_tls_conn_flag_t flags; +} knot_tls_conn_t; + +/*! + * \brief Initialize DoT answering context. + * + * \param creds Certificate credentials. + * \param io_timeout Connections' IO-timeout (in milliseconds). + * \param hs_timeout Handshake timeout (in milliseconds). + * \param server Server context (otherwise client). + * + * \return Initialized context or NULL. + */ +knot_tls_ctx_t *knot_tls_ctx_new(struct knot_creds *creds, unsigned io_timeout, + unsigned hs_timeout, bool server); + +/*! + * \brief Free DoT answering context. + */ +void knot_tls_ctx_free(knot_tls_ctx_t *ctx); + +/*! + * \brief Initialize DoT connection. + * + * \param ctx DoT answering context. + * \param sock_fd Opened TCP connection socket. + * + * \return Connection struct or NULL. + */ +knot_tls_conn_t *knot_tls_conn_new(knot_tls_ctx_t *ctx, int sock_fd); + +/*! + * \brief Free DoT connection struct. + * + * \note Doesn't close the TCP connection socket. + */ +void knot_tls_conn_del(knot_tls_conn_t *conn); + +/*! + * \brief Perform the TLS handshake (via gnutls_handshake()). + * + * \note This is also done by the recv/send functions. + * + * \param conn DoT connection. + * \param oneshot If set, don't wait untill the handshake is finished. + * + * \retval KNOT_EOK Handshake successfully finished. + * \retval KNOT_EGAIN Handshake not finished, call me again. + * \retval KNOT_NET_EHSHAKE Handshake error. + * \retval KNOT_NET_ECONNECT Socket not connected. + */ +int knot_tls_handshake(knot_tls_conn_t *conn, bool oneshot); + +/*! + * \brief Receive a size-word-prefixed DNS message. + * + * \param conn DoT connection. + * \param data Destination buffer. + * \param size Maximum buffer size. + * + * \return Either the DNS message size received or negative error code. + * + * \note The two-byte-size-prefix is stripped upon reception, not stored to the buffer. + */ +ssize_t knot_tls_recv_dns(knot_tls_conn_t *conn, void *data, size_t size); + +/*! + * \brief Send a size-word-prefixed DNS message. + * + * \param conn DoT connection. + * \param data DNS payload. + * \param size Payload size. + * + * \return Either exactly 'size' or a negative error code. + */ +ssize_t knot_tls_send_dns(knot_tls_conn_t *conn, void *data, size_t size); + +/*! + * \brief Set or unset the conection's BLOCKED flag. + */ +void knot_tls_conn_block(knot_tls_conn_t *conn, bool block); + +/*! @} */ diff --git a/src/libknot/quic/tls_common.c b/src/libknot/quic/tls_common.c new file mode 100644 index 0000000..d1647d8 --- /dev/null +++ b/src/libknot/quic/tls_common.c @@ -0,0 +1,472 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libknot/quic/tls_common.h" + +#include "contrib/atomic.h" +#include "contrib/sockaddr.h" +#include "contrib/string.h" +#include "libknot/attribute.h" +#include "libknot/error.h" + +typedef struct knot_creds { + knot_atomic_ptr_t cert_creds; // Current credentials. + gnutls_certificate_credentials_t cert_creds_prev; // Previous credentials (for pending connections). + gnutls_anti_replay_t tls_anti_replay; + gnutls_datum_t tls_ticket_key; + bool peer; + uint8_t peer_pin_len; + uint8_t peer_pin[]; +} knot_creds_t; + +static int tls_anti_replay_db_add_func(void *dbf, time_t exp_time, + const gnutls_datum_t *key, + const gnutls_datum_t *data) +{ + return 0; +} + +static void tls_session_ticket_key_free(gnutls_datum_t *ticket) +{ + memzero(ticket->data, ticket->size); + gnutls_free(ticket->data); +} + +static int self_key(gnutls_x509_privkey_t *privkey, const char *key_file) +{ + gnutls_datum_t data = { 0 }; + + int ret = gnutls_x509_privkey_init(privkey); + if (ret != GNUTLS_E_SUCCESS) { + return ret; + } + + int fd = open(key_file, O_RDONLY); + if (fd != -1) { + struct stat stat; + if (fstat(fd, &stat) != 0 || + (data.data = gnutls_malloc(stat.st_size)) == NULL || + read(fd, data.data, stat.st_size) != stat.st_size) { + ret = GNUTLS_E_KEYFILE_ERROR; + goto finish; + } + + data.size = stat.st_size; + ret = gnutls_x509_privkey_import_pkcs8(*privkey, &data, GNUTLS_X509_FMT_PEM, + NULL, GNUTLS_PKCS_PLAIN); + if (ret != GNUTLS_E_SUCCESS) { + goto finish; + } + } else { + ret = gnutls_x509_privkey_generate(*privkey, GNUTLS_PK_EDDSA_ED25519, + GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_ED25519), 0); + if (ret != GNUTLS_E_SUCCESS) { + goto finish; + } + + ret = gnutls_x509_privkey_export2_pkcs8(*privkey, GNUTLS_X509_FMT_PEM, NULL, + GNUTLS_PKCS_PLAIN, &data); + if (ret != GNUTLS_E_SUCCESS || + (fd = open(key_file, O_WRONLY | O_CREAT, 0600)) == -1 || + write(fd, data.data, data.size) != data.size) { + ret = GNUTLS_E_KEYFILE_ERROR; + goto finish; + } + } + +finish: + if (fd > -1) { + close(fd); + } + gnutls_free(data.data); + if (ret != GNUTLS_E_SUCCESS) { + gnutls_x509_privkey_deinit(*privkey); + *privkey = NULL; + } + return ret; +} + +static int self_signed_cert(gnutls_certificate_credentials_t tls_cert, + const char *key_file) +{ + gnutls_x509_privkey_t privkey = NULL; + gnutls_x509_crt_t cert = NULL; + + char *hostname = sockaddr_hostname(); + if (hostname == NULL) { + return GNUTLS_E_MEMORY_ERROR; + } + + int ret; + uint8_t serial[16]; + gnutls_rnd(GNUTLS_RND_NONCE, serial, sizeof(serial)); + // Clear the left-most bit to be a positive number (two's complement form). + serial[0] &= 0x7F; + +#define CHK(cmd) if ((ret = (cmd)) != GNUTLS_E_SUCCESS) { goto finish; } +#define NOW_DAYS(days) (time(NULL) + 24 * 3600 * (days)) + + CHK(self_key(&privkey, key_file)); + + CHK(gnutls_x509_crt_init(&cert)); + CHK(gnutls_x509_crt_set_version(cert, 3)); + CHK(gnutls_x509_crt_set_serial(cert, serial, sizeof(serial))); + CHK(gnutls_x509_crt_set_activation_time(cert, NOW_DAYS(-1))); + CHK(gnutls_x509_crt_set_expiration_time(cert, NOW_DAYS(10 * 365))); + CHK(gnutls_x509_crt_set_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, + hostname, strlen(hostname))); + CHK(gnutls_x509_crt_set_key(cert, privkey)); + CHK(gnutls_x509_crt_sign2(cert, cert, privkey, GNUTLS_DIG_SHA512, 0)); + + ret = gnutls_certificate_set_x509_key(tls_cert, &cert, 1, privkey); + +finish: + free(hostname); + gnutls_x509_crt_deinit(cert); + gnutls_x509_privkey_deinit(privkey); + + return ret; +} + +_public_ +struct knot_creds *knot_creds_init(const char *key_file, const char *cert_file) +{ + knot_creds_t *creds = calloc(1, sizeof(*creds)); + if (creds == NULL) { + return NULL; + } + + int ret = knot_creds_update(creds, key_file, cert_file); + if (ret != KNOT_EOK) { + goto fail; + } + + ret = gnutls_anti_replay_init(&creds->tls_anti_replay); + if (ret != GNUTLS_E_SUCCESS) { + goto fail; + } + gnutls_anti_replay_set_add_function(creds->tls_anti_replay, tls_anti_replay_db_add_func); + gnutls_anti_replay_set_ptr(creds->tls_anti_replay, NULL); + + ret = gnutls_session_ticket_key_generate(&creds->tls_ticket_key); + if (ret != GNUTLS_E_SUCCESS) { + goto fail; + } + + return creds; +fail: + knot_creds_free(creds); + return NULL; +} + +_public_ +struct knot_creds *knot_creds_init_peer(const struct knot_creds *local_creds, + const uint8_t *peer_pin, + uint8_t peer_pin_len) +{ + knot_creds_t *creds = calloc(1, sizeof(*creds) + peer_pin_len); + if (creds == NULL) { + return NULL; + } + + if (local_creds != NULL) { + creds->peer = true; + creds->cert_creds = ATOMIC_GET(local_creds->cert_creds); + } else { + gnutls_certificate_credentials_t new_creds; + int ret = gnutls_certificate_allocate_credentials(&new_creds); + if (ret != GNUTLS_E_SUCCESS) { + free(creds); + return NULL; + } + creds->cert_creds = new_creds; + } + + if (peer_pin_len > 0 && peer_pin != NULL) { + memcpy(creds->peer_pin, peer_pin, peer_pin_len); + creds->peer_pin_len = peer_pin_len; + } + + return creds; +} + +static int creds_cert(gnutls_certificate_credentials_t creds, + struct gnutls_x509_crt_int **cert) +{ + gnutls_x509_crt_t *certs; + unsigned cert_count; + int ret = gnutls_certificate_get_x509_crt(creds, 0, &certs, &cert_count); + if (ret == GNUTLS_E_SUCCESS) { + if (cert_count == 0) { + gnutls_x509_crt_deinit(*certs); + return KNOT_ENOENT; + } + *cert = *certs; + free(certs); + return KNOT_EOK; + } + return KNOT_ERROR; +} + +static int creds_changed(gnutls_certificate_credentials_t creds, + gnutls_certificate_credentials_t prev, + bool self_cert, bool *changed) +{ + if (creds == NULL || prev == NULL) { + *changed = true; + return KNOT_EOK; + } + + gnutls_x509_crt_t cert = NULL, cert_prev = NULL; + + int ret = creds_cert(creds, &cert); + if (ret != KNOT_EOK) { + goto failed; + } + ret = creds_cert(prev, &cert_prev); + if (ret != KNOT_EOK) { + goto failed; + } + + if (self_cert) { + uint8_t pin[KNOT_TLS_PIN_LEN], pin_prev[KNOT_TLS_PIN_LEN]; + size_t pin_size = sizeof(pin), pin_prev_size = sizeof(pin_prev); + + ret = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, + pin, &pin_size); + if (ret != KNOT_EOK) { + goto failed; + } + ret = gnutls_x509_crt_get_key_id(cert_prev, GNUTLS_KEYID_USE_SHA256, + pin_prev, &pin_prev_size); + if (ret != KNOT_EOK) { + goto failed; + } + + *changed = (pin_size != pin_prev_size) || + memcmp(pin, pin_prev, pin_size) != 0; + } else { + *changed = (gnutls_x509_crt_equals(cert, cert_prev) == 0); + } + + ret = KNOT_EOK; +failed: + gnutls_x509_crt_deinit(cert); + gnutls_x509_crt_deinit(cert_prev); + + return ret; +} + +_public_ +int knot_creds_update(struct knot_creds *creds, const char *key_file, const char *cert_file) +{ + if (creds == NULL || key_file == NULL) { + return KNOT_EINVAL; + } + + gnutls_certificate_credentials_t new_creds; + int ret = gnutls_certificate_allocate_credentials(&new_creds); + if (ret != GNUTLS_E_SUCCESS) { + return KNOT_ENOMEM; + } + + if (cert_file != NULL) { + ret = gnutls_certificate_set_x509_key_file(new_creds, + cert_file, key_file, + GNUTLS_X509_FMT_PEM); + } else { + ret = self_signed_cert(new_creds, key_file); + } + if (ret != GNUTLS_E_SUCCESS) { + gnutls_certificate_free_credentials(new_creds); + return KNOT_EFILE; + } + + bool changed = false; + ret = creds_changed(new_creds, ATOMIC_GET(creds->cert_creds), + cert_file == NULL, &changed); + if (ret != KNOT_EOK) { + gnutls_certificate_free_credentials(new_creds); + return ret; + } + + if (changed) { + if (creds->cert_creds_prev != NULL) { + gnutls_certificate_free_credentials(creds->cert_creds_prev); + } + creds->cert_creds_prev = ATOMIC_XCHG(creds->cert_creds, new_creds); + } else { + gnutls_certificate_free_credentials(new_creds); + } + + return KNOT_EOK; +} + +_public_ +int knot_creds_cert(struct knot_creds *creds, struct gnutls_x509_crt_int **cert) +{ + if (creds == NULL || cert == NULL) { + return KNOT_EINVAL; + } + + return creds_cert(ATOMIC_GET(creds->cert_creds), cert); +} + +_public_ +void knot_creds_free(struct knot_creds *creds) +{ + if (creds == NULL) { + return; + } + + if (!creds->peer && creds->cert_creds != NULL) { + gnutls_certificate_free_credentials(creds->cert_creds); + if (creds->cert_creds_prev != NULL) { + gnutls_certificate_free_credentials(creds->cert_creds_prev); + } + } + gnutls_anti_replay_deinit(creds->tls_anti_replay); + if (creds->tls_ticket_key.data != NULL) { + tls_session_ticket_key_free(&creds->tls_ticket_key); + } + free(creds); +} + +_public_ +int knot_tls_session(struct gnutls_session_int **session, + struct knot_creds *creds, + struct gnutls_priority_st *priority, + const char *alpn, + bool early_data, + bool server) +{ + if (session == NULL || creds == NULL || priority == NULL || alpn == NULL) { + return KNOT_EINVAL; + } + + gnutls_init_flags_t flags = GNUTLS_NO_SIGNAL; + if (early_data) { + flags |= GNUTLS_ENABLE_EARLY_DATA; +#ifdef ENABLE_QUIC // Next flags aren't available in older GnuTLS versions. + flags |= GNUTLS_NO_AUTO_SEND_TICKET | GNUTLS_NO_END_OF_EARLY_DATA; +#endif + } + + int ret = gnutls_init(session, (server ? GNUTLS_SERVER : GNUTLS_CLIENT) | flags); + if (ret == GNUTLS_E_SUCCESS) { + gnutls_certificate_send_x509_rdn_sequence(*session, 1); + gnutls_certificate_server_set_request(*session, GNUTLS_CERT_REQUEST); + ret = gnutls_priority_set(*session, priority); + } + if (server && ret == GNUTLS_E_SUCCESS) { + ret = gnutls_session_ticket_enable_server(*session, &creds->tls_ticket_key); + } + if (ret == GNUTLS_E_SUCCESS) { + const gnutls_datum_t alpn_datum = { (void *)&alpn[1], alpn[0] }; + gnutls_alpn_set_protocols(*session, &alpn_datum, 1, GNUTLS_ALPN_MANDATORY); + if (early_data) { + gnutls_record_set_max_early_data_size(*session, 0xffffffffu); + } + if (server) { + gnutls_anti_replay_enable(*session, creds->tls_anti_replay); + } + ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE, + ATOMIC_GET(creds->cert_creds)); + } + if (ret != GNUTLS_E_SUCCESS) { + gnutls_deinit(*session); + *session = NULL; + } + return ret == GNUTLS_E_SUCCESS ? KNOT_EOK : KNOT_ERROR; +} + +_public_ +void knot_tls_pin(struct gnutls_session_int *session, uint8_t *pin, + size_t *pin_size, bool local) +{ + if (session == NULL) { + goto error; + } + + const gnutls_datum_t *data = NULL; + if (local) { + data = gnutls_certificate_get_ours(session); + } else { + unsigned count = 0; + data = gnutls_certificate_get_peers(session, &count); + if (count == 0) { + goto error; + } + } + if (data == NULL) { + goto error; + } + + gnutls_x509_crt_t cert; + int ret = gnutls_x509_crt_init(&cert); + if (ret != GNUTLS_E_SUCCESS) { + goto error; + } + + ret = gnutls_x509_crt_import(cert, data, GNUTLS_X509_FMT_DER); + if (ret != GNUTLS_E_SUCCESS) { + gnutls_x509_crt_deinit(cert); + goto error; + } + + ret = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, pin, pin_size); + if (ret != GNUTLS_E_SUCCESS) { + gnutls_x509_crt_deinit(cert); + goto error; + } + + gnutls_x509_crt_deinit(cert); + + return; +error: + if (pin_size != NULL) { + *pin_size = 0; + } +} + +_public_ +int knot_tls_pin_check(struct gnutls_session_int *session, + struct knot_creds *creds) +{ + if (creds->peer_pin_len == 0) { + return KNOT_EOK; + } + + uint8_t pin[KNOT_TLS_PIN_LEN]; + size_t pin_size = sizeof(pin); + knot_tls_pin(session, pin, &pin_size, false); + if (pin_size != creds->peer_pin_len || + const_time_memcmp(pin, creds->peer_pin, pin_size) != 0) { + return KNOT_EBADCERTKEY; + } + + return KNOT_EOK; +} diff --git a/src/libknot/quic/tls_common.h b/src/libknot/quic/tls_common.h new file mode 100644 index 0000000..934f256 --- /dev/null +++ b/src/libknot/quic/tls_common.h @@ -0,0 +1,134 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +/*! + * \file + * + * \brief Credentials handling common to QUIC and TLS. + * + * \addtogroup quic + * @{ + */ + +#pragma once + +#include +#include +#include + +#define KNOT_TLS_PIN_LEN 32 +#define KNOT_TLS_PRIORITIES "-VERS-ALL:+VERS-TLS1.3:" \ + "-GROUP-ALL:+GROUP-X25519:+GROUP-SECP256R1:" \ + "+GROUP-SECP384R1:+GROUP-SECP521R1" + +struct gnutls_priority_st; +struct gnutls_session_int; +struct gnutls_x509_crt_int; +struct knot_creds; + +/*! + * \brief Init server TLS key and certificate for DoQ. + * + * \param key_file Key PEM file path/name. + * \param cert_file X509 certificate PEM file path/name (NULL if auto-generated). + * + * \return Initialized creds. + */ +struct knot_creds *knot_creds_init(const char *key_file, const char *cert_file); + +/*! + * \brief Init peer TLS key and certificate for DoQ. + * + * \param local_creds Local credentials if server. + * \param peer_pin Optional peer certificate pin to check. + * \param peer_pin_len Length of the peer pin. Set 0 if not specified. + * + * \return Initialized creds. + */ +struct knot_creds *knot_creds_init_peer(const struct knot_creds *local_creds, + const uint8_t *peer_pin, + uint8_t peer_pin_len); + +/*! + * \brief Load new server TLS key and certificate for DoQ. + * + * \param creds Server credentials where key/cert pair will be updated. + * \param key_file Key PEM file path/name. + * \param cert_file X509 certificate PEM file path/name (NULL if auto-generated). + * + * \return KNOT_E* + */ +int knot_creds_update(struct knot_creds *creds, const char *key_file, const char *cert_file); + +/*! + * \brief Gets the certificate from credentials. + * + * \param creds TLS credentials. + * \param cert Output certificate. + * + * \return KNOT_E* + */ +int knot_creds_cert(struct knot_creds *creds, struct gnutls_x509_crt_int **cert); + +/*! + * \brief Deinit server TLS certificate for DoQ. + */ +void knot_creds_free(struct knot_creds *creds); + +/*! + * \brief Initialize GnuTLS session with credentials, ALPN, etc. + * + * \param session Out: initialized GnuTLS session struct. + * \param creds Certificate credentials. + * \param priority Session priority configuration. + * \param alpn ALPN string, first byte is the string length. + * \param early_data Allow early data. + * \param server Should be server session (otherwise client). + * + * \return KNOT_E* + */ +int knot_tls_session(struct gnutls_session_int **session, + struct knot_creds *creds, + struct gnutls_priority_st *priority, + const char *alpn, + bool early_data, + bool server); + +/*! + * \brief Gets local or remote certificate pin. + * + * \note Zero output pin_size value means no certificate available or error. + * + * \param session TLS connection. + * \param pin Output certificate pin. + * \param pin_size Input size of the storage / output size of the stored pin. + * \param local Local or remote certificate indication. + */ +void knot_tls_pin(struct gnutls_session_int *session, uint8_t *pin, + size_t *pin_size, bool local); + +/*! + * \brief Checks remote certificate pin in the session against credentials. + * + * \param session TLS connection. + * \param creds TLS credentials. + * + * \return KNOT_EOK or KNOT_EBADCERTKEY + */ +int knot_tls_pin_check(struct gnutls_session_int *session, + struct knot_creds *creds); + +/*! @} */ diff --git a/src/libknot/rrset-dump.c b/src/libknot/rrset-dump.c index ea406ca..9fac99d 100644 --- a/src/libknot/rrset-dump.c +++ b/src/libknot/rrset-dump.c @@ -508,10 +508,46 @@ static void wire_len_data_encode_to_str(rrset_dump_params_t *p, } } -static void wire_data_omit(rrset_dump_params_t *p) +static void wire_data_omit(rrset_dump_params_t *p, + const size_t len_len, + const bool print_len) { CHECK_PRET + size_t in_len; + + // First len_len bytes are data length. + CHECK_INMAX(len_len) + + // Read data length. + switch (len_len) { + case 0: + in_len = p->in_max; + break; + case 2: + in_len = knot_wire_read_u16(p->in); + break; + default: + p->ret = -1; + return; + } + + // If required print data length. + if (print_len == true && len_len != 0) { + assert(len_len == 2); + wire_num16_to_str(p); + CHECK_PRET + + // If something follows, print one space character. + if (in_len > 0) { + dump_string(p, " "); + CHECK_PRET + } + } else { + p->in += len_len; + p->in_max -= len_len; + } + const char *omit_message = "[omitted]"; const size_t omlen = strlen(omit_message); @@ -527,8 +563,8 @@ static void wire_data_omit(rrset_dump_params_t *p) STRING_TERMINATION - p->in += p->in_max; - p->in_max = 0; + p->in += in_len; + p->in_max -= in_len; } static void wire_dnskey_to_tag(rrset_dump_params_t *p) @@ -1735,6 +1771,10 @@ static void dnskey_info(const uint8_t *rdata, #define DUMP_TYPE wire_type_to_str(p); CHECK_RET(p); #define DUMP_HEX wire_data_encode_to_str(p, &hex_encode, \ &hex_encode_alloc); CHECK_RET(p); +#define DUMP_OMIT wire_data_omit(p, 0, false); CHECK_RET(p); +#define DUMP_HEX_OMIT if (p->style->hide_crypto) { DUMP_OMIT; } \ + else if (p->style->wrap) { WRAP_INIT; DUMP_HEX; WRAP_END; } \ + else { DUMP_HEX; } #define DUMP_BASE64 wire_data_encode_to_str(p, &knot_base64_encode, \ &knot_base64_encode_alloc); CHECK_RET(p); #define DUMP_HASH wire_len_data_encode_to_str(p, &knot_base32hex_encode, \ @@ -1743,9 +1783,9 @@ static void dnskey_info(const uint8_t *rdata, 1, false, "-"); CHECK_RET(p); #define DUMP_TSIG_DGST wire_len_data_encode_to_str(p, &knot_base64_encode, \ 2, true, ""); CHECK_RET(p); +#define DUMP_TSIG_OMIT wire_data_omit(p, 2, true); CHECK_RET(p); #define DUMP_TSIG_DATA wire_len_data_encode_to_str(p, &num48_encode, \ 2, true, ""); CHECK_RET(p); -#define DUMP_OMIT wire_data_omit(p); CHECK_RET(p); #define DUMP_KEY_OMIT wire_dnskey_to_tag(p); CHECK_RET(p); #define DUMP_TEXT wire_text_to_str1(p, true, false); CHECK_RET(p); #define DUMP_LONG_TEXT wire_text_to_str(p, p->in_max, NULL, true, false); CHECK_RET(p); @@ -1923,16 +1963,17 @@ static int dump_naptr(DUMP_PARAMS) static int dump_cert(DUMP_PARAMS) { - if (p->style->wrap) { - DUMP_NUM16; DUMP_SPACE; - DUMP_NUM16; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; WRAP_INIT; + DUMP_NUM16; DUMP_SPACE; + DUMP_NUM16; DUMP_SPACE; + DUMP_NUM8; DUMP_SPACE; + + if (p->style->hide_crypto) { + DUMP_OMIT; + } else if (p->style->wrap) { + WRAP_INIT; DUMP_BASE64; WRAP_END; } else { - DUMP_NUM16; DUMP_SPACE; - DUMP_NUM16; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; DUMP_BASE64; } @@ -1982,34 +2023,19 @@ static int dump_apl(DUMP_PARAMS) static int dump_ds(DUMP_PARAMS) { - if (p->style->wrap) { - DUMP_NUM16; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; WRAP_INIT; - DUMP_HEX; - WRAP_END; - } else { - DUMP_NUM16; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; - DUMP_HEX; - } + DUMP_NUM16; DUMP_SPACE; + DUMP_NUM8; DUMP_SPACE; + DUMP_NUM8; DUMP_SPACE; + DUMP_HEX_OMIT; DUMP_END; } static int dump_sshfp(DUMP_PARAMS) { - if (p->style->wrap) { - DUMP_NUM8; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; WRAP_INIT; - DUMP_HEX; - WRAP_END; - } else { - DUMP_NUM8; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; - DUMP_HEX; - } + DUMP_NUM8; DUMP_SPACE; + DUMP_NUM8; DUMP_SPACE; + DUMP_HEX_OMIT; DUMP_END; } @@ -2067,7 +2093,9 @@ static int dump_nsec(DUMP_PARAMS) static int dump_dhcid(DUMP_PARAMS) { - if (p->style->wrap) { + if (p->style->hide_crypto) { + DUMP_OMIT; + } else if (p->style->wrap) { WRAP_INIT; DUMP_BASE64; WRAP_END; @@ -2112,18 +2140,10 @@ static int dump_nsec3param(DUMP_PARAMS) static int dump_tlsa(DUMP_PARAMS) { - if (p->style->wrap) { - DUMP_NUM8; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; WRAP_INIT; - DUMP_HEX; - WRAP_END; - } else { - DUMP_NUM8; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; - DUMP_HEX; - } + DUMP_NUM8; DUMP_SPACE; + DUMP_NUM8; DUMP_SPACE; + DUMP_NUM8; DUMP_SPACE; + DUMP_HEX_OMIT; DUMP_END; } @@ -2139,18 +2159,10 @@ static int dump_csync(DUMP_PARAMS) static int dump_zonemd(DUMP_PARAMS) { - if (p->style->wrap) { - DUMP_NUM32; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; WRAP_INIT; - DUMP_HEX; - WRAP_END; - } else { - DUMP_NUM32; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; - DUMP_NUM8; DUMP_SPACE; - DUMP_HEX; - } + DUMP_NUM32; DUMP_SPACE; + DUMP_NUM8; DUMP_SPACE; + DUMP_NUM8; DUMP_SPACE; + DUMP_HEX_OMIT; DUMP_END; } @@ -2184,7 +2196,11 @@ static int dump_tsig(DUMP_PARAMS) DUMP_DNAME; DUMP_SPACE; DUMP_NUM48; DUMP_SPACE; DUMP_NUM16; DUMP_SPACE; WRAP_INIT; - DUMP_TSIG_DGST; WRAP_LINE; + if (p->style->hide_crypto) { + DUMP_TSIG_OMIT; WRAP_LINE; + } else { + DUMP_TSIG_DGST; WRAP_LINE; + } DUMP_NUM16; DUMP_SPACE; DUMP_TSIG_RCODE; DUMP_SPACE; DUMP_TSIG_DATA; @@ -2193,7 +2209,11 @@ static int dump_tsig(DUMP_PARAMS) DUMP_DNAME; DUMP_SPACE; DUMP_NUM48; DUMP_SPACE; DUMP_NUM16; DUMP_SPACE; - DUMP_TSIG_DGST; DUMP_SPACE; + if (p->style->hide_crypto) { + DUMP_TSIG_OMIT; DUMP_SPACE; + } else { + DUMP_TSIG_DGST; DUMP_SPACE; + } DUMP_NUM16; DUMP_SPACE; DUMP_TSIG_RCODE; DUMP_SPACE; DUMP_TSIG_DATA; diff --git a/src/libknot/rrtype/tsig.c b/src/libknot/rrtype/tsig.c index 83f8436..0002963 100644 --- a/src/libknot/rrtype/tsig.c +++ b/src/libknot/rrtype/tsig.c @@ -245,7 +245,11 @@ int knot_tsig_rdata_set_other_data(knot_rrset_t *tsig, uint16_t len, _public_ const knot_dname_t *knot_tsig_rdata_alg_name(const knot_rrset_t *tsig) { - return knot_rdataset_at(&tsig->rrs, 0)->data; + const knot_rdata_t *rr_data = knot_rdataset_at(&tsig->rrs, 0); + if (!rr_data) { + return NULL; + } + return rr_data->data; } _public_ diff --git a/src/libknot/version.h b/src/libknot/version.h index 38e0b74..8e21f49 100644 --- a/src/libknot/version.h +++ b/src/libknot/version.h @@ -17,8 +17,8 @@ #pragma once #define KNOT_VERSION_MAJOR 3 -#define KNOT_VERSION_MINOR 3 -#define KNOT_VERSION_PATCH 0x09 +#define KNOT_VERSION_MINOR 4 +#define KNOT_VERSION_PATCH 0x00 #define KNOT_VERSION_HEX ((KNOT_VERSION_MAJOR << 16) | \ (KNOT_VERSION_MINOR << 8) | \ diff --git a/src/libknot/xdp/Makefile.in b/src/libknot/xdp/Makefile.in index 8aa77ce..f065f3e 100644 --- a/src/libknot/xdp/Makefile.in +++ b/src/libknot/xdp/Makefile.in @@ -270,6 +270,8 @@ infodir = @infodir@ install_sh = @install_sh@ libbpf_CFLAGS = @libbpf_CFLAGS@ libbpf_LIBS = @libbpf_LIBS@ +libdbus_CFLAGS = @libdbus_CFLAGS@ +libdbus_LIBS = @libdbus_LIBS@ libdir = @libdir@ libdnssec_SONAME = @libdnssec_SONAME@ libdnssec_SOVERSION = @libdnssec_SOVERSION@ @@ -281,8 +283,6 @@ libfstrm_CFLAGS = @libfstrm_CFLAGS@ libfstrm_LIBS = @libfstrm_LIBS@ libidn2_CFLAGS = @libidn2_CFLAGS@ libidn2_LIBS = @libidn2_LIBS@ -libidn_CFLAGS = @libidn_CFLAGS@ -libidn_LIBS = @libidn_LIBS@ libknot_SONAME = @libknot_SONAME@ libknot_SOVERSION = @libknot_SOVERSION@ libknot_VERSION_INFO = @libknot_VERSION_INFO@ @@ -300,7 +300,6 @@ libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@ libprotobuf_c_LIBS = @libprotobuf_c_LIBS@ liburcu_CFLAGS = @liburcu_CFLAGS@ liburcu_LIBS = @liburcu_LIBS@ -liburcu_PKGCONFIG = @liburcu_PKGCONFIG@ libxdp_CFLAGS = @libxdp_CFLAGS@ libxdp_LIBS = @libxdp_LIBS@ libzscanner_SONAME = @libzscanner_SONAME@ diff --git a/src/libknot/xdp/bpf-user.h b/src/libknot/xdp/bpf-user.h index 37aac61..b76c9d6 100644 --- a/src/libknot/xdp/bpf-user.h +++ b/src/libknot/xdp/bpf-user.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -60,8 +60,10 @@ struct kxsk_umem { /*! The memory frames. */ struct umem_frame *frames; + /*! Size of RX and TX rings. */ + uint16_t ring_size; /*! The number of free frames (for TX). */ - uint32_t tx_free_count; + uint16_t tx_free_count; /*! Stack of indices of the free frames (for TX). */ uint16_t tx_free_indices[]; }; @@ -82,15 +84,15 @@ struct knot_xdp_socket { /*! If non-NULL, it's a mocked socket with this send function. */ int (*send_mock)(struct knot_xdp_socket *, const knot_xdp_msg_t[], uint32_t, uint32_t *); - /*! The kernel has to be woken up by a syscall indication. */ - bool kernel_needs_wakeup; - /*! The limit of frame size. */ unsigned frame_limit; /*! Mapping of interface indices to VLAN tags. */ uint16_t *vlan_map; uint16_t vlan_map_max; + + /*! Enabled preferred busy polling. */ + bool busy_poll; }; /*! diff --git a/src/libknot/xdp/tcp.c b/src/libknot/xdp/tcp.c index eae73a9..d219db9 100644 --- a/src/libknot/xdp/tcp.c +++ b/src/libknot/xdp/tcp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -287,172 +287,162 @@ static void conn_update(knot_tcp_conn_t *conn, const knot_xdp_msg_t *msg) } _public_ -int knot_tcp_recv(knot_tcp_relay_t *relays, knot_xdp_msg_t msgs[], uint32_t msg_count, +int knot_tcp_recv(knot_tcp_relay_t *relay, knot_xdp_msg_t *msg, knot_tcp_table_t *tcp_table, knot_tcp_table_t *syn_table, knot_tcp_ignore_t ignore) { - if (msg_count == 0) { - return KNOT_EOK; - } - if (relays == NULL || msgs == NULL || tcp_table == NULL) { + if (relay == NULL || msg == NULL || tcp_table == NULL) { return KNOT_EINVAL; } - memset(relays, 0, msg_count * sizeof(*relays)); + memset(relay, 0, sizeof(*relay)); - knot_tcp_relay_t *relay = relays; int ret = KNOT_EOK; - for (knot_xdp_msg_t *msg = msgs; msg != msgs + msg_count && ret == KNOT_EOK; msg++) { - if (!(msg->flags & KNOT_XDP_MSG_TCP)) { - continue; - } + if (!(msg->flags & KNOT_XDP_MSG_TCP)) { + return KNOT_EOK; + } - uint64_t conn_hash = 0; - knot_tcp_conn_t **pconn = tcp_table_lookup(&msg->ip_from, &msg->ip_to, - &conn_hash, tcp_table); - knot_tcp_conn_t *conn = *pconn; - bool seq_ack_match = check_seq_ack(msg, conn); - if (seq_ack_match) { - assert(conn->mss != 0); - conn_update(conn, msg); - - rem_align_pointers(conn, tcp_table); - rem_node(tcp_conn_node(conn)); - add_tail(tcp_table_timeout(tcp_table), tcp_conn_node(conn)); - - if (msg->flags & KNOT_XDP_MSG_ACK) { - conn->acked = msg->ackno; - knot_tcp_outbufs_ack(&conn->outbufs, msg->ackno, &tcp_table->outbufs_total); - } + uint64_t conn_hash = 0; + knot_tcp_conn_t **pconn = tcp_table_lookup(&msg->ip_from, &msg->ip_to, + &conn_hash, tcp_table); + knot_tcp_conn_t *conn = *pconn; + bool seq_ack_match = check_seq_ack(msg, conn); + if (seq_ack_match) { + assert(conn->mss != 0); + conn_update(conn, msg); + + rem_align_pointers(conn, tcp_table); + rem_node(tcp_conn_node(conn)); + add_tail(tcp_table_timeout(tcp_table), tcp_conn_node(conn)); + + if (msg->flags & KNOT_XDP_MSG_ACK) { + conn->acked = msg->ackno; + knot_tcp_outbufs_ack(&conn->outbufs, msg->ackno, &tcp_table->outbufs_total); } + } - relay->msg = msg; - relay->conn = conn; + relay->msg = msg; + relay->conn = conn; - // process incoming data - if (seq_ack_match && (msg->flags & KNOT_XDP_MSG_ACK) && msg->payload.iov_len > 0) { - if (!(ignore & XDP_TCP_IGNORE_DATA_ACK)) { - relay->auto_answer = KNOT_XDP_MSG_ACK; - } - ret = knot_tcp_inbufs_upd(&conn->inbuf, msg->payload, false, - &relay->inbf, &tcp_table->inbufs_total); - if (ret != KNOT_EOK) { - break; - } - if (conn->inbuf.iov_len > 0 && tcp_table->next_ibuf == NULL) { - tcp_table->next_ibuf = conn; - } + // process incoming data + if (seq_ack_match && (msg->flags & KNOT_XDP_MSG_ACK) && msg->payload.iov_len > 0) { + if (!(ignore & XDP_TCP_IGNORE_DATA_ACK)) { + relay->auto_answer = KNOT_XDP_MSG_ACK; + } + ret = knot_tcp_inbufs_upd(&conn->inbuf, msg->payload, false, + &relay->inbf, &tcp_table->inbufs_total); + if (ret != KNOT_EOK) { + return ret; + } + if (conn->inbuf.iov_len > 0 && tcp_table->next_ibuf == NULL) { + tcp_table->next_ibuf = conn; } + } - // process TCP connection state - switch (msg->flags & (KNOT_XDP_MSG_SYN | KNOT_XDP_MSG_ACK | - KNOT_XDP_MSG_FIN | KNOT_XDP_MSG_RST)) { - case KNOT_XDP_MSG_SYN: - case (KNOT_XDP_MSG_SYN | KNOT_XDP_MSG_ACK): - if (conn == NULL) { - bool synack = (msg->flags & KNOT_XDP_MSG_ACK); - - knot_tcp_table_t *add_table = tcp_table; - if (syn_table != NULL) { - if (synack) { - break; // creating conn based on SYN+ACK is only for kxdpgun, disallow in knotd - } - add_table = syn_table; - if (*tcp_table_lookup(&msg->ip_from, &msg->ip_to, &conn_hash, syn_table) != NULL) { - break; - } - } + // process TCP connection state + switch (msg->flags & (KNOT_XDP_MSG_SYN | KNOT_XDP_MSG_ACK | + KNOT_XDP_MSG_FIN | KNOT_XDP_MSG_RST)) { + case KNOT_XDP_MSG_SYN: + case (KNOT_XDP_MSG_SYN | KNOT_XDP_MSG_ACK): + if (conn == NULL) { + bool synack = (msg->flags & KNOT_XDP_MSG_ACK); - ret = tcp_table_add(msg, conn_hash, add_table, &relay->conn); - if (ret == KNOT_EOK) { - relay->action = synack ? XDP_TCP_ESTABLISH : XDP_TCP_SYN; - if (!(ignore & XDP_TCP_IGNORE_ESTABLISH)) { - relay->auto_answer = synack ? KNOT_XDP_MSG_ACK : (KNOT_XDP_MSG_SYN | KNOT_XDP_MSG_ACK); - } - - conn = relay->conn; - conn->state = synack ? XDP_TCP_NORMAL: XDP_TCP_ESTABLISHING; - conn->mss = MAX(msg->mss, 536); // minimal MSS, most importantly not zero! - conn->window_scale = msg->win_scale; - conn_update(conn, msg); - if (!synack) { - conn->acked = dnssec_random_uint32_t(); - conn->ackno = conn->acked; - } + knot_tcp_table_t *add_table = tcp_table; + if (syn_table != NULL) { + if (synack) { + break; // creating conn based on SYN+ACK is only for kxdpgun, disallow in knotd + } + add_table = syn_table; + if (*tcp_table_lookup(&msg->ip_from, &msg->ip_to, &conn_hash, syn_table) != NULL) { + break; } - } else { - relay->auto_answer = KNOT_XDP_MSG_ACK; } - break; - case KNOT_XDP_MSG_ACK: - if (!seq_ack_match) { - if (syn_table != NULL && msg->payload.iov_len == 0 && conn == NULL && - (pconn = tcp_table_lookup(&msg->ip_from, &msg->ip_to, &conn_hash, syn_table)) != NULL && - (conn = *pconn) != NULL && check_seq_ack(msg, conn)) { - // move conn from syn_table to tcp_table - tcp_table_remove(pconn, syn_table); - tcp_table_insert(conn, conn_hash, tcp_table); - relay->conn = conn; - relay->action = XDP_TCP_ESTABLISH; - conn->state = XDP_TCP_NORMAL; - conn_update(conn, msg); + + ret = tcp_table_add(msg, conn_hash, add_table, &relay->conn); + if (ret == KNOT_EOK) { + relay->action = synack ? XDP_TCP_ESTABLISH : XDP_TCP_SYN; + if (!(ignore & XDP_TCP_IGNORE_ESTABLISH)) { + relay->auto_answer = synack ? KNOT_XDP_MSG_ACK : (KNOT_XDP_MSG_SYN | KNOT_XDP_MSG_ACK); } - } else { - switch (conn->state) { - case XDP_TCP_NORMAL: - case XDP_TCP_CLOSING1: // just a mess, ignore - break; - case XDP_TCP_ESTABLISHING: - conn->state = XDP_TCP_NORMAL; - relay->action = XDP_TCP_ESTABLISH; - break; - case XDP_TCP_CLOSING2: - if (msg->payload.iov_len == 0) { // otherwise ignore close - tcp_table_remove(pconn, tcp_table); - relay->answer = XDP_TCP_FREE; - } - break; + + conn = relay->conn; + conn->state = synack ? XDP_TCP_NORMAL: XDP_TCP_ESTABLISHING; + conn->mss = MAX(msg->mss, 536); // minimal MSS, most importantly not zero! + conn->window_scale = msg->win_scale; + conn_update(conn, msg); + if (!synack) { + conn->acked = dnssec_random_uint32_t(); + conn->ackno = conn->acked; } } - break; - case (KNOT_XDP_MSG_FIN | KNOT_XDP_MSG_ACK): - if (ignore & XDP_TCP_IGNORE_FIN) { - break; + } else { + relay->auto_answer = KNOT_XDP_MSG_ACK; + } + break; + case KNOT_XDP_MSG_ACK: + if (!seq_ack_match) { + if (syn_table != NULL && msg->payload.iov_len == 0 && conn == NULL && + (pconn = tcp_table_lookup(&msg->ip_from, &msg->ip_to, &conn_hash, syn_table)) != NULL && + (conn = *pconn) != NULL && check_seq_ack(msg, conn)) { + // move conn from syn_table to tcp_table + tcp_table_remove(pconn, syn_table); + tcp_table_insert(conn, conn_hash, tcp_table); + relay->conn = conn; + relay->action = XDP_TCP_ESTABLISH; + conn->state = XDP_TCP_NORMAL; + conn_update(conn, msg); } - if (!seq_ack_match) { - if (conn != NULL) { - relay->auto_answer = KNOT_XDP_MSG_RST; - relay->auto_seqno = msg->ackno; - } // else ignore. It would be better and possible, but no big value for the price of CPU. - } else { - if (conn->state == XDP_TCP_CLOSING1) { - relay->action = XDP_TCP_CLOSE; - relay->auto_answer = KNOT_XDP_MSG_ACK; - relay->answer = XDP_TCP_FREE; + } else { + switch (conn->state) { + case XDP_TCP_NORMAL: + case XDP_TCP_CLOSING1: // just a mess, ignore + break; + case XDP_TCP_ESTABLISHING: + conn->state = XDP_TCP_NORMAL; + relay->action = XDP_TCP_ESTABLISH; + break; + case XDP_TCP_CLOSING2: + if (msg->payload.iov_len == 0) { // otherwise ignore close tcp_table_remove(pconn, tcp_table); - } else if (msg->payload.iov_len == 0) { // otherwise ignore FIN - relay->action = XDP_TCP_CLOSE; - relay->auto_answer = KNOT_XDP_MSG_FIN | KNOT_XDP_MSG_ACK; - conn->state = XDP_TCP_CLOSING2; + relay->answer = XDP_TCP_FREE; } + break; } + } + break; + case (KNOT_XDP_MSG_FIN | KNOT_XDP_MSG_ACK): + if (ignore & XDP_TCP_IGNORE_FIN) { break; - case KNOT_XDP_MSG_RST: - if (conn != NULL && msg->seqno == conn->seqno) { - relay->action = XDP_TCP_RESET; - tcp_table_remove(pconn, tcp_table); - relay->answer = XDP_TCP_FREE; - } else if (conn != NULL) { + } + if (!seq_ack_match) { + if (conn != NULL) { + relay->auto_answer = KNOT_XDP_MSG_RST; + relay->auto_seqno = msg->ackno; + } // else ignore. It would be better and possible, but no big value for the price of CPU. + } else { + if (conn->state == XDP_TCP_CLOSING1) { + relay->action = XDP_TCP_CLOSE; relay->auto_answer = KNOT_XDP_MSG_ACK; + relay->answer = XDP_TCP_FREE; + tcp_table_remove(pconn, tcp_table); + } else if (msg->payload.iov_len == 0) { // otherwise ignore FIN + relay->action = XDP_TCP_CLOSE; + relay->auto_answer = KNOT_XDP_MSG_FIN | KNOT_XDP_MSG_ACK; + conn->state = XDP_TCP_CLOSING2; } - break; - default: - break; } - - if (!knot_tcp_relay_empty(relay)) { - relay++; + break; + case KNOT_XDP_MSG_RST: + if (conn != NULL && msg->seqno == conn->seqno) { + relay->action = XDP_TCP_RESET; + tcp_table_remove(pconn, tcp_table); + relay->answer = XDP_TCP_FREE; + } else if (conn != NULL) { + relay->auto_answer = KNOT_XDP_MSG_ACK; } + break; + default: + break; } return ret; diff --git a/src/libknot/xdp/tcp.h b/src/libknot/xdp/tcp.h index 09fe652..39a30fd 100644 --- a/src/libknot/xdp/tcp.h +++ b/src/libknot/xdp/tcp.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -148,18 +148,19 @@ knot_tcp_table_t *knot_tcp_table_new(size_t size, knot_tcp_table_t *secret_share void knot_tcp_table_free(knot_tcp_table_t *table); /*! - * \brief Process received packets, prepare automatic responses (e.g. ACK), pick incoming data. + * \brief Process received packet, prepare automatic response (e.g. ACK), pick incoming data. * - * \param relays Out: relays to be filled with message/connection details. - * \param msgs Packets received by knot_xdp_recv(). - * \param msg_count Number of received packets. + * \param relay Out: relay to be filled with message/connection details. + * \param msg Packet received by knot_xdp_recv(). * \param tcp_table Table of TCP connections. * \param syn_table Optional: extra table for handling partially established connections. * \param ignore Ignore specific TCP packets indication. * + * \note resulting relay might be knot_tcp_relay_empty() + * * \return KNOT_E* */ -int knot_tcp_recv(knot_tcp_relay_t *relays, knot_xdp_msg_t msgs[], uint32_t msg_count, +int knot_tcp_recv(knot_tcp_relay_t *relay, knot_xdp_msg_t *msg, knot_tcp_table_t *tcp_table, knot_tcp_table_t *syn_table, knot_tcp_ignore_t ignore); diff --git a/src/libknot/xdp/xdp.c b/src/libknot/xdp/xdp.c index 8286884..132f5c4 100644 --- a/src/libknot/xdp/xdp.c +++ b/src/libknot/xdp/xdp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,63 +38,68 @@ #include "contrib/net.h" #define FRAME_SIZE 2048 - -#define FRAME_COUNT_TX 2048 -#define FRAME_COUNT_RX 2048 -#define FRAME_COUNT (FRAME_COUNT_TX + FRAME_COUNT_RX) - -#define RING_LEN_TX FRAME_COUNT_TX -#define RING_LEN_CQ FRAME_COUNT_TX -#define RING_LEN_RX FRAME_COUNT_RX -/* It's recommended that the FQ ring size >= HW RX ring size + AF_XDP RX ring size. */ -#define RING_LEN_FQ (2 * FRAME_COUNT_RX) - -#define ALLOC_RETRY_NUM 15 -#define ALLOC_RETRY_DELAY 20 // In nanoseconds. - -/* With recent compilers we statically check #defines for settings that - * get refused by AF_XDP drivers (in current versions, at least). */ -#if (__STDC_VERSION__ >= 201112L) -#define IS_POWER_OF_2(n) (((n) & (n - 1)) == 0) -_Static_assert((FRAME_SIZE == 4096 || FRAME_SIZE == 2048) - && IS_POWER_OF_2(RING_LEN_TX) && IS_POWER_OF_2(RING_LEN_RX) - && IS_POWER_OF_2(RING_LEN_CQ) && IS_POWER_OF_2(RING_LEN_FQ) - && FRAME_COUNT_TX <= (1 << 16) /* see tx_free_indices */ - , "Incorrect #define combination for AF_XDP."); -#endif +#define DEFAULT_RING_SIZE 2048 +#define RETRY_DELAY 20 // In nanoseconds. struct umem_frame { uint8_t bytes[FRAME_SIZE]; }; -static int configure_xsk_umem(struct kxsk_umem **out_umem, bool extra_frames) +static bool valid_config(const knot_xdp_config_t *config) +{ + if (FRAME_SIZE != 2048 && FRAME_SIZE != 4096) { + return false; + } + + if (config == NULL) { + return true; + } + + if ((config->ring_size & (config->ring_size - 1)) != 0) { + return false; + } + + return true; +} + +static uint32_t ring_size(const knot_xdp_config_t *config) +{ + return config != NULL ? config->ring_size : DEFAULT_RING_SIZE; +} + +static int configure_xsk_umem(struct kxsk_umem **out_umem, uint32_t ring_size) { /* Allocate memory and call driver to create the UMEM. */ struct kxsk_umem *umem = calloc(1, offsetof(struct kxsk_umem, tx_free_indices) - + sizeof(umem->tx_free_indices[0]) * FRAME_COUNT_TX); + + sizeof(umem->tx_free_indices[0]) * ring_size); if (umem == NULL) { return KNOT_ENOMEM; } + umem->ring_size = ring_size; - size_t frame_count = FRAME_COUNT + (extra_frames ? FRAME_COUNT_RX : 0); + /* It's recommended that the FQ ring size >= HW RX ring size + AF_XDP RX ring size. + * However, the performance is better if FQ size == AF_XDP RX size. */ + const uint32_t FQ_SIZE = umem->ring_size; + const uint32_t CQ_SIZE = umem->ring_size; + const uint32_t FRAMES = FQ_SIZE + CQ_SIZE; int ret = posix_memalign((void **)&umem->frames, getpagesize(), - FRAME_SIZE * frame_count); + FRAME_SIZE * FRAMES); if (ret != 0) { free(umem); return KNOT_ENOMEM; } - const struct xsk_umem_config config = { - .fill_size = RING_LEN_FQ, - .comp_size = RING_LEN_CQ, + const struct xsk_umem_config umem_config = { + .fill_size = FQ_SIZE, + .comp_size = CQ_SIZE, .frame_size = FRAME_SIZE, .frame_headroom = KNOT_XDP_PKT_ALIGNMENT, }; - ret = xsk_umem__create(&umem->umem, umem->frames, FRAME_SIZE * frame_count, - &umem->fq, &umem->cq, &config); + ret = xsk_umem__create(&umem->umem, umem->frames, FRAME_SIZE * FRAMES, + &umem->fq, &umem->cq, &umem_config); if (ret != KNOT_EOK) { free(umem->frames); free(umem); @@ -103,23 +108,23 @@ static int configure_xsk_umem(struct kxsk_umem **out_umem, bool extra_frames) *out_umem = umem; /* Designate the starting chunk of buffers for TX, and put them onto the stack. */ - umem->tx_free_count = FRAME_COUNT_TX; - for (uint32_t i = 0; i < FRAME_COUNT_TX; ++i) { + umem->tx_free_count = CQ_SIZE; + for (uint32_t i = 0; i < CQ_SIZE; ++i) { umem->tx_free_indices[i] = i; } /* Designate the rest of buffers for RX, and pass them to the driver. */ uint32_t idx = 0; - ret = xsk_ring_prod__reserve(&umem->fq, frame_count - FRAME_COUNT_TX, &idx); - if (ret != frame_count - FRAME_COUNT_TX) { + ret = xsk_ring_prod__reserve(&umem->fq, FQ_SIZE, &idx); + if (ret != FQ_SIZE) { assert(0); return KNOT_ERROR; } assert(idx == 0); - for (uint32_t i = FRAME_COUNT_TX; i < frame_count; ++i) { + for (uint32_t i = CQ_SIZE; i < CQ_SIZE + FQ_SIZE; ++i) { *xsk_ring_prod__fill_addr(&umem->fq, idx++) = i * FRAME_SIZE; } - xsk_ring_prod__submit(&umem->fq, frame_count - FRAME_COUNT_TX); + xsk_ring_prod__submit(&umem->fq, FQ_SIZE); return KNOT_EOK; } @@ -131,6 +136,33 @@ static void deconfigure_xsk_umem(struct kxsk_umem *umem) free(umem); } +static int enable_busypoll(int socket, unsigned timeout_us, unsigned budget) +{ +#if defined(SO_PREFER_BUSY_POLL) && defined(SO_BUSY_POLL_BUDGET) + int opt_val = 1; + if (setsockopt(socket, SOL_SOCKET, SO_PREFER_BUSY_POLL, + &opt_val, sizeof(opt_val)) != 0) { + return knot_map_errno(); + } + + opt_val = timeout_us; + if (setsockopt(socket, SOL_SOCKET, SO_BUSY_POLL, + &opt_val, sizeof(opt_val)) != 0) { + return knot_map_errno(); + } + + opt_val = budget; + if (setsockopt(socket, SOL_SOCKET, SO_BUSY_POLL_BUDGET, + &opt_val, sizeof(opt_val)) != 0) { + return knot_map_errno(); + } + + return KNOT_EOK; +#else + return KNOT_ENOTSUP; +#endif +} + static int configure_xsk_socket(struct kxsk_umem *umem, const struct kxsk_iface *iface, knot_xdp_socket_t **out_sock, @@ -143,14 +175,14 @@ static int configure_xsk_socket(struct kxsk_umem *umem, xsk_info->iface = iface; xsk_info->umem = umem; - uint16_t bind_flags = 0; + uint16_t bind_flags = XDP_USE_NEED_WAKEUP; if (config != NULL && config->force_copy) { bind_flags |= XDP_COPY; } const struct xsk_socket_config sock_conf = { - .tx_size = RING_LEN_TX, - .rx_size = RING_LEN_RX, + .tx_size = umem->ring_size, + .rx_size = umem->ring_size, .libbpf_flags = XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD, .bind_flags = bind_flags, }; @@ -163,6 +195,17 @@ static int configure_xsk_socket(struct kxsk_umem *umem, return ret; } + if (config != NULL && config->busy_poll_budget > 0) { + ret = enable_busypoll(xsk_socket__fd(xsk_info->xsk), + config->busy_poll_timeout, config->busy_poll_budget); + if (ret != KNOT_EOK) { + xsk_socket__delete(xsk_info->xsk); + free(xsk_info); + return ret; + } + xsk_info->busy_poll = true; + } + *out_sock = xsk_info; return KNOT_EOK; } @@ -172,7 +215,7 @@ int knot_xdp_init(knot_xdp_socket_t **socket, const char *if_name, int if_queue, knot_xdp_filter_flag_t flags, uint16_t udp_port, uint16_t quic_port, knot_xdp_load_bpf_t load_bpf, const knot_xdp_config_t *xdp_config) { - if (socket == NULL || if_name == NULL || + if (socket == NULL || if_name == NULL || !valid_config(xdp_config) || (udp_port == quic_port && (flags & KNOT_XDP_FILTER_UDP) && (flags & KNOT_XDP_FILTER_QUIC)) || (flags & (KNOT_XDP_FILTER_UDP | KNOT_XDP_FILTER_TCP | KNOT_XDP_FILTER_QUIC)) == 0) { return KNOT_EINVAL; @@ -187,7 +230,7 @@ int knot_xdp_init(knot_xdp_socket_t **socket, const char *if_name, int if_queue, /* Initialize shared packet_buffer for umem usage. */ struct kxsk_umem *umem = NULL; - ret = configure_xsk_umem(&umem, xdp_config->extra_frames); + ret = configure_xsk_umem(&umem, ring_size(xdp_config)); if (ret != KNOT_EOK) { kxsk_iface_free(iface); return ret; @@ -266,7 +309,7 @@ static void tx_free_relative(struct kxsk_umem *umem, uint64_t addr_relative) { /* The address may not point to *start* of buffer, but `/` solves that. */ uint64_t index = addr_relative / FRAME_SIZE; - assert(index < FRAME_COUNT); + assert(index < umem->ring_size); umem->tx_free_indices[umem->tx_free_count++] = index; } @@ -285,7 +328,7 @@ void knot_xdp_send_prepare(knot_xdp_socket_t *socket) if (completed == 0) { return; } - assert(umem->tx_free_count + completed <= FRAME_COUNT_TX); + assert(umem->tx_free_count + completed <= umem->ring_size); for (uint32_t i = 0; i < completed; ++i) { uint64_t addr_relative = *xsk_ring_cons__comp_addr(cq, idx++); @@ -301,12 +344,13 @@ static struct umem_frame *alloc_tx_frame(knot_xdp_socket_t *socket) return malloc(sizeof(struct umem_frame)); } - const struct timespec delay = { .tv_nsec = ALLOC_RETRY_DELAY }; struct kxsk_umem *umem = socket->umem; - for (int i = 0; unlikely(umem->tx_free_count == 0); i++) { - if (i == ALLOC_RETRY_NUM) { - return NULL; + const struct timespec delay = { .tv_nsec = RETRY_DELAY }; + while (unlikely(umem->tx_free_count == 0)) { + if (socket->busy_poll || xsk_ring_prod__needs_wakeup(&socket->tx)) { + (void)sendto(xsk_socket__fd(socket->xsk), NULL, 0, + MSG_DONTWAIT, NULL, 0); } nanosleep(&delay, NULL); knot_xdp_send_prepare(socket); @@ -381,9 +425,7 @@ int knot_xdp_send(knot_xdp_socket_t *socket, const knot_xdp_msg_t msgs[], } if (unlikely(socket->send_mock != NULL)) { int ret = socket->send_mock(socket, msgs, count, sent); - for (uint32_t i = 0; i < count; ++i) { - free_unsent(socket, &msgs[i]); - } + knot_xdp_send_free(socket, msgs, count); return ret; } @@ -393,12 +435,13 @@ int knot_xdp_send(knot_xdp_socket_t *socket, const knot_xdp_msg_t msgs[], * and the API doesn't allow "cancelling reservations". * Therefore we handle `socket->tx.cached_prod` by hand. */ - if (xsk_prod_nb_free(&socket->tx, count) < count) { - /* This situation was sometimes observed in the emulated XDP mode. */ - for (uint32_t i = 0; i < count; ++i) { - free_unsent(socket, &msgs[i]); + const struct timespec delay = { .tv_nsec = RETRY_DELAY }; + while (unlikely(xsk_prod_nb_free(&socket->tx, count) < count)) { + if (socket->busy_poll || xsk_ring_prod__needs_wakeup(&socket->tx)) { + (void)sendto(xsk_socket__fd(socket->xsk), NULL, 0, + MSG_DONTWAIT, NULL, 0); } - return KNOT_ENOBUFS; + nanosleep(&delay, NULL); } uint32_t idx = socket->tx.cached_prod; @@ -425,7 +468,6 @@ int knot_xdp_send(knot_xdp_socket_t *socket, const knot_xdp_msg_t msgs[], assert(*sent <= count); socket->tx.cached_prod = idx; xsk_ring_prod__submit(&socket->tx, *sent); - socket->kernel_needs_wakeup = true; return KNOT_EOK; } @@ -446,34 +488,19 @@ int knot_xdp_send_finish(knot_xdp_socket_t *socket) return KNOT_EINVAL; } - /* Trigger sending queued packets. */ - if (!socket->kernel_needs_wakeup) { + if (!socket->busy_poll && !xsk_ring_prod__needs_wakeup(&socket->tx)) { return KNOT_EOK; } int ret = sendto(xsk_socket__fd(socket->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0); - const bool is_ok = (ret >= 0); - // List of "safe" errors taken from - // https://github.com/torvalds/linux/blame/master/samples/bpf/xdpsock_user.c - const bool is_again = !is_ok && (errno == ENOBUFS || errno == EAGAIN - || errno == EBUSY || errno == ENETDOWN); - // Some of the !is_ok cases are a little unclear - what to do about the syscall, - // including how caller of _sendmsg_finish() should react. - if (is_ok || !is_again) { - socket->kernel_needs_wakeup = false; - } - if (is_again) { - return KNOT_EAGAIN; - } else if (is_ok) { + if (ret >= 0) { return KNOT_EOK; + } else if (errno == ENOBUFS || errno == EAGAIN || errno == EBUSY || + errno == ENETDOWN) { + return KNOT_EAGAIN; } else { return -errno; } - /* This syscall might be avoided with a newer kernel feature (>= 5.4): - https://www.kernel.org/doc/html/latest/networking/af_xdp.html#xdp-use-need-wakeup-bind-flag - Unfortunately it's not easy to continue supporting older kernels - when using this feature on newer ones. - */ } _public_ @@ -518,7 +545,7 @@ int knot_xdp_recv(knot_xdp_socket_t *socket, knot_xdp_msg_t msgs[], static uint8_t *msg_uframe_ptr(const knot_xdp_msg_t *msg) { - return NULL + ((msg->payload.iov_base - NULL) & ~(FRAME_SIZE - 1)); + return (uint8_t *)((uintptr_t)msg->payload.iov_base & ~(FRAME_SIZE - 1)); } _public_ @@ -529,30 +556,32 @@ void knot_xdp_recv_finish(knot_xdp_socket_t *socket, const knot_xdp_msg_t msgs[] return; } - const struct timespec delay = { .tv_nsec = ALLOC_RETRY_DELAY }; - struct kxsk_umem *const umem = socket->umem; struct xsk_ring_prod *const fq = &umem->fq; uint32_t idx = 0; - uint32_t reserved = xsk_ring_prod__reserve(fq, count, &idx); - for (int i = 0; unlikely(reserved < count); i++) { - if (i == ALLOC_RETRY_NUM) { - return; + const struct timespec delay = { .tv_nsec = RETRY_DELAY }; + while (unlikely(xsk_ring_prod__reserve(fq, count, &idx) != count)) { + if (socket->busy_poll || xsk_ring_prod__needs_wakeup(fq)) { + (void)recvfrom(xsk_socket__fd(socket->xsk), NULL, 0, + MSG_DONTWAIT, NULL, NULL); } nanosleep(&delay, NULL); - reserved = xsk_ring_prod__reserve(fq, count, &idx); } - for (uint32_t i = 0; i < reserved; ++i) { + for (uint32_t i = 0; i < count; ++i) { uint8_t *uframe_p = msg_uframe_ptr(&msgs[i]); uint64_t offset = uframe_p - umem->frames->bytes; *xsk_ring_prod__fill_addr(fq, idx++) = offset; } - xsk_ring_prod__submit(fq, reserved); + xsk_ring_prod__submit(fq, count); + // recvfrom() here slightly worsens the performance, poll is called later anyway. } +// The number of busy frames +#define RING_BUSY(ring) ((*(ring)->producer - *(ring)->consumer) & (ring)->mask) + _public_ void knot_xdp_socket_info(const knot_xdp_socket_t *socket, FILE *file) { @@ -560,10 +589,6 @@ void knot_xdp_socket_info(const knot_xdp_socket_t *socket, FILE *file) return; } - // The number of busy frames - #define RING_BUSY(ring) \ - ((*(ring)->producer - *(ring)->consumer) & (ring)->mask) - #define RING_PRINFO(name, ring) \ fprintf(file, "Ring %s: size %4d, busy %4d (prod %4d, cons %4d)\n", \ name, (unsigned)(ring)->size, \ @@ -571,11 +596,11 @@ void knot_xdp_socket_info(const knot_xdp_socket_t *socket, FILE *file) (unsigned)*(ring)->producer, (unsigned)*(ring)->consumer) const int rx_busyf = RING_BUSY(&socket->umem->fq) + RING_BUSY(&socket->rx); - fprintf(file, "\nLOST RX frames: %4d", (int)(FRAME_COUNT_RX - rx_busyf)); + fprintf(file, "\nLOST RX frames: %4d", (int)(socket->umem->ring_size - rx_busyf)); const int tx_busyf = RING_BUSY(&socket->umem->cq) + RING_BUSY(&socket->tx); const int tx_freef = socket->umem->tx_free_count; - fprintf(file, "\nLOST TX frames: %4d\n", (int)(FRAME_COUNT_TX - tx_busyf - tx_freef)); + fprintf(file, "\nLOST TX frames: %4d\n", (int)(socket->umem->ring_size - tx_busyf - tx_freef)); RING_PRINFO("FQ", &socket->umem->fq); RING_PRINFO("RX", &socket->rx); @@ -583,3 +608,39 @@ void knot_xdp_socket_info(const knot_xdp_socket_t *socket, FILE *file) RING_PRINFO("CQ", &socket->umem->cq); fprintf(file, "TX free frames: %4d\n", tx_freef); } + +_public_ +int knot_xdp_socket_stats(knot_xdp_socket_t *socket, knot_xdp_stats_t *stats) +{ + if (socket == NULL || stats == NULL) { + return KNOT_EINVAL; + } + + memset(stats, 0, sizeof(*stats)); + + stats->if_name = socket->iface->if_name; + stats->if_index = socket->iface->if_index; + stats->if_queue = socket->iface->if_queue; + + struct xdp_statistics xdp_stats; + socklen_t optlen = sizeof(xdp_stats); + + int fd = knot_xdp_socket_fd(socket); + int ret = getsockopt(fd, SOL_XDP, XDP_STATISTICS, &xdp_stats, &optlen); + if (ret != 0) { + return knot_map_errno(); + } else if (optlen != sizeof(xdp_stats)) { + return KNOT_EINVAL; + } + + size_t common_size = MIN(sizeof(xdp_stats), sizeof(stats->socket)); + memcpy(&stats->socket, &xdp_stats, common_size); + + stats->rings.tx_busy = socket->umem->ring_size - socket->umem->tx_free_count; + stats->rings.fq_fill = RING_BUSY(&socket->umem->fq); + stats->rings.rx_fill = RING_BUSY(&socket->rx); + stats->rings.tx_fill = RING_BUSY(&socket->tx); + stats->rings.cq_fill = RING_BUSY(&socket->umem->cq); + + return KNOT_EOK; +} diff --git a/src/libknot/xdp/xdp.h b/src/libknot/xdp/xdp.h index 6c8bb1e..5944d44 100644 --- a/src/libknot/xdp/xdp.h +++ b/src/libknot/xdp/xdp.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -53,14 +53,54 @@ typedef struct knot_xdp_socket knot_xdp_socket_t; /*! \brief Configuration of XDP socket. */ struct knot_xdp_config { - bool force_generic; /*!< Use generic XDP mode (avoid driver/hadrware implementation). */ - bool force_copy; /*!< Force copying packet data between kernel and user-space (avoid zero-copy). */ - bool extra_frames; /*!< Extra FQ frames. */ + uint16_t ring_size; /*!< Size of RX and TX rings (must be power of 2). */ + bool force_generic; /*!< Use generic XDP mode (avoid driver/hardware implementation). */ + bool force_copy; /*!< Force copying packet data between kernel and user-space (avoid zero-copy). */ + unsigned busy_poll_timeout; /*!< Preferred busy poll budget (0 means disabled). */ + unsigned busy_poll_budget; /*!< Preferred busy poll timeout (in microseconds) . */ }; /*! \brief Configuration of XDP socket. */ typedef struct knot_xdp_config knot_xdp_config_t; +/*! \brief Various statistics of an XDP socket (optimally kernel >=5.9). */ +typedef struct { + /*! Interface name. */ + const char *if_name; + /*! Interface name index (derived from ifname). */ + int if_index; + /*! Network card queue id. */ + unsigned if_queue; + /*! Counters (xdp_statistics) retrieved from the kernel via XDP_STATISTICS. */ + struct { + /*! Dropped for other reasons. */ + uint64_t rx_dropped; + /*! Dropped due to invalid descriptor. */ + uint64_t rx_invalid; + /*! Dropped due to invalid descriptor. */ + uint64_t tx_invalid; + /*! Dropped due to rx ring being full. */ + uint64_t rx_full; + /*! Failed to retrieve item from fill ring. */ + uint64_t fq_empty; + /*! Failed to retrieve item from tx ring. */ + uint64_t tx_empty; + } socket; + /*! States of rings of the XDP socket. */ + struct { + /*! Busy TX buffers. */ + uint16_t tx_busy; + /*! Free buffers to consume from FQ ring. */ + uint16_t fq_fill; + /*! Pending buffers in TX ring. */ + uint16_t rx_fill; + /*! Pending buffers in RX ring. */ + uint16_t tx_fill; + /*! Pending buffers in CQ ring. */ + uint16_t cq_fill; + } rings; +} knot_xdp_stats_t; + /*! * \brief Initialize XDP socket. * @@ -196,4 +236,14 @@ void knot_xdp_recv_finish(knot_xdp_socket_t *socket, const knot_xdp_msg_t msgs[] */ void knot_xdp_socket_info(const knot_xdp_socket_t *socket, FILE *file); +/*! + * \brief Gets various statistics of the XDP socket. + * + * \param socket XDP socket. + * \param stats Output structure. + * + * \return KNOT_E* + */ +int knot_xdp_socket_stats(knot_xdp_socket_t *socket, knot_xdp_stats_t *stats); + /*! @} */ diff --git a/src/libknot/yparser/ypschema.h b/src/libknot/yparser/ypschema.h index 57ced72..7fca93e 100644 --- a/src/libknot/yparser/ypschema.h +++ b/src/libknot/yparser/ypschema.h @@ -130,6 +130,8 @@ typedef union { int64_t dflt; /*! Possible unit type. */ yp_style_t unit; + /*! Alternative default value. */ + int64_t dflt_alt; } i; /*! Boolean variables. */ struct { diff --git a/src/libknot/yparser/yptrafo.c b/src/libknot/yparser/yptrafo.c index 60b3717..764a5d1 100644 --- a/src/libknot/yparser/yptrafo.c +++ b/src/libknot/yparser/yptrafo.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,25 +31,31 @@ #include "contrib/wire_ctx.h" enum { - UNIT_BYTE = 'B', - UNIT_KILO = 'K', - UNIT_MEGA = 'M', - UNIT_GIGA = 'G', - UNIT_SEC = 's', - UNIT_MIN = 'm', - UNIT_HOUR = 'h', - UNIT_DAY = 'd' + UNIT_BYTE = 'B', + UNIT_KILO = 'K', + UNIT_MEGA = 'M', + UNIT_GIGA = 'G', + UNIT_SEC = 's', + UNIT_MIN = 'm', + UNIT_HOUR = 'h', + UNIT_DAY = 'd', + UNIT_WEEK = 'w', + UNIT_MONTH = 'M', + UNIT_YEAR = 'y', }; enum { - MULTI_BYTE = 1, - MULTI_KILO = 1024, - MULTI_MEGA = 1024 * 1024, - MULTI_GIGA = 1024 * 1024 * 1024, - MULTI_SEC = 1, - MULTI_MIN = 60, - MULTI_HOUR = 3600, - MULTI_DAY = 24 * 3600 + MULTI_BYTE = 1, + MULTI_KILO = 1024, + MULTI_MEGA = 1024 * 1024, + MULTI_GIGA = 1024 * 1024 * 1024, + MULTI_SEC = 1, + MULTI_MIN = 60, + MULTI_HOUR = 3600, + MULTI_DAY = 24 * 3600, + MULTI_WEEK = MULTI_DAY * 7, + MULTI_MONTH = MULTI_DAY * 30, + MULTI_YEAR = MULTI_DAY * 365, }; static wire_ctx_t copy_in( @@ -186,6 +192,15 @@ static int remove_unit( case UNIT_DAY: multiplier = MULTI_DAY; break; + case UNIT_WEEK: + multiplier = MULTI_WEEK; + break; + case UNIT_MONTH: + multiplier = MULTI_MONTH; + break; + case UNIT_YEAR: + multiplier = MULTI_YEAR; + break; default: return KNOT_EINVAL; } @@ -295,9 +310,18 @@ static void add_unit( } else if (*number < MULTI_DAY) { multiplier = MULTI_HOUR; new_unit = UNIT_HOUR; - } else { + } else if (*number < MULTI_WEEK) { multiplier = MULTI_DAY; new_unit = UNIT_DAY; + } else if (*number < MULTI_MONTH) { + multiplier = MULTI_WEEK; + new_unit = UNIT_WEEK; + } else if (*number < MULTI_YEAR) { + multiplier = MULTI_MONTH; + new_unit = UNIT_MONTH; + } else { + multiplier = MULTI_YEAR; + new_unit = UNIT_YEAR; } } diff --git a/src/libzscanner/version.h b/src/libzscanner/version.h index f24b3a9..05ab471 100644 --- a/src/libzscanner/version.h +++ b/src/libzscanner/version.h @@ -17,8 +17,8 @@ #pragma once #define ZSCANNER_VERSION_MAJOR 3 -#define ZSCANNER_VERSION_MINOR 3 -#define ZSCANNER_VERSION_PATCH 0x09 +#define ZSCANNER_VERSION_MINOR 4 +#define ZSCANNER_VERSION_PATCH 0x00 #define ZSCANNER_VERSION_HEX ((ZSCANNER_VERSION_MAJOR << 16) | \ (ZSCANNER_VERSION_MINOR << 8) | \ diff --git a/src/utils/Makefile.inc b/src/utils/Makefile.inc index 3097050..1f11282 100644 --- a/src/utils/Makefile.inc +++ b/src/utils/Makefile.inc @@ -103,7 +103,11 @@ kxdpgun_SOURCES = \ utils/kxdpgun/ip_route.h \ utils/kxdpgun/load_queries.c \ utils/kxdpgun/load_queries.h \ - utils/kxdpgun/main.c + utils/kxdpgun/main.c \ + utils/kxdpgun/main.h \ + utils/kxdpgun/stats.c \ + utils/kxdpgun/stats.h + kxdpgun_CPPFLAGS = $(libknotus_la_CPPFLAGS) $(libmnl_CFLAGS) kxdpgun_LDADD = libknot.la $(libcontrib_LIBS) $(libmnl_LIBS) $(pthread_LIBS) diff --git a/src/utils/common/msg.h b/src/utils/common/msg.h index d2ed57e..fbd6c8e 100644 --- a/src/utils/common/msg.h +++ b/src/utils/common/msg.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,10 +23,10 @@ #define WARNING_ ";; WARNING: " #define DEBUG_ ";; DEBUG: " -#define ERR(msg, ...) { fprintf(stderr, ERROR_ msg "\n", ##__VA_ARGS__); fflush(stderr); } -#define INFO(msg, ...) { fprintf(stdout, INFO_ msg "\n", ##__VA_ARGS__); fflush(stdout); } -#define WARN(msg, ...) { fprintf(stderr, WARNING_ msg "\n", ##__VA_ARGS__); fflush(stderr); } -#define DBG(msg, ...) { msg_debug(DEBUG_ msg "\n", ##__VA_ARGS__); fflush(stdout); } +#define ERR(msg, ...) do { fprintf(stderr, ERROR_ msg "\n", ##__VA_ARGS__); fflush(stderr); } while (0) +#define INFO(msg, ...) do { fprintf(stdout, INFO_ msg "\n", ##__VA_ARGS__); fflush(stdout); } while (0) +#define WARN(msg, ...) do { fprintf(stderr, WARNING_ msg "\n", ##__VA_ARGS__); fflush(stderr); } while (0) +#define DBG(msg, ...) do { msg_debug(DEBUG_ msg "\n", ##__VA_ARGS__); fflush(stdout); } while (0) /*! \brief Enable/disable debugging. */ int msg_enable_debug(int val); @@ -37,6 +37,6 @@ int msg_debug(const char *fmt, ...); /*! \brief Debug message for null input. */ #define DBG_NULL DBG("%s: null parameter", __func__) -#define ERR2(msg, ...) { fprintf(stderr, "error: " msg "\n", ##__VA_ARGS__); fflush(stderr); } -#define WARN2(msg, ...) { fprintf(stderr, "warning: " msg "\n", ##__VA_ARGS__); fflush(stderr); } -#define INFO2(msg, ...) { fprintf(stdout, msg "\n", ##__VA_ARGS__); fflush(stdout); } +#define ERR2(msg, ...) do { fprintf(stderr, "error: " msg "\n", ##__VA_ARGS__); fflush(stderr); } while (0) +#define WARN2(msg, ...) do { fprintf(stderr, "warning: " msg "\n", ##__VA_ARGS__); fflush(stderr); } while (0) +#define INFO2(msg, ...) do { fprintf(stdout, msg "\n", ##__VA_ARGS__); fflush(stdout); } while (0) diff --git a/src/utils/common/netio.c b/src/utils/common/netio.c index eed14ee..8ea7b59 100644 --- a/src/utils/common/netio.c +++ b/src/utils/common/netio.c @@ -32,6 +32,7 @@ #include "utils/common/msg.h" #include "utils/common/tls.h" #include "libknot/libknot.h" +#include "libknot/quic/tls_common.h" #include "contrib/net.h" #include "contrib/proxyv2/proxyv2.h" #include "contrib/sockaddr.h" @@ -521,8 +522,8 @@ int net_connect(net_t *net) #endif //LIBNGHTTP2 { // Establish TLS connection. - ret = tls_ctx_setup_remote_endpoint(&net->tls, &dot_alpn, 1, NULL, - net_get_remote(net)); + ret = tls_ctx_setup_remote_endpoint(&net->tls, &dot_alpn, 1, + KNOT_TLS_PRIORITIES, net_get_remote(net)); if (ret != 0) { net_close(net); return ret; @@ -546,7 +547,7 @@ int net_connect(net_t *net) return ret; } ret = tls_ctx_setup_remote_endpoint(&net->tls, - &doq_alpn, 1, QUIC_PRIORITY, net_get_remote(net)); + &doq_alpn, 1, KNOT_TLS_PRIORITIES, net_get_remote(net)); if (ret != 0) { net_close(net); return ret; diff --git a/src/utils/common/params.c b/src/utils/common/params.c index d16af4c..fe5a854 100644 --- a/src/utils/common/params.c +++ b/src/utils/common/params.c @@ -21,7 +21,7 @@ #include #ifdef LIBIDN -#include LIBIDN_HEADER +#include #endif #include "utils/common/params.h" diff --git a/src/utils/common/params.h b/src/utils/common/params.h index 8b7565e..bb071aa 100644 --- a/src/utils/common/params.h +++ b/src/utils/common/params.h @@ -22,6 +22,7 @@ #include #include "libknot/libknot.h" +#include "contrib/string.h" #include "contrib/ucw/lists.h" #define DEFAULT_IPV4_NAME "127.0.0.1" @@ -31,7 +32,7 @@ #define DEFAULT_DNS_QUIC_PORT "853" #define DEFAULT_DNS_TLS_PORT "853" #define DEFAULT_UDP_SIZE 512 -#define DEFAULT_EDNS_SIZE 4096 +#define DEFAULT_EDNS_SIZE 1232 #define MAX_PACKET_SIZE 65535 #define SEP_CHARS "\n\t " @@ -118,9 +119,15 @@ typedef struct { param_handle_f handler; } param_t; -inline static void print_version(const char *program_name) +inline static void print_version(const char *prog_name, bool verbose) { - printf("%s (Knot DNS), version %s\n", program_name, PACKAGE_VERSION); + if (prog_name != NULL) { + printf("%s, ", prog_name); + } + printf("Knot DNS %s\n", PACKAGE_VERSION); + if (verbose) { + printf("\n%s\n", configure_summary); + } } /*! diff --git a/src/utils/common/quic.h b/src/utils/common/quic.h index fd70d27..2b860c3 100644 --- a/src/utils/common/quic.h +++ b/src/utils/common/quic.h @@ -35,10 +35,6 @@ void quic_params_clean(quic_params_t *params); #include "utils/common/tls.h" -#define QUIC_DEFAULT_VERSION "-VERS-ALL:+VERS-TLS1.3" -#define QUIC_DEFAULT_GROUPS "-GROUP-ALL:+GROUP-X25519:+GROUP-SECP256R1:+GROUP-SECP384R1:+GROUP-SECP521R1" -#define QUIC_PRIORITY "%DISABLE_TLS13_COMPAT_MODE:NORMAL:"QUIC_DEFAULT_VERSION":"QUIC_DEFAULT_GROUPS - typedef enum { CLOSED, // Initialized CONNECTED, // RTT-0 diff --git a/src/utils/common/tls.c b/src/utils/common/tls.c index 276ae16..4c9a588 100644 --- a/src/utils/common/tls.c +++ b/src/utils/common/tls.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -398,7 +398,7 @@ int tls_certificate_verification(tls_ctx_t *ctx) }; size_t data_count = (ctx->params->hostname != NULL) ? 2 : 1; if (data_count == 1) { - WARN("TLS, no hostname provided, will not verify certificate owner") + WARN("TLS, no hostname provided, will not verify certificate owner"); } unsigned int status; @@ -533,7 +533,8 @@ int tls_ctx_setup_remote_endpoint(tls_ctx_t *ctx, const gnutls_datum_t *alpn, } if (priority != NULL) { - ret = gnutls_priority_set_direct(ctx->session, priority, NULL); + ret = gnutls_set_default_priority_append(ctx->session, priority, + NULL, 0); } else { ret = gnutls_set_default_priority(ctx->session); } diff --git a/src/utils/kcatalogprint/main.c b/src/utils/kcatalogprint/main.c index 0172347..85e50b6 100644 --- a/src/utils/kcatalogprint/main.c +++ b/src/utils/kcatalogprint/main.c @@ -108,7 +108,7 @@ int main(int argc, char *argv[]) { "catalog", required_argument, NULL, 'a' }, { "member", required_argument, NULL, 'm' }, { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, + { "version", optional_argument, NULL, 'V' }, { NULL } }; @@ -116,7 +116,7 @@ int main(int argc, char *argv[]) signal_init_std(); int opt = 0; - while ((opt = getopt_long(argc, argv, "c:C:D:a:m:hV", opts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "c:C:D:a:m:hV::", opts, NULL)) != -1) { switch (opt) { case 'c': if (util_conf_init_file(optarg) != KNOT_EOK) { @@ -147,7 +147,7 @@ int main(int argc, char *argv[]) print_help(); goto success; case 'V': - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, optarg != NULL); goto success; default: print_help(); @@ -155,13 +155,9 @@ int main(int argc, char *argv[]) } } - // Backward compatibility. if (argc - optind > 0) { - WARN2("obsolete parameter specified"); - if (util_conf_init_justdb("catalog-db", argv[optind]) != KNOT_EOK) { - goto failure; - } - optind++; + print_help(); + goto failure; } if (util_conf_init_default(true) != KNOT_EOK) { diff --git a/src/utils/kdig/kdig_params.c b/src/utils/kdig/kdig_params.c index c8fd83f..8566848 100644 --- a/src/utils/kdig/kdig_params.c +++ b/src/utils/kdig/kdig_params.c @@ -1690,7 +1690,7 @@ query_t *query_create(const char *owner, const query_t *conf) query->style.style.now = knot_time(); query->idn = true; query->nsid = false; - query->edns = -1; + query->edns = 0; query->cc.len = 0; query->sc.len = 0; query->badcookie = BADCOOKIE_RETRY_MAX; @@ -2517,12 +2517,7 @@ static int parse_opt1(const char *opt, const char *value, kdig_params_t *params, *index += add; break; case 'V': - if (len > 1) { - ERR("invalid option -%s", opt); - return KNOT_ENOTSUP; - } - - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, len > 1); params->stop = true; break; case 'x': @@ -2598,8 +2593,8 @@ static int parse_opt1(const char *opt, const char *value, kdig_params_t *params, if (strcmp(opt, "-help") == 0) { print_help(); params->stop = true; - } else if (strcmp(opt, "-version") == 0) { - print_version(PROGRAM_NAME); + } else if (strncmp(opt, "-version", 8) == 0) { + print_version(PROGRAM_NAME, strlen(opt) > 9); params->stop = true; } else { ERR("invalid option: -%s", opt); diff --git a/src/utils/keymgr/bind_privkey.c b/src/utils/keymgr/bind_privkey.c index 9ab895c..bbb61a5 100644 --- a/src/utils/keymgr/bind_privkey.c +++ b/src/utils/keymgr/bind_privkey.c @@ -281,9 +281,7 @@ static int rsa_params_to_pem(const bind_privkey_t *params, dnssec_binary_t *pem) static gnutls_ecc_curve_t choose_ecdsa_curve(size_t pubkey_size) { switch (pubkey_size) { -#ifdef HAVE_ED25519 case 32: return GNUTLS_ECC_CURVE_ED25519; -#endif #ifdef HAVE_ED448 case 57: return GNUTLS_ECC_CURVE_ED448; #endif @@ -334,7 +332,6 @@ static int ecdsa_params_to_pem(dnssec_key_t *dnskey, const bind_privkey_t *param return dnssec_pem_from_x509(key, pem); } -#if defined(HAVE_ED25519) || defined(HAVE_ED448) static void eddsa_extract_public_params(dnssec_key_t *key, gnutls_ecc_curve_t *curve, gnutls_datum_t *x) { @@ -371,7 +368,6 @@ static int eddsa_params_to_pem(dnssec_key_t *dnskey, const bind_privkey_t *param return dnssec_pem_from_x509(key, pem); } -#endif int bind_privkey_to_pem(dnssec_key_t *key, bind_privkey_t *params, dnssec_binary_t *pem) { @@ -385,15 +381,11 @@ int bind_privkey_to_pem(dnssec_key_t *key, bind_privkey_t *params, dnssec_binary case DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256: case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384: return ecdsa_params_to_pem(key, params, pem); -#ifdef HAVE_ED25519 case DNSSEC_KEY_ALGORITHM_ED25519: -#endif #ifdef HAVE_ED448 case DNSSEC_KEY_ALGORITHM_ED448: #endif -#if defined(HAVE_ED25519) || defined(HAVE_ED448) return eddsa_params_to_pem(key, params, pem); -#endif default: return DNSSEC_INVALID_KEY_ALGORITHM; } diff --git a/src/utils/keymgr/main.c b/src/utils/keymgr/main.c index b46aaa0..999b5c5 100644 --- a/src/utils/keymgr/main.c +++ b/src/utils/keymgr/main.c @@ -333,11 +333,10 @@ int main(int argc, char *argv[]) { "tsig", required_argument, NULL, 't' }, { "extended", no_argument, NULL, 'e' }, { "list", no_argument, NULL, 'l' }, - { "brief", no_argument, NULL, 'b' }, // Legacy. { "mono", no_argument, NULL, 'x' }, { "color", no_argument, NULL, 'X' }, { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, + { "version", optional_argument, NULL, 'V' }, { "json", no_argument, NULL, 'j' }, { NULL } }; @@ -358,7 +357,7 @@ int main(int argc, char *argv[]) list_params.color = isatty(STDOUT_FILENO); int opt = 0, parm = 0; - while ((opt = getopt_long(argc, argv, "c:C:D:t:ejlbxXhV", opts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "c:C:D:t:ejlxXhV::", opts, NULL)) != -1) { switch (opt) { case 'c': if (util_conf_init_file(optarg) != KNOT_EOK) { @@ -394,9 +393,6 @@ int main(int argc, char *argv[]) case 'l': just_list = true; break; - case 'b': - WARN2("option '--brief' is deprecated and enabled by default"); - break; case 'x': list_params.color = false; break; @@ -407,7 +403,7 @@ int main(int argc, char *argv[]) print_help(); goto success; case 'V': - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, optarg != NULL); goto success; default: print_help(); diff --git a/src/utils/keymgr/offline_ksk.c b/src/utils/keymgr/offline_ksk.c index b4260b9..05b2d2b 100644 --- a/src/utils/keymgr/offline_ksk.c +++ b/src/utils/keymgr/offline_ksk.c @@ -37,6 +37,8 @@ static int pregenerate_once(kdnssec_ctx_t *ctx, knot_time_t *next) { zone_sign_reschedule_t resch = { 0 }; + memset(ctx->stats, 0, sizeof(*ctx->stats)); + // generate ZSKs int ret = knot_dnssec_key_rollover(ctx, KEY_ROLL_ALLOW_ZSK_ROLL | KEY_ROLL_PRESERVE_FUTURE, &resch); if (ret != KNOT_EOK) { @@ -245,6 +247,9 @@ static int ksr_once(kdnssec_ctx_t *ctx, char **buf, size_t *buf_size, knot_time_ { knot_rrset_t *dnskey = NULL; zone_keyset_t keyset = { 0 }; + + memset(ctx->stats, 0, sizeof(*ctx->stats)); + int ret = load_dnskey_rrset(ctx, &dnskey, &keyset); if (ret != KNOT_EOK) { goto done; @@ -322,10 +327,10 @@ static int ksr_sign_dnskey(kdnssec_ctx_t *ctx, knot_rrset_t *zsk, knot_time_t no zone_keyset_t keyset = { 0 }; char *buf = NULL; size_t buf_size = 4096; - knot_time_t rrsigs_expire = 0; ctx->now = now; ctx->policy->dnskey_ttl = zsk->ttl; + memset(ctx->stats, 0, sizeof(*ctx->stats)); knot_timediff_t rrsig_refresh = ctx->policy->rrsig_refresh_before; if (rrsig_refresh == UINT32_MAX) { // not setting rrsig-refresh prohibited by documentation, but we need to do something @@ -352,7 +357,7 @@ static int ksr_sign_dnskey(kdnssec_ctx_t *ctx, knot_rrset_t *zsk, knot_time_t no // no check if the KSK used for signing (in keyset) is contained in DNSKEY record being signed (in KSR) ! for (int i = 0; i < keyset.count; i++) { - ret = key_records_sign(&keyset.keys[i], &r, ctx, &rrsigs_expire); + ret = key_records_sign(&keyset.keys[i], &r, ctx); if (ret != KNOT_EOK) { goto done; } @@ -362,7 +367,7 @@ static int ksr_sign_dnskey(kdnssec_ctx_t *ctx, knot_rrset_t *zsk, knot_time_t no print_header("SignedKeyResponse "KSR_SKR_VER, ctx->now, buf); *next_sign = knot_time_min( knot_get_next_zone_key_event(&keyset), - knot_time_add(rrsigs_expire, -rrsig_refresh) + knot_time_add(ctx->stats->expire, -rrsig_refresh) ); } @@ -446,6 +451,7 @@ static void skr_import_header(zs_scanner_t *sc) // trailing header without timestamp next_timestamp = 0; } + knot_time_t validity_ts = next_timestamp != 0 ? next_timestamp : ctx->timestamp; // delete possibly existing conflicting offline records ctx->ret = kasp_db_delete_offline_records( @@ -454,16 +460,11 @@ static void skr_import_header(zs_scanner_t *sc) // store previous SKR if (ctx->timestamp > 0 && ctx->ret == KNOT_EOK) { - ctx->ret = key_records_verify(&ctx->r, ctx->kctx, ctx->timestamp); + ctx->ret = key_records_verify(&ctx->r, ctx->kctx, ctx->timestamp, validity_ts); if (ctx->ret != KNOT_EOK) { return; } - if (next_timestamp > 0) { - ctx->ret = key_records_verify(&ctx->r, ctx->kctx, next_timestamp - 1); - if (ctx->ret != KNOT_EOK) { - return; - } - } + ctx->ret = kasp_db_store_offline_records(ctx->kctx->kasp_db, ctx->timestamp, &ctx->r); key_records_clear_rdatasets(&ctx->r); @@ -490,20 +491,14 @@ static void skr_validate_header(zs_scanner_t *sc) // trailing header without timestamp next_timestamp = 0; } + knot_time_t validity_ts = next_timestamp != 0 ? next_timestamp : ctx->timestamp; if (ctx->timestamp > 0 && ctx->ret == KNOT_EOK) { - int ret = key_records_verify(&ctx->r, ctx->kctx, ctx->timestamp); + int ret = key_records_verify(&ctx->r, ctx->kctx, ctx->timestamp, validity_ts); if (ret != KNOT_EOK) { // ctx->ret untouched ERR2("invalid SignedKeyResponse for %"KNOT_TIME_PRINTF" (%s)", ctx->timestamp, knot_strerror(ret)); } - if (next_timestamp > 0) { - ret = key_records_verify(&ctx->r, ctx->kctx, next_timestamp - 1); - if (ret != KNOT_EOK) { // ctx->ret untouched - ERR2("invalid SignedKeyResponse for %"KNOT_TIME_PRINTF" (%s)", - next_timestamp - 1, knot_strerror(ret)); - } - } key_records_clear_rdatasets(&ctx->r); } diff --git a/src/utils/khost/khost_params.c b/src/utils/khost/khost_params.c index 1423e09..de95d9b 100644 --- a/src/utils/khost/khost_params.c +++ b/src/utils/khost/khost_params.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -251,14 +251,14 @@ int khost_parse(kdig_params_t *params, int argc, char *argv[]) // Long options. struct option opts[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + { "version", optional_argument, NULL, 'V' }, { NULL } }; // Command line options processing. int opt = 0; - while ((opt = getopt_long(argc, argv, "46adhrsTvVwc:t:R:W:", opts, NULL)) + while ((opt = getopt_long(argc, argv, "46adhrsTvV::wc:t:R:W:", opts, NULL)) != -1) { switch (opt) { case '4': @@ -294,7 +294,7 @@ int khost_parse(kdig_params_t *params, int argc, char *argv[]) conf->style.show_footer = true; break; case 'V': - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, optarg != NULL); params->stop = false; return KNOT_EOK; case 'w': diff --git a/src/utils/kjournalprint/main.c b/src/utils/kjournalprint/main.c index 3ba0019..1d633dd 100644 --- a/src/utils/kjournalprint/main.c +++ b/src/utils/kjournalprint/main.c @@ -342,11 +342,10 @@ int main(int argc, char *argv[]) { "zone-list", no_argument, NULL, 'z' }, { "check", no_argument, NULL, 'H' }, { "debug", no_argument, NULL, 'd' }, - { "no-color", no_argument, NULL, 'n' }, { "mono", no_argument, NULL, 'x' }, { "color", no_argument, NULL, 'X' }, { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, + { "version", optional_argument, NULL, 'V' }, { NULL } }; @@ -354,7 +353,7 @@ int main(int argc, char *argv[]) signal_init_std(); int opt = 0; - while ((opt = getopt_long(argc, argv, "c:C:D:l:s:zHdnxXhV", opts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "c:C:D:l:s:zHdxXhV::", opts, NULL)) != -1) { switch (opt) { case 'c': if (util_conf_init_file(optarg) != KNOT_EOK) { @@ -393,7 +392,6 @@ int main(int argc, char *argv[]) case 'd': params.debug = true; break; - case 'n': case 'x': params.color = false; break; @@ -404,7 +402,7 @@ int main(int argc, char *argv[]) print_help(); goto success; case 'V': - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, optarg != NULL); goto success; default: print_help(); @@ -412,15 +410,6 @@ int main(int argc, char *argv[]) } } - // Backward compatibility. - if ((justlist && (argc - optind > 0)) || (!justlist && (argc - optind > 1))) { - WARN2("obsolete parameter specified"); - if (util_conf_init_justdb("journal-db", argv[optind]) != KNOT_EOK) { - goto failure; - } - optind++; - } - signal_ctx.color = params.color; if (util_conf_init_default(true) != KNOT_EOK) { diff --git a/src/utils/knotc/commands.c b/src/utils/knotc/commands.c index c2c25a2..5cc1a14 100644 --- a/src/utils/knotc/commands.c +++ b/src/utils/knotc/commands.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -51,6 +51,7 @@ #define CMD_ZONE_BACKUP "zone-backup" #define CMD_ZONE_RESTORE "zone-restore" #define CMD_ZONE_SIGN "zone-sign" +#define CMD_ZONE_VALIDATE "zone-validate" #define CMD_ZONE_KEYS_LOAD "zone-keys-load" #define CMD_ZONE_KEY_ROLL "zone-key-rollover" #define CMD_ZONE_KSK_SBM "zone-ksk-submitted" @@ -99,7 +100,7 @@ static int check_args(cmd_args_t *args, int min, int max) { if (max == 0 && args->argc > 0) { - log_error("command doesn't take arguments"); + log_error("command does not take arguments"); return KNOT_EINVAL; } else if (min == max && args->argc != min) { log_error("command requires %i arguments", min); @@ -272,6 +273,7 @@ static void format_data(cmd_args_t *args, knot_ctl_type_t data_type, case CTL_ZONE_BACKUP: case CTL_ZONE_RESTORE: case CTL_ZONE_SIGN: + case CTL_ZONE_VALIDATE: case CTL_ZONE_KEYS_LOAD: case CTL_ZONE_KEY_ROLL: case CTL_ZONE_KSK_SBM: @@ -411,6 +413,7 @@ static void format_block(ctl_cmd_t cmd, bool failed, bool empty) case CTL_ZONE_BACKUP: case CTL_ZONE_RESTORE: case CTL_ZONE_SIGN: + case CTL_ZONE_VALIDATE: case CTL_ZONE_KEYS_LOAD: case CTL_ZONE_KEY_ROLL: case CTL_ZONE_KSK_SBM: @@ -1294,6 +1297,7 @@ const cmd_desc_t cmd_table[] = { { CMD_ZONE_BACKUP, cmd_zone_filter_ctl, CTL_ZONE_BACKUP, CMD_FOPT_ZONE }, { CMD_ZONE_RESTORE, cmd_zone_filter_ctl, CTL_ZONE_RESTORE, CMD_FOPT_ZONE }, { CMD_ZONE_SIGN, cmd_zone_ctl, CTL_ZONE_SIGN, CMD_FOPT_ZONE }, + { CMD_ZONE_VALIDATE, cmd_zone_ctl, CTL_ZONE_VALIDATE, CMD_FOPT_ZONE }, { CMD_ZONE_KEYS_LOAD, cmd_zone_ctl, CTL_ZONE_KEYS_LOAD, CMD_FOPT_ZONE }, { CMD_ZONE_KEY_ROLL, cmd_zone_key_roll_ctl, CTL_ZONE_KEY_ROLL, CMD_FREQ_ZONE }, { CMD_ZONE_KSK_SBM, cmd_zone_ctl, CTL_ZONE_KSK_SBM, CMD_FREQ_ZONE | CMD_FOPT_ZONE }, @@ -1347,6 +1351,7 @@ static const cmd_help_t cmd_help_table[] = { { CMD_ZONE_BACKUP, "[...] [...] +backupdir ", "Backup zone data and metadata. (#)" }, { CMD_ZONE_RESTORE, "[...] [...] +backupdir ", "Restore zone data and metadata. (#)" }, { CMD_ZONE_SIGN, "[...]", "Re-sign the automatically signed zone. (#)" }, + { CMD_ZONE_VALIDATE, "[...]", "Trigger a DNSSEC validation of the zone. (#)" }, { CMD_ZONE_KEYS_LOAD, "[...]", "Re-load keys from KASP database, sign the zone. (#)" }, { CMD_ZONE_KEY_ROLL, " ksk|zsk", "Trigger immediate key rollover. (#)" }, { CMD_ZONE_KSK_SBM, " ...", "When KSK submission, confirm parent's DS presence. (#)" }, diff --git a/src/utils/knotc/main.c b/src/utils/knotc/main.c index dad3671..274ab6d 100644 --- a/src/utils/knotc/main.c +++ b/src/utils/knotc/main.c @@ -82,7 +82,7 @@ int main(int argc, char **argv) { "color", no_argument, NULL, 'X' }, { "verbose", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, + { "version", optional_argument, NULL, 'V' }, { NULL } }; @@ -97,7 +97,7 @@ int main(int argc, char **argv) /* Parse command line arguments */ int opt = 0; - while ((opt = getopt_long(argc, argv, "+c:C:m:s:t:befxXvhV", opts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "+c:C:m:s:t:befxXvhV::", opts, NULL)) != -1) { switch (opt) { case 'c': params.orig_config = optarg; @@ -147,7 +147,7 @@ int main(int argc, char **argv) print_help(); return EXIT_SUCCESS; case 'V': - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, optarg != NULL); return EXIT_SUCCESS; default: print_help(); diff --git a/src/utils/knotd/main.c b/src/utils/knotd/main.c index d4ebd53..e863296 100644 --- a/src/utils/knotd/main.c +++ b/src/utils/knotd/main.c @@ -38,15 +38,39 @@ #include "knot/conf/conf.h" #include "knot/conf/migration.h" #include "knot/conf/module.h" +#include "knot/common/dbus.h" #include "knot/common/log.h" #include "knot/common/process.h" #include "knot/common/stats.h" #include "knot/common/systemd.h" #include "knot/server/server.h" #include "knot/server/tcp-handler.h" +#include "utils/common/params.h" #define PROGRAM_NAME "knotd" +typedef enum { + CONCURRENT_EMPTY = 0, // fresh cctx without a thread. + CONCURRENT_ASSIGNED, // cctx assigned to process a command. + CONCURRENT_RUNNING, // ctl command is being processed in the thread. + CONCURRENT_IDLE, // command has been processed, waiting for a new one. + CONCURRENT_KILLED, // cctx cleanup has started. + CONCURRENT_FINISHED, // after having been killed, the thread is being joined. +} concurrent_ctl_state_t; + +typedef struct { + concurrent_ctl_state_t state; + pthread_mutex_t mutex; // Protects .state. + pthread_cond_t cond; + knot_ctl_t *ctl; + server_t *server; + pthread_t thread; + sigset_t sigmask; + int ret; + int thread_idx; + bool exclusive; +} concurrent_ctl_ctx_t; + /* Signal flags. */ static volatile bool sig_req_stop = false; static volatile bool sig_req_reload = false; @@ -161,13 +185,14 @@ static void setup_signals(void) sigdelset(&all, SIGBUS); sigdelset(&all, SIGFPE); sigdelset(&all, SIGSEGV); - pthread_sigmask(SIG_SETMASK, &all, NULL); /* Setup handlers. */ struct sigaction action = { .sa_handler = handle_signal }; for (const struct signal *s = SIGNALS; s->signum > 0; s++) { sigaction(s->signum, &action, NULL); } + + pthread_sigmask(SIG_SETMASK, &all, NULL); } /*! \brief Unblock server control signals. */ @@ -185,6 +210,24 @@ static void enable_signals(void) pthread_sigmask(SIG_UNBLOCK, &mask, NULL); } +/*! \brief Create a control thread with correct signals setting. */ +static void create_thread_sigmask(pthread_t *thr, void *(*fcn)(void*), void *ctx, + sigset_t *out_mask) +{ + /* Block all blockable signals. */ + sigset_t mask; + sigfillset(&mask); + sigdelset(&mask, SIGBUS); + sigdelset(&mask, SIGFPE); + sigdelset(&mask, SIGILL); + sigdelset(&mask, SIGSEGV); + pthread_sigmask(SIG_SETMASK, &mask, out_mask); + + pthread_create(thr, NULL, fcn, ctx); + + pthread_sigmask(SIG_SETMASK, out_mask, NULL); +} + /*! \brief Drop POSIX 1003.1e capabilities. */ static void drop_capabilities(void) { @@ -224,6 +267,7 @@ static void check_loaded(server_t *server) return; } + rcu_read_lock(); knot_zonedb_iter_t *it = knot_zonedb_iter_begin(server->zone_db); while (!knot_zonedb_iter_finished(it)) { zone_t *zone = (zone_t *)knot_zonedb_iter_val(it); @@ -234,9 +278,162 @@ static void check_loaded(server_t *server) knot_zonedb_iter_next(it); } knot_zonedb_iter_free(it); + rcu_read_unlock(); finished = true; - systemd_emit_running(true); + dbus_emit_running(true); +} + +static void *ctl_process_thread(void *arg); + +/*! + * Try to find an empty ctl processing context and if successful, + * prepare to lauch the incomming command processing in it. + * + * \param[in] concurrent_ctxs Configured concurrent control contexts. + * \param[in] n_ctxs Number of configured concurrent control contexts. + * \param[in] ctl Control context. + * + * \return Assigned concurrent control context, or NULL. + */ + +static concurrent_ctl_ctx_t *find_free_ctx(concurrent_ctl_ctx_t *concurrent_ctxs, + size_t n_ctxs, knot_ctl_t *ctl) +{ + concurrent_ctl_ctx_t *res = NULL; + for (size_t i = 0; i < n_ctxs && res == NULL; i++) { + concurrent_ctl_ctx_t *cctx = &concurrent_ctxs[i]; + pthread_mutex_lock(&cctx->mutex); + if (cctx->exclusive) { + while (cctx->state != CONCURRENT_IDLE) { + pthread_cond_wait(&cctx->cond, &cctx->mutex); + } + knot_ctl_free(cctx->ctl); + cctx->ctl = knot_ctl_clone(ctl); + if (cctx->ctl == NULL) { + cctx->exclusive = false; + pthread_mutex_unlock(&cctx->mutex); + break; + } + cctx->state = CONCURRENT_ASSIGNED; + res = cctx; + pthread_cond_broadcast(&cctx->cond); + } + pthread_mutex_unlock(&cctx->mutex); + } + for (size_t i = 0; i < n_ctxs && res == NULL; i++) { + concurrent_ctl_ctx_t *cctx = &concurrent_ctxs[i]; + pthread_mutex_lock(&cctx->mutex); + switch (cctx->state) { + case CONCURRENT_EMPTY: + create_thread_sigmask(&cctx->thread, ctl_process_thread, cctx, &cctx->sigmask); + break; + case CONCURRENT_IDLE: + knot_ctl_free(cctx->ctl); + pthread_cond_broadcast(&cctx->cond); + break; + default: + pthread_mutex_unlock(&cctx->mutex); + continue; + } + cctx->ctl = knot_ctl_clone(ctl); + if (cctx->ctl != NULL) { + cctx->state = CONCURRENT_ASSIGNED; + res = cctx; + } + pthread_mutex_unlock(&cctx->mutex); + } + return res; +} + +static void init_ctxs(concurrent_ctl_ctx_t *concurrent_ctxs, size_t n_ctxs, server_t *server) +{ + for (size_t i = 0; i < n_ctxs; i++) { + concurrent_ctl_ctx_t *cctx = &concurrent_ctxs[i]; + pthread_mutex_init(&cctx->mutex, NULL); + pthread_cond_init(&cctx->cond, NULL); + cctx->server = server; + cctx->thread_idx = i + 1; + } +} + +static int cleanup_ctxs(concurrent_ctl_ctx_t *concurrent_ctxs, size_t n_ctxs) +{ + int ret = KNOT_EOK; + for (size_t i = 0; i < n_ctxs; i++) { + concurrent_ctl_ctx_t *cctx = &concurrent_ctxs[i]; + pthread_mutex_lock(&cctx->mutex); + if (cctx->state == CONCURRENT_IDLE) { + knot_ctl_free(cctx->ctl); + cctx->ctl = NULL; + if (cctx->ret == KNOT_CTL_ESTOP) { + ret = cctx->ret; + } + } + pthread_mutex_unlock(&cctx->mutex); + } + return ret; +} + +static void finalize_ctxs(concurrent_ctl_ctx_t *concurrent_ctxs, size_t n_ctxs) +{ + for (size_t i = 0; i < n_ctxs; i++) { + concurrent_ctl_ctx_t *cctx = &concurrent_ctxs[i]; + pthread_mutex_lock(&cctx->mutex); + if (cctx->state == CONCURRENT_EMPTY) { + pthread_mutex_unlock(&cctx->mutex); + pthread_mutex_destroy(&cctx->mutex); + pthread_cond_destroy(&cctx->cond); + continue; + } + + cctx->state = CONCURRENT_KILLED; + pthread_cond_broadcast(&cctx->cond); + pthread_mutex_unlock(&cctx->mutex); + (void)pthread_join(cctx->thread, NULL); + + assert(cctx->state == CONCURRENT_FINISHED); + knot_ctl_free(cctx->ctl); + pthread_mutex_destroy(&cctx->mutex); + pthread_cond_destroy(&cctx->cond); + } +} + +static void *ctl_process_thread(void *arg) +{ + concurrent_ctl_ctx_t *ctx = arg; + rcu_register_thread(); + setup_signals(); // in fact, this blocks common signals so that they + // arrive to main thread instead of this one + + pthread_mutex_lock(&ctx->mutex); + while (ctx->state != CONCURRENT_KILLED) { + if (ctx->state != CONCURRENT_ASSIGNED) { + pthread_cond_wait(&ctx->cond, &ctx->mutex); + continue; + } + ctx->state = CONCURRENT_RUNNING; + bool exclusive = ctx->exclusive; + pthread_mutex_unlock(&ctx->mutex); + + // Not IDLE, ctx can be read without locking. + int ret = ctl_process(ctx->ctl, ctx->server, ctx->thread_idx, &exclusive); + + pthread_mutex_lock(&ctx->mutex); + ctx->ret = ret; + ctx->exclusive = exclusive; + if (ctx->state == CONCURRENT_RUNNING) { // not KILLED + ctx->state = CONCURRENT_IDLE; + pthread_cond_broadcast(&ctx->cond); + } + } + + knot_ctl_close(ctx->ctl); + + ctx->state = CONCURRENT_FINISHED; + pthread_mutex_unlock(&ctx->mutex); + rcu_unregister_thread(); + return NULL; } /*! \brief Event loop listening for signals and remote commands. */ @@ -274,7 +471,7 @@ static void event_loop(server_t *server, const char *socket, bool daemonize, /* Bind the control socket. */ uint16_t backlog = conf_get_int(conf(), C_CTL, C_BACKLOG); - int ret = knot_ctl_bind2(ctl, listen, backlog); + int ret = knot_ctl_bind(ctl, listen, backlog); if (ret != KNOT_EOK) { knot_ctl_free(ctl); log_fatal("control, failed to bind socket '%s' (%s)", @@ -286,6 +483,10 @@ static void event_loop(server_t *server, const char *socket, bool daemonize, enable_signals(); + concurrent_ctl_ctx_t concurrent_ctxs[CTL_MAX_CONCURRENT] = { 0 }; + init_ctxs(concurrent_ctxs, CTL_MAX_CONCURRENT, server); + bool main_thread_exclusive = false; + /* Notify systemd about successful start. */ systemd_ready_notify(); if (daemonize) { @@ -299,15 +500,19 @@ static void event_loop(server_t *server, const char *socket, bool daemonize, /* Interrupts. */ if (sig_req_reload && !sig_req_stop) { sig_req_reload = false; + pthread_rwlock_wrlock(&server->ctl_lock); server_reload(server, RELOAD_FULL); + pthread_rwlock_unlock(&server->ctl_lock); } if (sig_req_zones_reload && !sig_req_stop) { sig_req_zones_reload = false; reload_t mode = server->catalog_upd_signal ? RELOAD_CATALOG : RELOAD_ZONES; + pthread_rwlock_wrlock(&server->ctl_lock); server->catalog_upd_signal = false; server_update_zones(conf(), server, mode); + pthread_rwlock_unlock(&server->ctl_lock); } - if (sig_req_stop) { + if (sig_req_stop || cleanup_ctxs(concurrent_ctxs, CTL_MAX_CONCURRENT) == KNOT_CTL_ESTOP) { break; } @@ -325,15 +530,20 @@ static void event_loop(server_t *server, const char *socket, bool daemonize, continue; } - ret = ctl_process(ctl, server); - knot_ctl_close(ctl); - if (ret == KNOT_CTL_ESTOP) { - break; + if (main_thread_exclusive || + find_free_ctx(concurrent_ctxs, CTL_MAX_CONCURRENT, ctl) == NULL) { + ret = ctl_process(ctl, server, 0, &main_thread_exclusive); + knot_ctl_close(ctl); + if (ret == KNOT_CTL_ESTOP) { + break; + } } } + finalize_ctxs(concurrent_ctxs, CTL_MAX_CONCURRENT); + if (conf()->cache.srv_dbus_event & DBUS_EVENT_RUNNING) { - systemd_emit_running(false); + dbus_emit_running(false); } /* Unbind the control socket. */ @@ -363,11 +573,6 @@ static void print_help(void) CONF_MAPSIZE, RUN_DIR "/knot.sock"); } -static void print_version(void) -{ - printf("%s (Knot DNS), version %s\n", PROGRAM_NAME, PACKAGE_VERSION); -} - static int set_config(const char *confdb, const char *config, size_t max_conf_size) { if (config != NULL && confdb != NULL) { @@ -440,7 +645,7 @@ int main(int argc, char **argv) { "daemonize", optional_argument, NULL, 'd' }, { "verbose", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, + { "version", optional_argument, NULL, 'V' }, { NULL } }; @@ -449,7 +654,7 @@ int main(int argc, char **argv) /* Parse command line arguments. */ int opt = 0; - while ((opt = getopt_long(argc, argv, "c:C:m:s:dvhV", opts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "c:C:m:s:dvhV::", opts, NULL)) != -1) { switch (opt) { case 'c': config = optarg; @@ -481,7 +686,7 @@ int main(int argc, char **argv) print_help(); return EXIT_SUCCESS; case 'V': - print_version(); + print_version(PROGRAM_NAME, optarg != NULL); return EXIT_SUCCESS; default: print_help(); @@ -570,14 +775,9 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - if (conf()->cache.srv_dbus_event != DBUS_EVENT_NONE) { - ret = systemd_dbus_open(); - if (ret != KNOT_EOK) { - log_error("d-bus: failed to open system bus (%s)", - knot_strerror(ret)); - } else { - log_info("d-bus: connected to system bus"); - } + /* Connect to the system D-bus. */ + if (conf()->cache.srv_dbus_event != DBUS_EVENT_NONE && + dbus_open() == KNOT_EOK) { int64_t delay = conf_get_int(conf(), C_SRV, C_DBUS_INIT_DELAY); sleep(delay); } @@ -595,7 +795,7 @@ int main(int argc, char **argv) server_wait(&server); server_deinit(&server); conf_free(conf()); - systemd_dbus_close(); + dbus_close(); log_close(); dnssec_crypto_cleanup(); return EXIT_FAILURE; @@ -636,7 +836,7 @@ int main(int argc, char **argv) rcu_unregister_thread(); pid_cleanup(); conf_free(conf()); - systemd_dbus_close(); + dbus_close(); log_close(); dnssec_crypto_cleanup(); return EXIT_FAILURE; @@ -660,7 +860,7 @@ int main(int argc, char **argv) /* Unhook from RCU. */ rcu_unregister_thread(); - systemd_dbus_close(); + dbus_close(); log_info("shutting down"); log_close(); diff --git a/src/utils/knsec3hash/knsec3hash.c b/src/utils/knsec3hash/knsec3hash.c index a7bac97..a18498d 100644 --- a/src/utils/knsec3hash/knsec3hash.c +++ b/src/utils/knsec3hash/knsec3hash.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,7 +36,7 @@ */ static void print_help(void) { - printf("Usage: " PROGRAM_NAME " \n"); + printf("Usage: " PROGRAM_NAME " [-h | -V] \n"); printf("Example: " PROGRAM_NAME " c01dcafe 1 10 knot-dns.cz\n"); printf("Alternative usage: "PROGRAM_NAME " \n"); printf("Example: " PROGRAM_NAME " 1 0 10 c01dcafe knot-dns.cz\n"); @@ -103,19 +103,19 @@ static bool parse_nsec3_params(dnssec_nsec3_params_t *params, const char *salt_s int main(int argc, char *argv[]) { struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + { "version", optional_argument, NULL, 'V' }, { NULL } }; int opt = 0; - while ((opt = getopt_long(argc, argv, "hV", options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "hV::", options, NULL)) != -1) { switch(opt) { case 'h': print_help(); return EXIT_SUCCESS; case 'V': - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, optarg != NULL); return EXIT_SUCCESS; default: print_help(); diff --git a/src/utils/knsupdate/knsupdate_exec.c b/src/utils/knsupdate/knsupdate_exec.c index e201711..d716ffb 100644 --- a/src/utils/knsupdate/knsupdate_exec.c +++ b/src/utils/knsupdate/knsupdate_exec.c @@ -452,15 +452,23 @@ static int pkt_sendrecv(knsupdate_params_t *params) return -1; } + ret = net_init_crypto(&net, ¶ms->tls_params, NULL, ¶ms->quic_params); + if (ret != 0) { + ERR("failed to initialize crypto context (%s)", knot_strerror(ret)); + net_clean(&net); + return -1; + } + ret = net_connect(&net); - DBG("%s: send_msg = %d", __func__, net.sockfd); if (ret != KNOT_EOK) { + ERR("failed to connect (%s)", knot_strerror(ret)); net_clean(&net); return -1; } ret = net_send(&net, params->query->wire, params->query->size); if (ret != KNOT_EOK) { + ERR("failed to send update (%s)", knot_strerror(ret)); net_close(&net); net_clean(&net); return -1; @@ -471,8 +479,8 @@ static int pkt_sendrecv(knsupdate_params_t *params) /* Wait for reception. */ int rb = net_receive(&net, params->answer->wire, params->answer->max_size); - DBG("%s: receive_msg = %d", __func__, rb); if (rb <= 0) { + ERR("failed to receive response (%s)", knot_strerror(rb)); net_close(&net); net_clean(&net); return -1; diff --git a/src/utils/knsupdate/knsupdate_params.c b/src/utils/knsupdate/knsupdate_params.c index f9fa41f..5aaf808 100644 --- a/src/utils/knsupdate/knsupdate_params.c +++ b/src/utils/knsupdate/knsupdate_params.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #include "utils/common/netio.h" #include "libknot/libknot.h" #include "libknot/tsig.h" +#include "contrib/base64.h" #include "contrib/mempattern.h" #include "contrib/strtonum.h" #include "contrib/ucw/mempool.h" @@ -90,6 +91,8 @@ static int knsupdate_init(knsupdate_params_t *params) init_list(¶ms->update_list); init_list(¶ms->prereq_list); + tls_params_init(¶ms->tls_params); + /* Initialize memory context. */ mm_ctx_mempool(¶ms->mm, MM_DEFAULT_BLKSIZE); @@ -142,6 +145,9 @@ void knsupdate_clean(knsupdate_params_t *params) knot_pkt_free(params->answer); knot_tsig_key_deinit(¶ms->tsig_key); + tls_params_clean(¶ms->tls_params); + quic_params_clean(¶ms->quic_params); + /* Clean up the structure. */ mp_delete(params->mm.ctx); memset(params, 0, sizeof(*params)); @@ -172,9 +178,31 @@ void knsupdate_reset(knsupdate_params_t *params) static void print_help(void) { - printf("Usage: %s [-d] [-v] [-k keyfile | -y [hmac:]name:key]\n" - " [-p port] [-t timeout] [-r retries] [filename]\n", - PROGRAM_NAME); + printf("Usage:\n" + " %s [-T] [options] [filename]\n" + " %s [-S | -Q] [tls_options] [options] [filename]\n" + "\n" + "Options:\n" + " -T, --tcp Use TCP protocol.\n" + " -S, --tls Use TLS protocol.\n" + " -Q, --quic Use QUIC protocol.\n" + " -p, --port Remote port.\n" + " -r, --retry Number of retries over UDP.\n" + " -t, --timeout Update timeout.\n" + " -y, --tsig TSIG key in the form [alg:]name:key.\n" + " -k, --tsigfile Path to a TSIG key file.\n" + " -d, --debug Debug mode output.\n" + " -h, --help Print the program help.\n" + " -V, --version Print the program version.\n" + "\n" + "QUIC/TLS options:\n" + " -H, --hostname Remote hostname validation.\n" + " -P, --pin Certificate key PIN.\n" + " -A, --ca [] Path to a CA file.\n" + " -E, --certfile Path to a client certificate file.\n" + " -K, --keyfile Path to a client key file.\n" + " -s, --sni Remote SNI.\n", + PROGRAM_NAME, PROGRAM_NAME); } int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) @@ -188,40 +216,74 @@ int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) return ret; } - // Long options. + const char *opts_str = "dhvTSQV::p:r:t:y:k:H:P:A::E:K:s:"; struct option opts[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, + { "debug", no_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "tcp", no_argument, NULL, 'T' }, + { "tls", no_argument, NULL, 'S' }, + { "quic", no_argument, NULL, 'Q' }, + { "version", optional_argument, NULL, 'V' }, + { "port", required_argument, NULL, 'p' }, + { "retry", required_argument, NULL, 'r' }, + { "timeout", required_argument, NULL, 't' }, + { "tsig", required_argument, NULL, 'y' }, + { "tsigfile", required_argument, NULL, 'k' }, + { "hostname", required_argument, NULL, 'H' }, + { "pin", required_argument, NULL, 'P' }, + { "ca", optional_argument, NULL, 'A' }, + { "certfile", required_argument, NULL, 'E' }, + { "keyfile", required_argument, NULL, 'K' }, + { "sni", required_argument, NULL, 's' }, { NULL } }; - /* Command line options processing. */ + bool default_port = true; + int opt = 0; - while ((opt = getopt_long(argc, argv, "dhDvVp:t:r:y:k:", opts, NULL)) - != -1) { + while ((opt = getopt_long(argc, argv, opts_str, opts, NULL)) != -1) { switch (opt) { case 'd': - case 'D': /* Extra debugging. */ msg_enable_debug(1); break; case 'h': print_help(); params->stop = true; return KNOT_EOK; - case 'v': + case 'v': // Compatibility with nsupdate. + case 'T': params->protocol = PROTO_TCP; break; + case 'S': + params->protocol = PROTO_TCP; + + params->tls_params.enable = true; + + if (default_port) { + free(params->server->service); + params->server->service = strdup(DEFAULT_DNS_TLS_PORT); + } + break; + case 'Q': + params->protocol = PROTO_UDP; + + params->tls_params.enable = true; + params->quic_params.enable = true; + + if (default_port) { + free(params->server->service); + params->server->service = strdup(DEFAULT_DNS_QUIC_PORT); + } + break; case 'V': - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, optarg != NULL); params->stop = true; return KNOT_EOK; case 'p': + assert(optarg); + default_port = false; free(params->server->service); params->server->service = strdup(optarg); - if (!params->server->service) { - ERR("failed to set default port '%s'", optarg); - return KNOT_ENOMEM; - } break; case 'r': ret = str_to_u32(optarg, ¶ms->retries); @@ -241,7 +303,7 @@ int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) knot_tsig_key_deinit(¶ms->tsig_key); ret = knot_tsig_key_init_str(¶ms->tsig_key, optarg); if (ret != KNOT_EOK) { - ERR("failed to parse key '%s'", optarg); + ERR("failed to parse TSIG key '%s'", optarg); return ret; } break; @@ -249,9 +311,63 @@ int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) knot_tsig_key_deinit(¶ms->tsig_key); ret = knot_tsig_key_init_file(¶ms->tsig_key, optarg); if (ret != KNOT_EOK) { - ERR("failed to parse keyfile '%s'", optarg); + ERR("failed to parse TSIG keyfile '%s'", optarg); + return ret; + } + break; + case 'H': + assert(optarg); + free(params->tls_params.hostname); + params->tls_params.hostname = strdup(optarg); + break; + case 'P': + assert(optarg); + uint8_t pin[64] = { 0 }; + ret = knot_base64_decode((const uint8_t *)optarg, strlen(optarg), pin, sizeof(pin)); + if (ret < 0) { + ERR("invalid certificate pin %s", optarg); return ret; + } else if (ret != CERT_PIN_LEN) { // Check for 256-bit value. + ERR("invalid SHA256 hash length of certificate pin %s", optarg); + return KNOT_EINVAL; } + + uint8_t *item = malloc(1 + ret); // 1 ~ leading data length. + if (item == NULL) { + return KNOT_ENOMEM; + } + item[0] = ret; + memcpy(&item[1], pin, ret); + + if (ptrlist_add(¶ms->tls_params.pins, item, NULL) == NULL) { + return KNOT_ENOMEM; + } + + break; + case 'A': + if (optarg == NULL) { + params->tls_params.system_ca = true; + break; + } + if (ptrlist_add(¶ms->tls_params.ca_files, strdup(optarg), NULL) == NULL) { + ERR("failed to set CA file '%s'", optarg); + return KNOT_ENOMEM; + } + break; + case 'E': + assert(optarg); + free(params->tls_params.certfile); + params->tls_params.certfile = strdup(optarg); + break; + case 'K': + assert(optarg); + free(params->tls_params.keyfile); + params->tls_params.keyfile = strdup(optarg); + break; + case 's': + assert(optarg); + free(params->tls_params.sni); + params->tls_params.sni = strdup(optarg); break; default: print_help(); @@ -259,8 +375,8 @@ int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) } } - /* No retries for TCP. */ - if (params->protocol == PROTO_TCP) { + /* Retries only for UDP. */ + if (params->protocol == PROTO_TCP || params->quic_params.enable) { params->retries = 0; } else { /* If wait/tries < 1 s, set 1 second for each try. */ @@ -277,7 +393,7 @@ int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]) ptrlist_add(¶ms->qfiles, argv[optind], ¶ms->mm); } - return ret; + return KNOT_EOK; } int knsupdate_set_ttl(knsupdate_params_t *params, const uint32_t ttl) diff --git a/src/utils/knsupdate/knsupdate_params.h b/src/utils/knsupdate/knsupdate_params.h index 1933244..fbf30e5 100644 --- a/src/utils/knsupdate/knsupdate_params.h +++ b/src/utils/knsupdate/knsupdate_params.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,7 +20,9 @@ #include "utils/common/netio.h" #include "utils/common/params.h" +#include "utils/common/quic.h" #include "utils/common/sign.h" +#include "utils/common/tls.h" #include "libknot/libknot.h" #include "libzscanner/scanner.h" #include "contrib/ucw/lists.h" @@ -63,6 +65,10 @@ typedef struct { style_t style; /*!< Memory context. */ knot_mm_t mm; + /*!< TLS params. */ + tls_params_t tls_params; + /*!< QUIC params. */ + quic_params_t quic_params; } knsupdate_params_t; int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[]); diff --git a/src/utils/kxdpgun/load_queries.c b/src/utils/kxdpgun/load_queries.c index 8ecac48..fe7c9ae 100644 --- a/src/utils/kxdpgun/load_queries.c +++ b/src/utils/kxdpgun/load_queries.c @@ -16,9 +16,11 @@ #include #include +#include #include #include #include +#include #include "load_queries.h" #include "libknot/libknot.h" @@ -44,106 +46,181 @@ void free_global_payloads(void) global_payloads = NULL; } -bool load_queries(const char *filename, uint16_t edns_size, uint16_t msgid, size_t maxcount) +typedef struct { + char line[KNOT_DNAME_TXT_MAXLEN + 256]; + char dname_txt[KNOT_DNAME_TXT_MAXLEN + 1]; + uint8_t dname[KNOT_DNAME_MAXLEN]; + char type_txt[128]; + char flags_txt[128]; +} txt_bufs_t; + +typedef struct { + char line[USHRT_MAX]; +} bin_bufs_t; + +static int read_txt(struct pkt_payload **g_payloads_top_p, FILE *f, txt_bufs_t *bufs, + uint16_t edns_size, uint16_t msgid) +{ + assert(g_payloads_top_p != NULL); + struct pkt_payload *g_payloads_top = *g_payloads_top_p; + if (fgets(bufs->line, sizeof(bufs->line), f) == NULL) { + return 0; + } + bufs->flags_txt[0] = '\0'; + int ret = sscanf(bufs->line, "%s%s%s", bufs->dname_txt, bufs->type_txt, + bufs->flags_txt); + if (ret < 2) { + ERR2(ERR_PREFIX "(faulty line): '%.*s'", + (int)strcspn(bufs->line, "\n"), bufs->line); + return KNOT_EINVAL; + } + + void *pret = knot_dname_from_str(bufs->dname, bufs->dname_txt, sizeof(bufs->dname)); + if (pret == NULL) { + ERR2(ERR_PREFIX "(faulty dname): '%s'", bufs->dname_txt); + return KNOT_EINVAL; + } + + uint16_t type; + ret = knot_rrtype_from_string(bufs->type_txt, &type); + if (ret < 0) { + ERR2(ERR_PREFIX "(faulty type): '%s'", bufs->type_txt); + return KNOT_EINVAL; + } + + enum qflags flags = 0; + switch (bufs->flags_txt[0]) { + case '\0': + break; + case 'e': + case 'E': + flags |= QFLAG_EDNS; + break; + case 'd': + case 'D': + flags |= QFLAG_EDNS | QFLAG_DO; + break; + default: + ERR2(ERR_PREFIX "(faulty flag): '%s'", bufs->flags_txt); + return KNOT_EINVAL; + } + + size_t dname_len = knot_dname_size(bufs->dname); + size_t pkt_len = KNOT_WIRE_HEADER_SIZE + 2 * sizeof(uint16_t) + dname_len; + if (flags & QFLAG_EDNS) { + pkt_len += KNOT_EDNS_MIN_SIZE; + } + + struct pkt_payload *pkt = calloc(1, sizeof(*pkt) + pkt_len); + if (pkt == NULL) { + ERR2(ERR_PREFIX "(out of memory)"); + return KNOT_ENOMEM; + } + pkt->len = pkt_len; + memcpy(pkt->payload, &msgid, sizeof(msgid)); + pkt->payload[2] = 0x01; // RD bit + pkt->payload[5] = 0x01; // 1 question + pkt->payload[11] = (flags & QFLAG_EDNS) ? 0x01 : 0x00; + memcpy(pkt->payload + 12, bufs->dname, dname_len); + pkt->payload[dname_len + 12] = type >> 8; + pkt->payload[dname_len + 13] = type & 0xff; + pkt->payload[dname_len + 15] = KNOT_CLASS_IN; + if (flags & QFLAG_EDNS) { + pkt->payload[dname_len + 18] = KNOT_RRTYPE_OPT; + pkt->payload[dname_len + 19] = edns_size >> 8; + pkt->payload[dname_len + 20] = edns_size & 0xff; + pkt->payload[dname_len + 23] = (flags & QFLAG_DO) ? 0x80 : 0x00; + } + + // add pkt to list global_payloads + if (g_payloads_top == NULL) { + global_payloads = pkt; + *g_payloads_top_p = pkt; + } else { + g_payloads_top->next = pkt; + *g_payloads_top_p = pkt; + } + return pkt_len; +} + +static int read_bin(struct pkt_payload **g_payloads_top_p, FILE *f, bin_bufs_t *bufs, + uint16_t msgid) +{ + assert(g_payloads_top_p != NULL); + struct pkt_payload *g_payloads_top = *g_payloads_top_p; + uint16_t size; + if (fread(&size, sizeof(size), 1, f) < 1) { + return 0; + } + size = ntohs(size); + if (fread(bufs->line, size, 1, f) < 1) { + return KNOT_EINVAL; + } + struct pkt_payload *pkt = calloc(1, sizeof(*pkt) + size); + if (pkt == NULL) { + ERR2(ERR_PREFIX "(out of memory)"); + return KNOT_ENOMEM; + } + pkt->len = size; + memcpy(pkt->payload, &msgid, sizeof(msgid)); // Override msgID + memcpy(pkt->payload + 2, bufs->line + 2, size - 2); + + // add pkt to list global_payloads + if (g_payloads_top == NULL) { + global_payloads = pkt; + *g_payloads_top_p = pkt; + } else { + g_payloads_top->next = pkt; + *g_payloads_top_p = pkt; + } + return size; +} + +bool load_queries(const input_t *input, uint16_t edns_size, uint16_t msgid, size_t maxcount) { size_t read = 0; - FILE *f = fopen(filename, "r"); + FILE *f = fopen(input->path, (input->format == BIN) ? "rb" : "r"); if (f == NULL) { - ERR2(ERR_PREFIX "file '%s' (%s)", filename, strerror(errno)); + ERR2(ERR_PREFIX "file '%s' (%s)", input->path, strerror(errno)); return false; } - struct pkt_payload *g_payloads_top = NULL; - struct { - char line[KNOT_DNAME_TXT_MAXLEN + 256]; - char dname_txt[KNOT_DNAME_TXT_MAXLEN + 1]; - uint8_t dname[KNOT_DNAME_MAXLEN]; - char type_txt[128]; - char flags_txt[128]; - } *bufs; - bufs = malloc(sizeof(*bufs)); // avoiding too much stuff on stack + void *bufs = NULL; + switch (input->format) { + case TXT: + bufs = malloc(sizeof(txt_bufs_t)); // avoiding too much stuff on stack + break; + case BIN: + bufs = malloc(sizeof(bin_bufs_t)); + break; + default: + assert(0); + goto fail; + } if (bufs == NULL) { ERR2(ERR_PREFIX "(out of memory)"); goto fail; } + struct pkt_payload *g_payloads_top = NULL; while (read < maxcount) { - if (fgets(bufs->line, sizeof(bufs->line), f) == NULL) { + int ret = 0; + switch (input->format) { + case TXT: + ret = read_txt(&g_payloads_top, f, bufs, edns_size, msgid); break; - } - bufs->flags_txt[0] = '\0'; - int ret = sscanf(bufs->line, "%s%s%s", bufs->dname_txt, bufs->type_txt, bufs->flags_txt); - if (ret < 2) { - ERR2(ERR_PREFIX "(faulty line): '%.*s'", - (int)strcspn(bufs->line, "\n"), bufs->line); - goto fail; - } - - void *pret = knot_dname_from_str(bufs->dname, bufs->dname_txt, sizeof(bufs->dname)); - if (pret == NULL) { - ERR2(ERR_PREFIX "(faulty dname): '%s'", bufs->dname_txt); - goto fail; - } - - uint16_t type; - ret = knot_rrtype_from_string(bufs->type_txt, &type); - if (ret < 0) { - ERR2(ERR_PREFIX "(faulty type): '%s'", bufs->type_txt); - goto fail; - } - - enum qflags flags = 0; - switch (bufs->flags_txt[0]) { - case '\0': - break; - case 'e': - case 'E': - flags |= QFLAG_EDNS; - break; - case 'd': - case 'D': - flags |= QFLAG_EDNS | QFLAG_DO; + case BIN: + ret = read_bin(&g_payloads_top, f, bufs, msgid); break; default: - ERR2(ERR_PREFIX "(faulty flag): '%s'", bufs->flags_txt); - goto fail; - } - - size_t dname_len = knot_dname_size(bufs->dname); - size_t pkt_len = KNOT_WIRE_HEADER_SIZE + 2 * sizeof(uint16_t) + dname_len; - if (flags & QFLAG_EDNS) { - pkt_len += KNOT_EDNS_MIN_SIZE; + ret = -1; + break; } - - struct pkt_payload *pkt = calloc(1, sizeof(struct pkt_payload) + pkt_len); - if (pkt == NULL) { - ERR2(ERR_PREFIX "(out of memory)"); + if (ret == 0) { + break; + } else if (ret < 0) { goto fail; } - pkt->len = pkt_len; - memcpy(pkt->payload, &msgid, sizeof(msgid)); - pkt->payload[2] = 0x01; // RD bit - pkt->payload[5] = 0x01; // 1 question - pkt->payload[11] = (flags & QFLAG_EDNS) ? 0x01 : 0x00; - memcpy(pkt->payload + 12, bufs->dname, dname_len); - pkt->payload[dname_len + 12] = type >> 8; - pkt->payload[dname_len + 13] = type & 0xff; - pkt->payload[dname_len + 15] = KNOT_CLASS_IN; - if (flags & QFLAG_EDNS) { - pkt->payload[dname_len + 18] = KNOT_RRTYPE_OPT; - pkt->payload[dname_len + 19] = edns_size >> 8; - pkt->payload[dname_len + 20] = edns_size & 0xff; - pkt->payload[dname_len + 23] = (flags & QFLAG_DO) ? 0x80 : 0x00; - } - - // add pkt to list global_payloads - if (g_payloads_top == NULL) { - global_payloads = pkt; - g_payloads_top = pkt; - } else { - g_payloads_top->next = pkt; - g_payloads_top = pkt; - } read++; } diff --git a/src/utils/kxdpgun/load_queries.h b/src/utils/kxdpgun/load_queries.h index 3d7bace..09dfee9 100644 --- a/src/utils/kxdpgun/load_queries.h +++ b/src/utils/kxdpgun/load_queries.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,16 @@ #include #include +enum input_format { + TXT = 0, + BIN +}; + +typedef struct { + const char *path; + enum input_format format; +} input_t; + struct pkt_payload { struct pkt_payload *next; size_t len; @@ -27,6 +37,6 @@ struct pkt_payload { extern struct pkt_payload *global_payloads; -bool load_queries(const char *filename, uint16_t edns_size, uint16_t msgid, size_t maxcount); +bool load_queries(const input_t *input, uint16_t edns_size, uint16_t msgid, size_t maxcount); void free_global_payloads(void); diff --git a/src/utils/kxdpgun/main.c b/src/utils/kxdpgun/main.c index 523f64f..4e3aa31 100644 --- a/src/utils/kxdpgun/main.c +++ b/src/utils/kxdpgun/main.c @@ -14,12 +14,15 @@ along with this program. If not, see . */ +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -28,16 +31,11 @@ #include #include #include -#include -#include -#include - -#include -#include -#include #include -#include #include +#include +#include +#include #include "libknot/libknot.h" #include "libknot/xdp.h" @@ -46,101 +44,28 @@ #include #include "libknot/quic/quic.h" #endif // ENABLE_QUIC -#include "contrib/macros.h" -#include "contrib/mempattern.h" -#include "contrib/openbsd/strlcat.h" +#include "contrib/atomic.h" #include "contrib/openbsd/strlcpy.h" #include "contrib/os.h" #include "contrib/sockaddr.h" #include "contrib/toeplitz.h" -#include "contrib/ucw/mempool.h" #include "utils/common/msg.h" #include "utils/common/params.h" #include "utils/kxdpgun/ip_route.h" #include "utils/kxdpgun/load_queries.h" - -#define PROGRAM_NAME "kxdpgun" -#define SPACE " " - -enum { - KXDPGUN_WAIT, - KXDPGUN_START, - KXDPGUN_STOP, -}; +#include "utils/kxdpgun/main.h" +#include "utils/kxdpgun/stats.h" volatile int xdp_trigger = KXDPGUN_WAIT; -volatile unsigned stats_trigger = 0; +volatile knot_atomic_uint64_t stats_trigger = 0; +volatile knot_atomic_bool stats_switch = STATS_SUM; unsigned global_cpu_aff_start = 0; unsigned global_cpu_aff_step = 1; -#define REMOTE_PORT_DEFAULT 53 -#define REMOTE_PORT_DOQ_DEFAULT 853 -#define LOCAL_PORT_MIN 2000 -#define LOCAL_PORT_MAX 65535 -#define QUIC_THREAD_PORTS 100 - -#define RCODE_MAX (0x0F + 1) - -typedef struct { - size_t collected; - uint64_t duration; - uint64_t qry_sent; - uint64_t synack_recv; - uint64_t ans_recv; - uint64_t finack_recv; - uint64_t rst_recv; - uint64_t size_recv; - uint64_t wire_recv; - uint64_t rcodes_recv[RCODE_MAX]; - pthread_mutex_t mutex; -} kxdpgun_stats_t; - static kxdpgun_stats_t global_stats = { 0 }; -typedef enum { - KXDPGUN_IGNORE_NONE = 0, - KXDPGUN_IGNORE_QUERY = (1 << 0), - KXDPGUN_IGNORE_LASTBYTE = (1 << 1), - KXDPGUN_IGNORE_CLOSE = (1 << 2), - KXDPGUN_REUSE_CONN = (1 << 3), -} xdp_gun_ignore_t; - -typedef struct { - union { - struct sockaddr_in local_ip4; - struct sockaddr_in6 local_ip; - struct sockaddr_storage local_ip_ss; - }; - union { - struct sockaddr_in target_ip4; - struct sockaddr_in6 target_ip; - struct sockaddr_storage target_ip_ss; - }; - char dev[IFNAMSIZ]; - uint64_t qps, duration; - unsigned at_once; - uint16_t msgid; - uint16_t edns_size; - uint16_t vlan_tci; - uint8_t local_mac[6], target_mac[6]; - uint8_t local_ip_range; - bool ipv6; - bool tcp; - bool quic; - bool quic_full_handshake; - const char *qlog_dir; - const char *sending_mode; - xdp_gun_ignore_t ignore1; - knot_tcp_ignore_t ignore2; - uint16_t target_port; - knot_xdp_filter_flag_t flags; - unsigned n_threads, thread_id; - knot_eth_rss_conf_t *rss_conf; - knot_xdp_config_t xdp_config; -} xdp_gun_ctx_t; - const static xdp_gun_ctx_t ctx_defaults = { .dev[0] = '\0', .edns_size = 1232, @@ -150,7 +75,9 @@ const static xdp_gun_ctx_t ctx_defaults = { .sending_mode = "", .target_port = 0, .flags = KNOT_XDP_FILTER_UDP | KNOT_XDP_FILTER_PASS, - .xdp_config = { .extra_frames = true }, + .xdp_config = { .ring_size = 2048 }, + .jw = NULL, + .stats_period = 0, }; static void sigterm_handler(int signo) @@ -163,103 +90,8 @@ static void sigusr_handler(int signo) { assert(signo == SIGUSR1); if (global_stats.collected == 0) { - stats_trigger++; - } -} - -static void clear_stats(kxdpgun_stats_t *st) -{ - pthread_mutex_lock(&st->mutex); - st->duration = 0; - st->qry_sent = 0; - st->synack_recv = 0; - st->ans_recv = 0; - st->finack_recv = 0; - st->rst_recv = 0; - st->size_recv = 0; - st->wire_recv = 0; - st->collected = 0; - memset(st->rcodes_recv, 0, sizeof(st->rcodes_recv)); - pthread_mutex_unlock(&st->mutex); -} - -static size_t collect_stats(kxdpgun_stats_t *into, const kxdpgun_stats_t *what) -{ - pthread_mutex_lock(&into->mutex); - into->duration = MAX(into->duration, what->duration); - into->qry_sent += what->qry_sent; - into->synack_recv += what->synack_recv; - into->ans_recv += what->ans_recv; - into->finack_recv += what->finack_recv; - into->rst_recv += what->rst_recv; - into->size_recv += what->size_recv; - into->wire_recv += what->wire_recv; - for (int i = 0; i < RCODE_MAX; i++) { - into->rcodes_recv[i] += what->rcodes_recv[i]; + ATOMIC_ADD(stats_trigger, 1); } - size_t res = ++into->collected; - pthread_mutex_unlock(&into->mutex); - return res; -} - -static void print_stats(kxdpgun_stats_t *st, bool tcp, bool quic, bool recv, uint64_t qps) -{ - pthread_mutex_lock(&st->mutex); - -#define ps(counter) ((typeof(counter))((counter) * 1000 / ((float)st->duration / 1000))) -#define pct(counter) ((counter) * 100.0 / st->qry_sent) - - const char *name = tcp ? "SYNs: " : quic ? "initials:" : "queries: "; - printf("total %s %"PRIu64" (%"PRIu64" pps) (%f%%)\n", name, st->qry_sent, - ps(st->qry_sent), 100.0 * st->qry_sent / (st->duration / 1000000.0 * qps)); - if (st->qry_sent > 0 && recv) { - if (tcp || quic) { - name = tcp ? "established:" : "handshakes: "; - printf("total %s %"PRIu64" (%"PRIu64" pps) (%f%%)\n", name, - st->synack_recv, ps(st->synack_recv), pct(st->synack_recv)); - } - printf("total replies: %"PRIu64" (%"PRIu64" pps) (%f%%)\n", - st->ans_recv, ps(st->ans_recv), pct(st->ans_recv)); - if (tcp) { - printf("total closed: %"PRIu64" (%"PRIu64" pps) (%f%%)\n", - st->finack_recv, ps(st->finack_recv), pct(st->finack_recv)); - } - if (st->rst_recv > 0) { - printf("total reset: %"PRIu64" (%"PRIu64" pps) (%f%%)\n", - st->rst_recv, ps(st->rst_recv), pct(st->rst_recv)); - } - printf("average DNS reply size: %"PRIu64" B\n", - st->ans_recv > 0 ? st->size_recv / st->ans_recv : 0); - printf("average Ethernet reply rate: %"PRIu64" bps (%.2f Mbps)\n", - ps(st->wire_recv * 8), ps((float)st->wire_recv * 8 / (1000 * 1000))); - - for (int i = 0; i < RCODE_MAX; i++) { - if (st->rcodes_recv[i] > 0) { - const knot_lookup_t *rcode = knot_lookup_by_id(knot_rcode_names, i); - const char *rcname = rcode == NULL ? "unknown" : rcode->name; - int space = MAX(9 - strlen(rcname), 0); - printf("responded %s: %.*s%"PRIu64"\n", - rcname, space, " ", st->rcodes_recv[i]); - } - } - } - printf("duration: %"PRIu64" s\n", (st->duration / (1000 * 1000))); - - pthread_mutex_unlock(&st->mutex); -} - -inline static void timer_start(struct timespec *timesp) -{ - clock_gettime(CLOCK_MONOTONIC, timesp); -} - -inline static uint64_t timer_end(struct timespec *timesp) -{ - struct timespec end; - clock_gettime(CLOCK_MONOTONIC, &end); - uint64_t res = (end.tv_sec - timesp->tv_sec) * (uint64_t)1000000; - res += ((int64_t)end.tv_nsec - timesp->tv_nsec) / 1000; - return res; } static unsigned addr_bits(bool ipv6) @@ -267,7 +99,8 @@ static unsigned addr_bits(bool ipv6) return ipv6 ? 128 : 32; } -static void shuffle_sockaddr4(struct sockaddr_in *dst, struct sockaddr_in *src, uint64_t increment) +static void shuffle_sockaddr4(struct sockaddr_in *dst, struct sockaddr_in *src, + uint64_t increment) { memcpy(&dst->sin_addr, &src->sin_addr, sizeof(dst->sin_addr)); if (increment > 0) { @@ -275,7 +108,8 @@ static void shuffle_sockaddr4(struct sockaddr_in *dst, struct sockaddr_in *src, } } -static void shuffle_sockaddr6(struct sockaddr_in6 *dst, struct sockaddr_in6 *src, uint64_t increment) +static void shuffle_sockaddr6(struct sockaddr_in6 *dst, struct sockaddr_in6 *src, + uint64_t increment) { memcpy(&dst->sin6_addr, &src->sin6_addr, sizeof(dst->sin6_addr)); if (increment > 0) { @@ -293,7 +127,8 @@ static void shuffle_sockaddr(struct sockaddr_in6 *dst, struct sockaddr_in6 *src, if (src->sin6_family == AF_INET6) { shuffle_sockaddr6(dst, src, increment); } else { - shuffle_sockaddr4((struct sockaddr_in *)dst, (struct sockaddr_in *)src, increment); + shuffle_sockaddr4((struct sockaddr_in *)dst, (struct sockaddr_in *)src, + increment); } } @@ -311,7 +146,8 @@ static void next_payload(struct pkt_payload **payload, int increment) } } -static void put_dns_payload(struct iovec *put_into, bool zero_copy, xdp_gun_ctx_t *ctx, struct pkt_payload **payl) +static void put_dns_payload(struct iovec *put_into, bool zero_copy, xdp_gun_ctx_t *ctx, + struct pkt_payload **payl) { if (zero_copy) { put_into->iov_base = (*payl)->payload; @@ -472,19 +308,41 @@ static void quic_free_cb(knot_quic_reply_t *rpl) } #endif // ENABLE_QUIC +static uint64_t timestamp_ns(void) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return ((uint64_t)ts.tv_sec * 1000000000) + ts.tv_nsec; +} + +static void timer_start(struct timespec *out) +{ + clock_gettime(CLOCK_MONOTONIC, out); +} + +static uint64_t timer_end_ns(const struct timespec *start) +{ + struct timespec end; + clock_gettime(CLOCK_MONOTONIC, &end); + uint64_t res = (end.tv_sec - start->tv_sec) * (uint64_t)1000000000; + res += end.tv_nsec - start->tv_nsec; + return res; +} + void *xdp_gun_thread(void *_ctx) { xdp_gun_ctx_t *ctx = _ctx; struct knot_xdp_socket *xsk = NULL; - struct timespec timer; knot_xdp_msg_t pkts[ctx->at_once]; - uint64_t errors = 0, lost = 0, duration = 0; - kxdpgun_stats_t local_stats = { 0 }; + uint64_t duration_us = 0; + struct timespec timer; + kxdpgun_stats_t local_stats = { 0 }; // cumulative stats of past periods excluding the current + kxdpgun_stats_t periodic_stats = { 0 }; // stats for the current period (see -S option) unsigned stats_triggered = 0; knot_tcp_table_t *tcp_table = NULL; #ifdef ENABLE_QUIC knot_quic_table_t *quic_table = NULL; - struct knot_quic_creds *quic_creds = NULL; + struct knot_creds *quic_creds = NULL; list_t quic_sessions; init_list(&quic_sessions); #endif // ENABLE_QUIC @@ -501,12 +359,13 @@ void *xdp_gun_thread(void *_ctx) } if (ctx->quic) { #ifdef ENABLE_QUIC - quic_creds = knot_quic_init_creds_peer(NULL, NULL, 0); + quic_creds = knot_creds_init_peer(NULL, NULL, 0); if (quic_creds == NULL) { ERR2("failed to initialize QUIC context"); goto cleanup; } - quic_table = knot_quic_table_new(ctx->qps * 100, SIZE_MAX, SIZE_MAX, 1232, quic_creds); + quic_table = knot_quic_table_new(ctx->qps * 100, SIZE_MAX, SIZE_MAX, + 1232, quic_creds); if (quic_table == NULL) { ERR2("failed to allocate QUIC connection table"); goto cleanup; @@ -517,12 +376,12 @@ void *xdp_gun_thread(void *_ctx) #endif // ENABLE_QUIC } - knot_xdp_load_bpf_t mode = (ctx->thread_id == 0 ? - KNOT_XDP_LOAD_BPF_ALWAYS : KNOT_XDP_LOAD_BPF_NEVER); + knot_xdp_load_bpf_t mode = + (ctx->thread_id == 0 ? KNOT_XDP_LOAD_BPF_ALWAYS : KNOT_XDP_LOAD_BPF_NEVER); /* * This mutex prevents libbpf from logging: * 'libbpf: can't get link by id (5535): Resource temporarily unavailable' - */ + */ pthread_mutex_lock(&global_stats.mutex); int ret = knot_xdp_init(&xsk, ctx->dev, ctx->thread_id, ctx->flags, LOCAL_PORT_MIN, LOCAL_PORT_MIN, mode, &ctx->xdp_config); @@ -534,13 +393,7 @@ void *xdp_gun_thread(void *_ctx) } if (ctx->thread_id == 0) { - INFO2("using interface %s, XDP threads %u, IPv%c/%s%s%s, %s mode", - ctx->dev, ctx->n_threads, (ctx->ipv6 ? '6' : '4'), - (ctx->tcp ? "TCP" : ctx->quic ? "QUIC" : "UDP"), - (ctx->sending_mode[0] != '\0' ? " mode " : ""), - (ctx->sending_mode[0] != '\0' ? ctx->sending_mode : ""), - (knot_eth_xdp_mode(if_nametoindex(ctx->dev)) == KNOT_XDP_MODE_FULL ? - "native" : "emulated")); + STATS_HDR(ctx); } struct pollfd pfd = { knot_xdp_socket_fd(xsk), POLLIN, 0 }; @@ -576,7 +429,7 @@ void *xdp_gun_thread(void *_ctx) ctx->target_ip.sin6_port = htobe16(ctx->target_port); knot_sweep_stats_t sweep_stats = { 0 }; - uint16_t local_ports[QUIC_THREAD_PORTS]; + uint16_t local_ports[QUIC_THREAD_PORTS] = { 0 }; uint16_t port = LOCAL_PORT_MIN; for (int i = 0; ctx->quic && i < QUIC_THREAD_PORTS; ++i) { local_ports[i] = adjust_port(ctx, port); @@ -586,24 +439,25 @@ void *xdp_gun_thread(void *_ctx) size_t local_ports_it = 0; #endif // ENABLE_QUIC + local_stats.since = periodic_stats.since = timestamp_ns(); timer_start(&timer); + ctx->stats_start_us = local_stats.since / 1000; - while (duration < ctx->duration + extra_wait) { - + while (duration_us < ctx->duration + extra_wait) { // sending part - if (duration < ctx->duration) { + if (duration_us < ctx->duration) { while (1) { knot_xdp_send_prepare(xsk); unsigned alloced = alloc_pkts(pkts, xsk, ctx, tick); if (alloced < ctx->at_once) { - lost += ctx->at_once - alloced; + periodic_stats.lost += ctx->at_once - alloced; if (alloced == 0) { break; } } if (ctx->tcp) { - for (int i = 0; i < alloced; i++) { + for (uint32_t i = 0; i < alloced; i++) { pkts[i].payload.iov_len = 0; if (!EMPTY_LIST(reuse_conns)) { @@ -621,7 +475,7 @@ void *xdp_gun_thread(void *_ctx) } if (ret == KNOT_EOK) { pkts[i].flags &= ~KNOT_XDP_MSG_SYN; // skip sending respective packet - local_stats.qry_sent++; + periodic_stats.qry_sent++; } free(rl); } @@ -670,14 +524,14 @@ void *xdp_gun_thread(void *_ctx) (ctx->ignore1 & KXDPGUN_IGNORE_LASTBYTE) ? KNOT_QUIC_SEND_IGNORE_LASTBYTE : 0); } if (ret == KNOT_EOK) { - local_stats.qry_sent++; + periodic_stats.qry_sent++; } } (void)knot_xdp_send_finish(xsk); #endif // ENABLE_QUIC break; } else { - for (int i = 0; i < alloced; i++) { + for (uint32_t i = 0; i < alloced; i++) { put_dns_payload(&pkts[i].payload, false, ctx, &payload_ptr); } @@ -685,9 +539,9 @@ void *xdp_gun_thread(void *_ctx) uint32_t really_sent = 0; if (knot_xdp_send(xsk, pkts, alloced, &really_sent) != KNOT_EOK) { - lost += alloced; + periodic_stats.lost += alloced; } - local_stats.qry_sent += really_sent; + periodic_stats.qry_sent += really_sent; (void)knot_xdp_send_finish(xsk); break; @@ -699,7 +553,7 @@ void *xdp_gun_thread(void *_ctx) while (1) { ret = poll(&pfd, 1, 0); if (ret < 0) { - errors++; + periodic_stats.errors++; break; } if (!pfd.revents) { @@ -714,18 +568,19 @@ void *xdp_gun_thread(void *_ctx) } if (ctx->tcp) { knot_tcp_relay_t relays[recvd]; - ret = knot_tcp_recv(relays, pkts, recvd, tcp_table, NULL, ctx->ignore2); - if (ret != KNOT_EOK) { - errors++; - break; - } for (size_t i = 0; i < recvd; i++) { knot_tcp_relay_t *rl = &relays[i]; + ret = knot_tcp_recv(rl, &pkts[i], tcp_table, NULL, ctx->ignore2); + if (ret != KNOT_EOK) { + periodic_stats.errors++; + continue; + } + struct iovec payl; switch (rl->action) { case XDP_TCP_ESTABLISH: - local_stats.synack_recv++; + periodic_stats.synack_recv++; if (ctx->ignore1 & KXDPGUN_IGNORE_QUERY) { break; } @@ -734,20 +589,20 @@ void *xdp_gun_thread(void *_ctx) (ctx->ignore1 & KXDPGUN_IGNORE_LASTBYTE), payl.iov_base, payl.iov_len); if (ret != KNOT_EOK) { - errors++; + periodic_stats.errors++; } break; case XDP_TCP_CLOSE: - local_stats.finack_recv++; + periodic_stats.finack_recv++; break; case XDP_TCP_RESET: - local_stats.rst_recv++; + periodic_stats.rst_recv++; break; default: break; } for (size_t j = 0; rl->inbf != NULL && j < rl->inbf->n_inbufs; j++) { - if (check_dns_payload(&rl->inbf->inbufs[j], ctx, &local_stats)) { + if (check_dns_payload(&rl->inbf->inbufs[j], ctx, &periodic_stats)) { if (!(ctx->ignore1 & KXDPGUN_IGNORE_CLOSE)) { rl->answer = XDP_TCP_CLOSE; } else if ((ctx->ignore1 & KXDPGUN_REUSE_CONN)) { @@ -763,7 +618,7 @@ void *xdp_gun_thread(void *_ctx) ret = knot_tcp_send(xsk, relays, recvd, ctx->at_once); if (ret != KNOT_EOK) { - errors++; + periodic_stats.errors++; } (void)knot_xdp_send_finish(xsk); @@ -781,11 +636,11 @@ void *xdp_gun_thread(void *_ctx) ret = knot_quic_handle(quic_table, &quic_reply, 5000000000L, &conn); if (ret == KNOT_ECONN) { - local_stats.rst_recv++; + periodic_stats.rst_recv++; knot_quic_cleanup(&conn, 1); continue; } else if (ret != 0) { - errors++; + periodic_stats.errors++; knot_quic_cleanup(&conn, 1); break; } @@ -805,7 +660,7 @@ void *xdp_gun_thread(void *_ctx) if ((conn->flags & KNOT_QUIC_CONN_HANDSHAKE_DONE) && conn->streams_count == -1) { conn->streams_count = 1; - local_stats.synack_recv++; + periodic_stats.synack_recv++; if ((ctx->ignore1 & KXDPGUN_IGNORE_QUERY)) { knot_quic_table_rem(conn, quic_table); knot_quic_cleanup(&conn, 1); @@ -822,14 +677,14 @@ void *xdp_gun_thread(void *_ctx) if ((ctx->ignore2 & XDP_TCP_IGNORE_ESTABLISH)) { knot_quic_table_rem(conn, quic_table); knot_quic_cleanup(&conn, 1); - local_stats.synack_recv++; + periodic_stats.synack_recv++; continue; } int64_t s0id; knot_quic_stream_t *stream0 = knot_quic_stream_get_process(conn, &s0id); if (stream0 != NULL && stream0->inbufs != NULL && stream0->inbufs->n_inbufs > 0) { - check_dns_payload(&stream0->inbufs->inbufs[0], ctx, &local_stats); + check_dns_payload(&stream0->inbufs->inbufs[0], ctx, &periodic_stats); stream0->inbufs->n_inbufs = 0; // signal that data have been read out if ((ctx->ignore2 & XDP_TCP_IGNORE_DATA_ACK)) { @@ -837,7 +692,9 @@ void *xdp_gun_thread(void *_ctx) knot_quic_cleanup(&conn, 1); continue; } else if ((ctx->ignore1 & KXDPGUN_REUSE_CONN)) { - if (conn->streams_count > 1) { // keep the number of outstanding streams below MAX_STREAMS_PER_CONN, while preserving at least one at all times + /* keep the number of outstanding streams below MAX_STREAMS_PER_CONN, + * while preserving at least one at all times */ + if (conn->streams_count > 1) { knot_quic_conn_stream_free(conn, conn->streams_first * 4); } ptrlist_add(&reuse_conns, conn, NULL); @@ -846,30 +703,31 @@ void *xdp_gun_thread(void *_ctx) ret = knot_quic_send(quic_table, conn, &quic_reply, 4, (ctx->ignore1 & KXDPGUN_IGNORE_LASTBYTE) ? KNOT_QUIC_SEND_IGNORE_LASTBYTE : 0); if (ret != KNOT_EOK) { - errors++; + periodic_stats.errors++; } - if (!(ctx->ignore1 & KXDPGUN_IGNORE_CLOSE) && (conn->flags & KNOT_QUIC_CONN_SESSION_TAKEN) && - stream0 != NULL && stream0->inbufs != NULL && stream0->inbufs->n_inbufs == 0) { + if (!(ctx->ignore1 & KXDPGUN_IGNORE_CLOSE) + && (conn->flags & KNOT_QUIC_CONN_SESSION_TAKEN) + && stream0 != NULL && stream0->inbufs != NULL + && stream0->inbufs->n_inbufs == 0) { assert(!(ctx->ignore2 & XDP_TCP_IGNORE_DATA_ACK)); quic_reply.handle_ret = KNOT_QUIC_HANDLE_RET_CLOSE; ret = knot_quic_send(quic_table, conn, &quic_reply, 1, 0); knot_quic_table_rem(conn, quic_table); knot_quic_cleanup(&conn, 1); if (ret != KNOT_EOK) { - errors++; + periodic_stats.errors++; } } } (void)knot_xdp_send_finish(xsk); #endif // ENABLE_QUIC } else { - for (int i = 0; i < recvd; i++) { - (void)check_dns_payload(&pkts[i].payload, ctx, - &local_stats); + for (uint32_t i = 0; i < recvd; i++) { + check_dns_payload(&pkts[i].payload, ctx, &periodic_stats); } } - local_stats.wire_recv += wire; + periodic_stats.wire_recv += wire; knot_xdp_recv_finish(xsk, pkts, recvd); pfd.revents = 0; } @@ -882,47 +740,59 @@ void *xdp_gun_thread(void *_ctx) #endif // ENABLE_QUIC // speed and signal part - uint64_t dura_exp = (local_stats.qry_sent * 1000000) / ctx->qps; - duration = timer_end(&timer); - if (xdp_trigger == KXDPGUN_STOP && ctx->duration > duration) { - ctx->duration = duration; + uint64_t duration_ns = timer_end_ns(&timer); + duration_us = duration_ns / 1000; + uint64_t dura_exp = ((local_stats.qry_sent + periodic_stats.qry_sent) * 1000000) / ctx->qps; + if (ctx->thread_id == 0 && ctx->stats_period != 0 && global_stats.collected == 0 + && (duration_ns - (periodic_stats.since - local_stats.since)) >= ctx->stats_period) { + ATOMIC_SET(stats_switch, STATS_PERIODIC); + ATOMIC_ADD(stats_trigger, 1); } - if (stats_trigger > stats_triggered) { - assert(stats_trigger == stats_triggered + 1); - stats_triggered++; - local_stats.duration = duration; - size_t collected = collect_stats(&global_stats, &local_stats); + if (xdp_trigger == KXDPGUN_STOP && ctx->duration > duration_us) { + ctx->duration = duration_us; + } + uint64_t tmp_stats_trigger = ATOMIC_GET(stats_trigger); + if (duration_us < ctx->duration && tmp_stats_trigger > stats_triggered) { + bool tmp_stats_switch = ATOMIC_GET(stats_switch); + stats_triggered = tmp_stats_trigger; + + local_stats.until = periodic_stats.until = local_stats.since + duration_ns; + kxdpgun_stats_t cumulative_stats = periodic_stats; + if (tmp_stats_switch == STATS_PERIODIC) { + collect_periodic_stats(&local_stats, &periodic_stats); + clear_stats(&periodic_stats); + periodic_stats.since = local_stats.since + duration_ns; + } else { + collect_periodic_stats(&cumulative_stats, &local_stats); + cumulative_stats.since = local_stats.since; + } + + size_t collected = collect_stats(&global_stats, &cumulative_stats); + assert(collected <= ctx->n_threads); if (collected == ctx->n_threads) { - print_stats(&global_stats, ctx->tcp, ctx->quic, - !(ctx->flags & KNOT_XDP_FILTER_DROP), - ctx->qps * ctx->n_threads); + STATS_FMT(ctx, &global_stats, tmp_stats_switch); + if (!JSON_MODE(*ctx)) { + puts(STATS_SECTION_SEP); + } clear_stats(&global_stats); + ATOMIC_SET(stats_switch, STATS_SUM); } } - if (dura_exp > duration) { - usleep(dura_exp - duration); + if (dura_exp > duration_us) { + usleep(dura_exp - duration_us); } - if (duration > ctx->duration) { + if (duration_us > ctx->duration) { usleep(1000); } tick++; } + periodic_stats.until = local_stats.since + timer_end_ns(&timer) - extra_wait * 1000; + collect_periodic_stats(&local_stats, &periodic_stats); + + STATS_THRD(ctx, &local_stats); - char recv_str[40] = "", lost_str[40] = "", err_str[40] = ""; - if (!(ctx->flags & KNOT_XDP_FILTER_DROP)) { - (void)snprintf(recv_str, sizeof(recv_str), ", received %"PRIu64, local_stats.ans_recv); - } - if (lost > 0) { - (void)snprintf(lost_str, sizeof(lost_str), ", lost %"PRIu64, lost); - } - if (errors > 0) { - (void)snprintf(err_str, sizeof(err_str), ", errors %"PRIu64, errors); - } - INFO2("thread#%02u: sent %"PRIu64"%s%s%s", - ctx->thread_id, local_stats.qry_sent, recv_str, lost_str, err_str); - local_stats.duration = ctx->duration; collect_stats(&global_stats, &local_stats); cleanup: @@ -943,7 +813,7 @@ cleanup: WALK_LIST_DELSAFE(n, nxt, quic_sessions) { knot_quic_session_load(NULL, n); } - knot_quic_free_creds(quic_creds); + knot_creds_free(quic_creds); #endif // ENABLE_QUIC return NULL; @@ -1118,30 +988,33 @@ static void print_help(void) printf("Usage: %s [options] -i \n" "\n" "Options:\n" - " -t, --duration "SPACE"Duration of traffic generation.\n" - " "SPACE" (default is %"PRIu64" seconds)\n" - " -T, --tcp[=debug_mode] "SPACE"Send queries over TCP.\n" - " -U, --quic[=debug_mode] "SPACE"Send queries over QUIC.\n" - " -Q, --qps "SPACE"Number of queries-per-second (approximately) to be sent.\n" - " "SPACE" (default is %"PRIu64" qps)\n" - " -b, --batch "SPACE"Send queries in a batch of defined size.\n" - " "SPACE" (default is %d for UDP, %d for TCP)\n" - " -r, --drop "SPACE"Drop incoming responses (disables response statistics).\n" - " -p, --port "SPACE"Remote destination port.\n" - " "SPACE" (default is %d for UDP/TCP, %u for QUIC)\n" - " -F, --affinity "SPACE"CPU affinity in the format [][s].\n" - " "SPACE" (default is %s)\n" - " -i, --infile "SPACE"Path to a file with query templates.\n" - " -I, --interface "SPACE"Override auto-detected interface for outgoing communication.\n" - " -l, --local "SPACE"Override auto-detected source IP address or subnet.\n" - " -L, --local-mac "SPACE"Override auto-detected local MAC address.\n" - " -R, --remote-mac "SPACE"Override auto-detected remote MAC address.\n" - " -v, --vlan "SPACE"Add VLAN 802.1Q header with the given id.\n" - " -e, --edns-size "SPACE"EDNS UDP payload size, range 512-4096 (default 1232)\n" - " -m, --mode "SPACE"Set XDP mode (auto, copy, generic).\n" - " -G, --qlog "SPACE"Output directory for qlog (useful for QUIC only).\n" - " -h, --help "SPACE"Print the program help.\n" - " -V, --version "SPACE"Print the program version.\n" + " -t, --duration "SPACE"Duration of traffic generation.\n" + " "SPACE" (default is %"PRIu64" seconds)\n" + " -T, --tcp[=debug_mode] "SPACE"Send queries over TCP.\n" + " -U, --quic[=debug_mode] "SPACE"Send queries over QUIC.\n" + " -Q, --qps "SPACE"Number of queries-per-second (approximately) to be sent.\n" + " "SPACE" (default is %"PRIu64" qps)\n" + " -b, --batch "SPACE"Send queries in a batch of defined size.\n" + " "SPACE" (default is %d for UDP, %d for TCP)\n" + " -r, --drop "SPACE"Drop incoming responses (disables response statistics).\n" + " -p, --port "SPACE"Remote destination port.\n" + " "SPACE" (default is %d for UDP/TCP, %u for QUIC)\n" + " -F, --affinity "SPACE"CPU affinity in the format [][s].\n" + " "SPACE" (default is %s)\n" + " -I, --interface "SPACE"Override auto-detected interface for outgoing communication.\n" + " -i, --infile "SPACE"Path to a file with query templates.\n" + " -B, --binary "SPACE"Specify that input file is in binary format ().\n" + " -l, --local "SPACE"Override auto-detected source IP address or subnet.\n" + " -L, --local-mac "SPACE"Override auto-detected local MAC address.\n" + " -R, --remote-mac "SPACE"Override auto-detected remote MAC address.\n" + " -v, --vlan "SPACE"Add VLAN 802.1Q header with the given id.\n" + " -e, --edns-size "SPACE"EDNS UDP payload size, range 512-4096 (default 1232)\n" + " -m, --mode "SPACE"Set XDP mode (auto, copy, generic).\n" + " -G, --qlog "SPACE"Output directory for qlog (useful for QUIC only).\n" + " -j, --json "SPACE"Output statistics in json.\n" + " -S, --stats-period "SPACE"Enable periodic statistics printout in milliseconds.\n" + " -h, --help "SPACE"Print the program help.\n" + " -V, --version "SPACE"Print the program version.\n" "\n" "Parameters:\n" " "SPACE"IPv4 or IPv6 address of the remote destination.\n", @@ -1240,40 +1113,45 @@ static int set_mode(const char *arg, knot_xdp_config_t *config) static bool get_opts(int argc, char *argv[], xdp_gun_ctx_t *ctx) { + const char *opts_str = "hV::t:Q:b:rp:T::U::F:I:i:Bl:L:R:v:e:m:G:jS:"; struct option opts[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, - { "duration", required_argument, NULL, 't' }, - { "qps", required_argument, NULL, 'Q' }, - { "batch", required_argument, NULL, 'b' }, - { "drop", no_argument, NULL, 'r' }, - { "port", required_argument, NULL, 'p' }, - { "tcp", optional_argument, NULL, 'T' }, - { "quic", optional_argument, NULL, 'U' }, - { "affinity", required_argument, NULL, 'F' }, - { "interface", required_argument, NULL, 'I' }, - { "local", required_argument, NULL, 'l' }, - { "infile", required_argument, NULL, 'i' }, - { "local-mac", required_argument, NULL, 'L' }, - { "remote-mac", required_argument, NULL, 'R' }, - { "vlan", required_argument, NULL, 'v' }, - { "edns-size", required_argument, NULL, 'e' }, - { "mode", required_argument, NULL, 'm' }, - { "qlog", required_argument, NULL, 'G' }, - { NULL } + { "help", no_argument, NULL, 'h' }, + { "version", optional_argument, NULL, 'V' }, + { "duration", required_argument, NULL, 't' }, + { "qps", required_argument, NULL, 'Q' }, + { "batch", required_argument, NULL, 'b' }, + { "drop", no_argument, NULL, 'r' }, + { "port", required_argument, NULL, 'p' }, + { "tcp", optional_argument, NULL, 'T' }, + { "quic", optional_argument, NULL, 'U' }, + { "affinity", required_argument, NULL, 'F' }, + { "interface", required_argument, NULL, 'I' }, + { "infile", required_argument, NULL, 'i' }, + { "binary", no_argument, NULL, 'B' }, + { "local", required_argument, NULL, 'l' }, + { "local-mac", required_argument, NULL, 'L' }, + { "remote-mac", required_argument, NULL, 'R' }, + { "vlan", required_argument, NULL, 'v' }, + { "edns-size", required_argument, NULL, 'e' }, + { "mode", required_argument, NULL, 'm' }, + { "qlog", required_argument, NULL, 'G' }, + { "json", no_argument, NULL, 'j' }, + { "stats-period", required_argument, NULL, 'S' }, + { 0 } }; int opt = 0, arg; bool default_at_once = true; double argf; - char *argcp, *local_ip = NULL, *filename = NULL; - while ((opt = getopt_long(argc, argv, "hVt:Q:b:rp:T::U::F:I:l:i:L:R:v:e:m:G:", opts, NULL)) != -1) { + char *argcp, *local_ip = NULL; + input_t input = { .format = TXT }; + while ((opt = getopt_long(argc, argv, opts_str, opts, NULL)) != -1) { switch (opt) { case 'h': print_help(); exit(EXIT_SUCCESS); case 'V': - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, optarg != NULL); exit(EXIT_SUCCESS); case 't': assert(optarg); @@ -1366,12 +1244,15 @@ static bool get_opts(int argc, char *argv[], xdp_gun_ctx_t *ctx) case 'I': strlcpy(ctx->dev, optarg, IFNAMSIZ); break; + case 'i': + input.path = optarg; + break; + case 'B': + input.format = BIN; + break; case 'l': local_ip = optarg; break; - case 'i': - filename = optarg; - break; case 'L': if (mac_sscan(optarg, ctx->local_mac) != KNOT_EOK) { ERR2("invalid local MAC address '%s'", optarg); @@ -1415,17 +1296,33 @@ static bool get_opts(int argc, char *argv[], xdp_gun_ctx_t *ctx) case 'G': ctx->qlog_dir = optarg; break; + case 'S': + assert(optarg); + arg = atoi(optarg); + if (arg > 0) { + ctx->stats_period = arg * 1000000; // convert to ns + } else { + ERR2("period must be a positive integer\n"); + return false; + } + break; + case 'j': + if ((ctx->jw = jsonw_new(stdout, JSON_INDENT)) == NULL) { + ERR2("failed to use JSON"); + return false; + } + break; default: print_help(); return false; } } - if (filename == NULL) { + if (input.path == NULL) { print_help(); return false; } size_t qcount = ctx->duration / 1000000 * ctx->qps; - if (!load_queries(filename, ctx->edns_size, ctx->msgid, qcount)) { + if (!load_queries(&input, ctx->edns_size, ctx->msgid, qcount)) { return false; } if (global_payloads == NULL || argc - optind != 1) { @@ -1452,25 +1349,29 @@ static bool get_opts(int argc, char *argv[], xdp_gun_ctx_t *ctx) int main(int argc, char *argv[]) { + int ecode = EXIT_FAILURE; + xdp_gun_ctx_t ctx = ctx_defaults, *thread_ctxs = NULL; ctx.msgid = time(NULL) % UINT16_MAX; + ctx.runid = timestamp_ns() / 1000; + ctx.argv = argv; pthread_t *threads = NULL; if (!get_opts(argc, argv, &ctx)) { - free_global_payloads(); - return EXIT_FAILURE; + goto err; + } + + if (JSON_MODE(ctx)) { + jsonw_list(ctx.jw, NULL); // wrap the json in a list, for syntactic correctness } thread_ctxs = calloc(ctx.n_threads, sizeof(*thread_ctxs)); threads = calloc(ctx.n_threads, sizeof(*threads)); if (thread_ctxs == NULL || threads == NULL) { ERR2("out of memory"); - free(thread_ctxs); - free(threads); - free_global_payloads(); - return EXIT_FAILURE; + goto err; } - for (int i = 0; i < ctx.n_threads; i++) { + for (uint32_t i = 0; i < ctx.n_threads; i++) { thread_ctxs[i] = ctx; thread_ctxs[i].thread_id = i; } @@ -1482,8 +1383,7 @@ int main(int argc, char *argv[]) cur_limit.rlim_max != min_limit.rlim_max) { int ret = setrlimit(RLIMIT_MEMLOCK, &min_limit); if (ret != 0) { - WARN2("unable to increase RLIMIT_MEMLOCK: %s", - strerror(errno)); + WARN2("unable to increase RLIMIT_MEMLOCK: %s", strerror(errno)); } } } @@ -1509,22 +1409,30 @@ int main(int argc, char *argv[]) usleep(20000); } usleep(1000000); - xdp_trigger = KXDPGUN_START; usleep(1000000); for (size_t i = 0; i < ctx.n_threads; i++) { pthread_join(threads[i], NULL); } - if (global_stats.duration > 0 && global_stats.qry_sent > 0) { - print_stats(&global_stats, ctx.tcp, ctx.quic, !(ctx.flags & KNOT_XDP_FILTER_DROP), ctx.qps * ctx.n_threads); + if (DURATION_US(global_stats) > 0 && global_stats.qry_sent > 0) { + if (!JSON_MODE(ctx)) { + puts(STATS_SECTION_SEP); + } + STATS_FMT(&ctx, &global_stats, STATS_SUM); } pthread_mutex_destroy(&global_stats.mutex); + ecode = EXIT_SUCCESS; + +err: free(ctx.rss_conf); free(thread_ctxs); free(threads); free_global_payloads(); - - return EXIT_SUCCESS; + if (JSON_MODE(ctx)) { + jsonw_end(ctx.jw); + jsonw_free(&ctx.jw); + } + return ecode; } diff --git a/src/utils/kxdpgun/main.h b/src/utils/kxdpgun/main.h new file mode 100644 index 0000000..d87aee8 --- /dev/null +++ b/src/utils/kxdpgun/main.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +#include "contrib/json.h" +#include "libknot/xdp/eth.h" +#include "libknot/xdp/tcp.h" + +#define PROGRAM_NAME "kxdpgun" +#define SPACE " " + +#define REMOTE_PORT_DEFAULT 53 +#define REMOTE_PORT_DOQ_DEFAULT 853 +#define LOCAL_PORT_MIN 2000 +#define LOCAL_PORT_MAX 65535 +#define QUIC_THREAD_PORTS 100 + +enum { + KXDPGUN_WAIT, + KXDPGUN_START, + KXDPGUN_STOP, +}; + +typedef enum { + KXDPGUN_IGNORE_NONE = 0, + KXDPGUN_IGNORE_QUERY = (1 << 0), + KXDPGUN_IGNORE_LASTBYTE = (1 << 1), + KXDPGUN_IGNORE_CLOSE = (1 << 2), + KXDPGUN_REUSE_CONN = (1 << 3), +} xdp_gun_ignore_t; + +typedef struct xdp_gun_ctx { + union { + struct sockaddr_in local_ip4; + struct sockaddr_in6 local_ip; + struct sockaddr_storage local_ip_ss; + }; + union { + struct sockaddr_in target_ip4; + struct sockaddr_in6 target_ip; + struct sockaddr_storage target_ip_ss; + }; + char dev[IFNAMSIZ]; + uint64_t qps, duration; + uint64_t runid; + uint64_t stats_start_us; + uint32_t stats_period; // 0 means no periodic stats + unsigned at_once; + uint16_t msgid; + uint16_t edns_size; + uint16_t vlan_tci; + uint8_t local_mac[6], target_mac[6]; + uint8_t local_ip_range; + bool ipv6; + bool tcp; + bool quic; + bool quic_full_handshake; + const char *qlog_dir; + const char *sending_mode; + xdp_gun_ignore_t ignore1; + knot_tcp_ignore_t ignore2; + uint16_t target_port; + knot_xdp_filter_flag_t flags; + unsigned n_threads, thread_id; + knot_eth_rss_conf_t *rss_conf; + jsonw_t *jw; + char **argv; + knot_xdp_config_t xdp_config; +} xdp_gun_ctx_t; diff --git a/src/utils/kxdpgun/stats.c b/src/utils/kxdpgun/stats.c new file mode 100644 index 0000000..f1e4f43 --- /dev/null +++ b/src/utils/kxdpgun/stats.c @@ -0,0 +1,292 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include "contrib/macros.h" +#include "libknot/codes.h" +#include "libknot/lookup.h" +#include "utils/common/msg.h" +#include "utils/kxdpgun/main.h" +#include "utils/kxdpgun/stats.h" + +pthread_mutex_t stdout_mtx = PTHREAD_MUTEX_INITIALIZER; + +void clear_stats(kxdpgun_stats_t *st) +{ + pthread_mutex_lock(&st->mutex); + st->since = 0; + st->until = 0; + st->qry_sent = 0; + st->synack_recv = 0; + st->ans_recv = 0; + st->finack_recv = 0; + st->rst_recv = 0; + st->size_recv = 0; + st->wire_recv = 0; + st->collected = 0; + st->lost = 0; + st->errors = 0; + memset(st->rcodes_recv, 0, sizeof(st->rcodes_recv)); + pthread_mutex_unlock(&st->mutex); +} + +size_t collect_stats(kxdpgun_stats_t *into, const kxdpgun_stats_t *what) +{ + pthread_mutex_lock(&into->mutex); + into->since = what->since; + collect_periodic_stats(into, what); + size_t res = ++into->collected; + pthread_mutex_unlock(&into->mutex); + return res; +} + +void collect_periodic_stats(kxdpgun_stats_t *into, const kxdpgun_stats_t *what) +{ + into->until = what->until; + into->qry_sent += what->qry_sent; + into->synack_recv += what->synack_recv; + into->ans_recv += what->ans_recv; + into->finack_recv += what->finack_recv; + into->rst_recv += what->rst_recv; + into->size_recv += what->size_recv; + into->wire_recv += what->wire_recv; + into->lost += what->lost; + into->errors += what->errors; + for (int i = 0; i < RCODE_MAX; i++) { + into->rcodes_recv[i] += what->rcodes_recv[i]; + } +} + +void plain_stats_header(const xdp_gun_ctx_t *ctx) +{ + INFO2("using interface %s, XDP threads %u, IPv%c/%s%s%s, %s mode", ctx->dev, ctx->n_threads, + (ctx->ipv6 ? '6' : '4'), + (ctx->tcp ? "TCP" : ctx->quic ? "QUIC" : "UDP"), + (ctx->sending_mode[0] != '\0' ? " mode " : ""), + (ctx->sending_mode[0] != '\0' ? ctx->sending_mode : ""), + (knot_eth_xdp_mode(if_nametoindex(ctx->dev)) == KNOT_XDP_MODE_FULL ? "native" : "emulated")); + puts(STATS_SECTION_SEP); +} + +/* see: + * - https://github.com/DNS-OARC/dns-metrics/blob/main/dns-metrics.schema.json + * - https://github.com/DNS-OARC/dns-metrics/issues/16#issuecomment-2139462920 + */ +void json_stats_header(const xdp_gun_ctx_t *ctx) +{ + jsonw_t *w = ctx->jw; + + jsonw_object(w, NULL); + { + jsonw_ulong(w, "runid", ctx->runid); + jsonw_str(w, "type", "header"); + jsonw_int(w, "schema_version", STATS_SCHEMA_VERSION); + jsonw_str(w, "generator", PROGRAM_NAME); + jsonw_str(w, "generator_version", PACKAGE_VERSION); + + jsonw_list(w, "generator_params"); + { + for (char **it = ctx->argv; *it != NULL; ++it) { + jsonw_str(w, NULL, *it); + } + } + jsonw_end(w); + + jsonw_ulong(w, "time_units_per_sec", 1000000000); + if (ctx->stats_period > 0) { + jsonw_double(w, "stats_interval", ctx->stats_period / 1000.0); + } + // TODO: timeout + + // mirror the info given by the plaintext printout + jsonw_object(w, "additional_info"); + { + jsonw_str(w, "interface", ctx->dev); + jsonw_int(w, "xdp_threads", ctx->n_threads); + jsonw_int(w, "ip_version", ctx->ipv6 ? 6 : 4); + jsonw_str(w, "transport_layer_proto", ctx->tcp ? "TCP" : (ctx->quic ? "QUIC" : "UDP")); + jsonw_object(w, "mode_info"); + { + if (ctx->sending_mode[0] != '\0') { + jsonw_str(w, "debug", ctx->sending_mode); + } + jsonw_str(w, "mode", knot_eth_xdp_mode(if_nametoindex(ctx->dev)) == KNOT_XDP_MODE_FULL + ? "native" + : "emulated"); + } + jsonw_end(w); + } + jsonw_end(w); + } + jsonw_end(w); +} + +void plain_thrd_summary(const xdp_gun_ctx_t *ctx, const kxdpgun_stats_t *st) +{ + pthread_mutex_lock(&stdout_mtx); + + char recv_str[40] = "", lost_str[40] = "", err_str[40] = ""; + if (!(ctx->flags & KNOT_XDP_FILTER_DROP)) { + (void)snprintf(recv_str, sizeof(recv_str), ", received %"PRIu64, st->ans_recv); + } + if (st->lost > 0) { + (void)snprintf(lost_str, sizeof(lost_str), ", lost %"PRIu64, st->lost); + } + if (st->errors > 0) { + (void)snprintf(err_str, sizeof(err_str), ", errors %"PRIu64, st->errors); + } + INFO2("thread#%02u: sent %"PRIu64"%s%s%s", + ctx->thread_id, st->qry_sent, recv_str, lost_str, err_str); + + pthread_mutex_unlock(&stdout_mtx); +} + +void json_thrd_summary(const xdp_gun_ctx_t *ctx, const kxdpgun_stats_t *st) +{ + pthread_mutex_lock(&stdout_mtx); + + jsonw_t *w = ctx->jw; + + jsonw_object(ctx->jw, NULL); + { + jsonw_str(w, "type", "thread_summary"); + jsonw_ulong(w, "runid", ctx->runid); + jsonw_ulong(w, "subid", ctx->thread_id); + jsonw_ulong(w, "qry_sent", st->qry_sent); + jsonw_ulong(w, "ans_recv", st->ans_recv); + jsonw_ulong(w, "lost", st->lost); + jsonw_ulong(w, "errors", st->errors); + } + jsonw_end(ctx->jw); + + pthread_mutex_unlock(&stdout_mtx); +} + +void plain_stats(const xdp_gun_ctx_t *ctx, kxdpgun_stats_t *st, stats_type_t stt) +{ + pthread_mutex_lock(&st->mutex); + + printf("%s metrics:\n", (stt == STATS_SUM) ? "cumulative" : "periodic"); + + bool recv = !(ctx->flags & KNOT_XDP_FILTER_DROP); + uint64_t duration = DURATION_US(*st); + double rel_start_us = (st->since / 1000.0) - ctx->stats_start_us ; + double rel_end_us = rel_start_us + duration; + +#define ps(counter) ((typeof(counter))((counter) * 1000 / ((float)duration / 1000))) +#define pct(counter) ((counter) * 100.0 / st->qry_sent) + + const char *name = ctx->tcp ? "SYNs: " : ctx->quic ? "initials:" : "queries: "; + printf("total %s %"PRIu64" (%"PRIu64" pps) (%f%%)\n", name, st->qry_sent, + ps(st->qry_sent), 100.0 * st->qry_sent / (duration / 1000000.0 * ctx->qps * ctx->n_threads)); + if (st->qry_sent > 0 && recv) { + if (ctx->tcp || ctx->quic) { + name = ctx->tcp ? "established:" : "handshakes: "; + printf("total %s %"PRIu64" (%"PRIu64" pps) (%f%%)\n", name, + st->synack_recv, ps(st->synack_recv), pct(st->synack_recv)); + } + printf("total replies: %"PRIu64" (%"PRIu64" pps) (%f%%)\n", + st->ans_recv, ps(st->ans_recv), pct(st->ans_recv)); + if (ctx->tcp) { + printf("total closed: %"PRIu64" (%"PRIu64" pps) (%f%%)\n", + st->finack_recv, ps(st->finack_recv), pct(st->finack_recv)); + } + if (st->rst_recv > 0) { + printf("total reset: %"PRIu64" (%"PRIu64" pps) (%f%%)\n", + st->rst_recv, ps(st->rst_recv), pct(st->rst_recv)); + } + printf("average DNS reply size: %"PRIu64" B\n", + st->ans_recv > 0 ? st->size_recv / st->ans_recv : 0); + printf("average Ethernet reply rate: %"PRIu64" bps (%.2f Mbps)\n", + ps(st->wire_recv * 8), ps((float)st->wire_recv * 8 / (1000 * 1000))); + + for (int i = 0; i < RCODE_MAX; i++) { + if (st->rcodes_recv[i] > 0) { + const knot_lookup_t *rcode = knot_lookup_by_id(knot_rcode_names, i); + const char *rcname = rcode == NULL ? "unknown" : rcode->name; + int space = MAX(9 - strlen(rcname), 0); + printf("responded %s: %.*s%"PRIu64"\n", + rcname, space, " ", st->rcodes_recv[i]); + } + } + } + if (stt == STATS_SUM) { + printf("duration: %.4f s\n", duration / 1000000.0); + } else { + printf("since: %.4fs until: %.4fs\n", rel_start_us / 1000000, rel_end_us / 1000000); + } + + pthread_mutex_unlock(&st->mutex); +} + +/* see https://github.com/DNS-OARC/dns-metrics/blob/main/dns-metrics.schema.json + * and https://github.com/DNS-OARC/dns-metrics/issues/16#issuecomment-2139462920 */ +void json_stats(const xdp_gun_ctx_t *ctx, kxdpgun_stats_t *st, stats_type_t stt) +{ + assert(stt == STATS_PERIODIC || stt == STATS_SUM); + + jsonw_t *w = ctx->jw; + + pthread_mutex_lock(&st->mutex); + + jsonw_object(w, NULL); + { + jsonw_ulong(w, "runid", ctx->runid); + jsonw_str(w, "type", (stt == STATS_PERIODIC) ? "stats_periodic" : "stats_sum"); + jsonw_ulong(w, "since", st->since); + jsonw_ulong(w, "until", st->until); + jsonw_ulong(w, "queries", st->qry_sent); + jsonw_ulong(w, "responses", st->ans_recv); + + jsonw_object(w, "response_rcodes"); + { + for (size_t i = 0; i < RCODE_MAX; ++i) { + if (st->rcodes_recv[i] > 0) { + const knot_lookup_t *rc = knot_lookup_by_id(knot_rcode_names, i); + jsonw_ulong(w, (rc == NULL) ? "unknown" : rc->name, st->rcodes_recv[i]); + } + } + } + jsonw_end(w); + + jsonw_object(w, "conn_info"); + { + jsonw_str(w, "type", ctx->tcp ? "tcp" : (ctx->quic ? "quic_conn" : "udp")); + + // TODO: + // packets_sent + // packets_recieved + + jsonw_ulong(w, "socket_errors", st->errors); + if (ctx->tcp || ctx->quic) { + jsonw_ulong(w, "handshakes", st->synack_recv); + // TODO: handshakes_failed + if (ctx->quic) { + // TODO: conn_resumption + } + } + } + jsonw_end(w); + } + jsonw_end(w); + + pthread_mutex_unlock(&st->mutex); +} diff --git a/src/utils/kxdpgun/stats.h b/src/utils/kxdpgun/stats.h new file mode 100644 index 0000000..2c62ee3 --- /dev/null +++ b/src/utils/kxdpgun/stats.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include +#include + +#include "utils/kxdpgun/main.h" + +#define RCODE_MAX (0x0F + 1) + +#define STATS_SECTION_SEP "--------------------------------------------------------------" + +#define JSON_INDENT " " +#define STATS_SCHEMA_VERSION 20240530 + +#define DURATION_US(st) (((st).until - (st).since) / 1000) +#define DURATION_NS(st) ((st).until - (st).since) + +#define JSON_MODE(ctx) ((ctx).jw != NULL) + +#define STATS_HDR(ctx) ((JSON_MODE(*(ctx)) ? json_stats_header : plain_stats_header)((ctx))) +#define STATS_THRD(ctx, stats) \ + ((JSON_MODE(*ctx) ? json_thrd_summary : plain_thrd_summary)((ctx), (stats))) +#define STATS_FMT(ctx, stats, stats_type) \ + ((JSON_MODE(*(ctx)) ? json_stats : plain_stats)((ctx), (stats), (stats_type))) + +typedef struct { + size_t collected; + uint64_t since, until; // nanosecs UNIX + uint64_t qry_sent; + uint64_t synack_recv; + uint64_t ans_recv; + uint64_t finack_recv; + uint64_t rst_recv; + uint64_t size_recv; + uint64_t wire_recv; + uint64_t errors; + uint64_t lost; + uint64_t rcodes_recv[RCODE_MAX]; + pthread_mutex_t mutex; +} kxdpgun_stats_t; + +typedef enum { + STATS_PERIODIC, + STATS_SUM, +} stats_type_t; + +void clear_stats(kxdpgun_stats_t *st); +size_t collect_stats(kxdpgun_stats_t *into, const kxdpgun_stats_t *what); +void collect_periodic_stats(kxdpgun_stats_t *into, const kxdpgun_stats_t *what); + +void plain_stats_header(const xdp_gun_ctx_t *ctx); +void json_stats_header(const xdp_gun_ctx_t *ctx); + +void plain_thrd_summary(const xdp_gun_ctx_t *ctx, const kxdpgun_stats_t *st); +void json_thrd_summary(const xdp_gun_ctx_t *ctx, const kxdpgun_stats_t *st); + +void plain_stats(const xdp_gun_ctx_t *ctx, kxdpgun_stats_t *st, stats_type_t stt); +void json_stats(const xdp_gun_ctx_t *ctx, kxdpgun_stats_t *st, stats_type_t stt); + +extern pthread_mutex_t stdout_mtx; diff --git a/src/utils/kzonecheck/main.c b/src/utils/kzonecheck/main.c index b602cc9..e8c5868 100644 --- a/src/utils/kzonecheck/main.c +++ b/src/utils/kzonecheck/main.c @@ -81,7 +81,7 @@ int main(int argc, char *argv[]) { "print", no_argument, NULL, 'p' }, { "verbose", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, + { "version", optional_argument, NULL, 'V' }, { NULL } }; @@ -90,7 +90,7 @@ int main(int argc, char *argv[]) /* Parse command line arguments */ int opt = 0; - while ((opt = getopt_long(argc, argv, "o:t:d:zpvVh", opts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "o:t:d:zpvV::h", opts, NULL)) != -1) { switch (opt) { case 'o': origin = optarg; @@ -105,7 +105,7 @@ int main(int argc, char *argv[]) print_help(); return EXIT_SUCCESS; case 'V': - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, optarg != NULL); return EXIT_SUCCESS; case 'd': optional = str2bool(optarg) ? SEMCHECK_DNSSEC_ON : SEMCHECK_DNSSEC_OFF; diff --git a/src/utils/kzonesign/main.c b/src/utils/kzonesign/main.c index e70abb6..641acfc 100644 --- a/src/utils/kzonesign/main.c +++ b/src/utils/kzonesign/main.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -117,7 +117,7 @@ static int zonesign(sign_params_t *params) goto fail; } - ret = knot_dnssec_validate_zone(&up, conf(), params->timestamp, false); + ret = knot_dnssec_validate_zone(&up, conf(), params->timestamp, false, false); if (ret != KNOT_EOK) { ERR2("DNSSEC validation failed (%s)", knot_strerror(ret)); char type_str[16]; @@ -204,7 +204,7 @@ int main(int argc, char *argv[]) { "verify" , no_argument, NULL, 'v' }, { "time", required_argument, NULL, 't' }, { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, + { "version", optional_argument, NULL, 'V' }, { NULL } }; @@ -212,7 +212,7 @@ int main(int argc, char *argv[]) signal_init_std(); int opt = 0; - while ((opt = getopt_long(argc, argv, "c:C:o:rvt:hV", opts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "c:C:o:rvt:hV::", opts, NULL)) != -1) { switch (opt) { case 'c': if (util_conf_init_file(optarg) != KNOT_EOK) { @@ -245,7 +245,7 @@ int main(int argc, char *argv[]) print_help(); goto success; case 'V': - print_version(PROGRAM_NAME); + print_version(PROGRAM_NAME, optarg != NULL); goto success; default: print_help(); diff --git a/tests-fuzz/Makefile.am b/tests-fuzz/Makefile.am index dcf18a6..489153d 100644 --- a/tests-fuzz/Makefile.am +++ b/tests-fuzz/Makefile.am @@ -31,7 +31,8 @@ knotd_stdio_CPPFLAGS = \ $(libkqueue_CFLAGS) \ $(liburcu_CFLAGS) \ $(lmdb_CFLAGS) \ - $(systemd_CFLAGS) + $(systemd_CFLAGS) \ + $(libdbus_CFLAGS) knotd_stdio_LDADD = \ $(top_builddir)/src/libknotd.la \ @@ -43,7 +44,8 @@ knotd_stdio_LDADD = \ $(gnutls_LIBS) \ $(liburcu_LIBS) \ $(lmdb_LIBS) \ - $(systemd_LIBS) + $(systemd_LIBS) \ + $(libdbus_LIBS) BUILT_SOURCES = knotd_wrap/main.c CLEANFILES = knotd_wrap/main.c diff --git a/tests-fuzz/Makefile.in b/tests-fuzz/Makefile.in index 7c94673..55650c4 100644 --- a/tests-fuzz/Makefile.in +++ b/tests-fuzz/Makefile.in @@ -205,7 +205,7 @@ knotd_stdio_OBJECTS = $(am_knotd_stdio_OBJECTS) \ @HAVE_DAEMON_TRUE@ $(top_builddir)/src/libzscanner.la \ @HAVE_DAEMON_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ @HAVE_DAEMON_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ -@HAVE_DAEMON_TRUE@ $(am__DEPENDENCIES_1) +@HAVE_DAEMON_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -623,6 +623,8 @@ infodir = @infodir@ install_sh = @install_sh@ libbpf_CFLAGS = @libbpf_CFLAGS@ libbpf_LIBS = @libbpf_LIBS@ +libdbus_CFLAGS = @libdbus_CFLAGS@ +libdbus_LIBS = @libdbus_LIBS@ libdir = @libdir@ libdnssec_SONAME = @libdnssec_SONAME@ libdnssec_SOVERSION = @libdnssec_SOVERSION@ @@ -634,8 +636,6 @@ libfstrm_CFLAGS = @libfstrm_CFLAGS@ libfstrm_LIBS = @libfstrm_LIBS@ libidn2_CFLAGS = @libidn2_CFLAGS@ libidn2_LIBS = @libidn2_LIBS@ -libidn_CFLAGS = @libidn_CFLAGS@ -libidn_LIBS = @libidn_LIBS@ libknot_SONAME = @libknot_SONAME@ libknot_SOVERSION = @libknot_SOVERSION@ libknot_VERSION_INFO = @libknot_VERSION_INFO@ @@ -653,7 +653,6 @@ libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@ libprotobuf_c_LIBS = @libprotobuf_c_LIBS@ liburcu_CFLAGS = @liburcu_CFLAGS@ liburcu_LIBS = @liburcu_LIBS@ -liburcu_PKGCONFIG = @liburcu_PKGCONFIG@ libxdp_CFLAGS = @libxdp_CFLAGS@ libxdp_LIBS = @libxdp_LIBS@ libzscanner_SONAME = @libzscanner_SONAME@ @@ -715,7 +714,8 @@ FUZZERS = \ @HAVE_DAEMON_TRUE@ $(libkqueue_CFLAGS) \ @HAVE_DAEMON_TRUE@ $(liburcu_CFLAGS) \ @HAVE_DAEMON_TRUE@ $(lmdb_CFLAGS) \ -@HAVE_DAEMON_TRUE@ $(systemd_CFLAGS) +@HAVE_DAEMON_TRUE@ $(systemd_CFLAGS) \ +@HAVE_DAEMON_TRUE@ $(libdbus_CFLAGS) @HAVE_DAEMON_TRUE@knotd_stdio_LDADD = \ @HAVE_DAEMON_TRUE@ $(top_builddir)/src/libknotd.la \ @@ -727,7 +727,8 @@ FUZZERS = \ @HAVE_DAEMON_TRUE@ $(gnutls_LIBS) \ @HAVE_DAEMON_TRUE@ $(liburcu_LIBS) \ @HAVE_DAEMON_TRUE@ $(lmdb_LIBS) \ -@HAVE_DAEMON_TRUE@ $(systemd_LIBS) +@HAVE_DAEMON_TRUE@ $(systemd_LIBS) \ +@HAVE_DAEMON_TRUE@ $(libdbus_LIBS) @HAVE_DAEMON_TRUE@BUILT_SOURCES = knotd_wrap/main.c @HAVE_DAEMON_TRUE@CLEANFILES = knotd_wrap/main.c diff --git a/tests/Makefile.am b/tests/Makefile.am index c173b61..bbcf8b8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -14,7 +14,8 @@ if HAVE_DAEMON LDADD += \ $(top_builddir)/src/libknotd.la \ $(liburcu_LIBS) \ - $(systemd_LIBS) + $(systemd_LIBS) \ + $(libdbus_LIBS) endif HAVE_DAEMON LDADD += \ @@ -47,6 +48,7 @@ libtap_la_SOURCES = \ EXTRA_PROGRAMS = tap/runtests check_PROGRAMS = \ + contrib/test_atomic \ contrib/test_base32hex \ contrib/test_base64 \ contrib/test_base64url \ diff --git a/tests/Makefile.in b/tests/Makefile.in index 3170082..b0c576a 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -90,14 +90,16 @@ host_triplet = @host@ @HAVE_DAEMON_TRUE@am__append_1 = \ @HAVE_DAEMON_TRUE@ $(top_builddir)/src/libknotd.la \ @HAVE_DAEMON_TRUE@ $(liburcu_LIBS) \ -@HAVE_DAEMON_TRUE@ $(systemd_LIBS) +@HAVE_DAEMON_TRUE@ $(systemd_LIBS) \ +@HAVE_DAEMON_TRUE@ $(libdbus_LIBS) EXTRA_PROGRAMS = tap/runtests$(EXEEXT) \ libzscanner/zscanner-tool$(EXEEXT) -check_PROGRAMS = contrib/test_base32hex$(EXEEXT) \ - contrib/test_base64$(EXEEXT) contrib/test_base64url$(EXEEXT) \ - contrib/test_heap$(EXEEXT) contrib/test_inet_ntop$(EXEEXT) \ - contrib/test_net$(EXEEXT) contrib/test_net_shortwrite$(EXEEXT) \ +check_PROGRAMS = contrib/test_atomic$(EXEEXT) \ + contrib/test_base32hex$(EXEEXT) contrib/test_base64$(EXEEXT) \ + contrib/test_base64url$(EXEEXT) contrib/test_heap$(EXEEXT) \ + contrib/test_inet_ntop$(EXEEXT) contrib/test_net$(EXEEXT) \ + contrib/test_net_shortwrite$(EXEEXT) \ contrib/test_qp-trie$(EXEEXT) contrib/test_qp-cow$(EXEEXT) \ contrib/test_siphash$(EXEEXT) contrib/test_sockaddr$(EXEEXT) \ contrib/test_spinlock$(EXEEXT) contrib/test_string$(EXEEXT) \ @@ -236,13 +238,23 @@ AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = -contrib_test_base32hex_SOURCES = contrib/test_base32hex.c -contrib_test_base32hex_OBJECTS = contrib/test_base32hex.$(OBJEXT) -contrib_test_base32hex_LDADD = $(LDADD) +contrib_test_atomic_SOURCES = contrib/test_atomic.c +contrib_test_atomic_OBJECTS = contrib/test_atomic.$(OBJEXT) +contrib_test_atomic_LDADD = $(LDADD) am__DEPENDENCIES_1 = @HAVE_DAEMON_TRUE@am__DEPENDENCIES_2 = \ @HAVE_DAEMON_TRUE@ $(top_builddir)/src/libknotd.la \ -@HAVE_DAEMON_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +@HAVE_DAEMON_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ +@HAVE_DAEMON_TRUE@ $(am__DEPENDENCIES_1) +contrib_test_atomic_DEPENDENCIES = libtap.la $(am__DEPENDENCIES_2) \ + $(top_builddir)/src/libknot.la \ + $(top_builddir)/src/libdnssec.la \ + $(top_builddir)/src/libcontrib.la \ + $(top_builddir)/src/libzscanner.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +contrib_test_base32hex_SOURCES = contrib/test_base32hex.c +contrib_test_base32hex_OBJECTS = contrib/test_base32hex.$(OBJEXT) +contrib_test_base32hex_LDADD = $(LDADD) contrib_test_base32hex_DEPENDENCIES = libtap.la $(am__DEPENDENCIES_2) \ $(top_builddir)/src/libknot.la \ $(top_builddir)/src/libdnssec.la \ @@ -1058,7 +1070,8 @@ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles -am__depfiles_remade = contrib/$(DEPDIR)/test_base32hex.Po \ +am__depfiles_remade = contrib/$(DEPDIR)/test_atomic.Po \ + contrib/$(DEPDIR)/test_base32hex.Po \ contrib/$(DEPDIR)/test_base64.Po \ contrib/$(DEPDIR)/test_base64url.Po \ contrib/$(DEPDIR)/test_heap.Po \ @@ -1155,20 +1168,21 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(libtap_la_SOURCES) contrib/test_base32hex.c \ - contrib/test_base64.c contrib/test_base64url.c \ - contrib/test_heap.c contrib/test_inet_ntop.c \ - contrib/test_net.c contrib/test_net_shortwrite.c \ - contrib/test_qp-cow.c contrib/test_qp-trie.c \ - contrib/test_siphash.c contrib/test_sockaddr.c \ - contrib/test_spinlock.c contrib/test_string.c \ - contrib/test_strtonum.c contrib/test_time.c \ - contrib/test_toeplitz.c contrib/test_wire_ctx.c \ - $(knot_test_acl_SOURCES) knot/test_changeset.c \ - $(knot_test_conf_SOURCES) knot/test_conf_tools.c \ - $(knot_test_confdb_SOURCES) $(knot_test_confio_SOURCES) \ - knot/test_digest.c knot/test_dthreads.c knot/test_fdset.c \ - knot/test_journal.c knot/test_kasp_db.c knot/test_node.c \ +SOURCES = $(libtap_la_SOURCES) contrib/test_atomic.c \ + contrib/test_base32hex.c contrib/test_base64.c \ + contrib/test_base64url.c contrib/test_heap.c \ + contrib/test_inet_ntop.c contrib/test_net.c \ + contrib/test_net_shortwrite.c contrib/test_qp-cow.c \ + contrib/test_qp-trie.c contrib/test_siphash.c \ + contrib/test_sockaddr.c contrib/test_spinlock.c \ + contrib/test_string.c contrib/test_strtonum.c \ + contrib/test_time.c contrib/test_toeplitz.c \ + contrib/test_wire_ctx.c $(knot_test_acl_SOURCES) \ + knot/test_changeset.c $(knot_test_conf_SOURCES) \ + knot/test_conf_tools.c $(knot_test_confdb_SOURCES) \ + $(knot_test_confio_SOURCES) knot/test_digest.c \ + knot/test_dthreads.c knot/test_fdset.c knot/test_journal.c \ + knot/test_kasp_db.c knot/test_node.c \ $(knot_test_process_query_SOURCES) knot/test_query_module.c \ knot/test_requestor.c knot/test_server.c \ knot/test_unreachable.c knot/test_worker_pool.c \ @@ -1197,18 +1211,18 @@ SOURCES = $(libtap_la_SOURCES) contrib/test_base32hex.c \ libknot/test_yptrafo.c $(libzscanner_zscanner_tool_SOURCES) \ modules/test_onlinesign.c modules/test_rrl.c tap/runtests.c \ utils/test_lookup.c -DIST_SOURCES = $(libtap_la_SOURCES) contrib/test_base32hex.c \ - contrib/test_base64.c contrib/test_base64url.c \ - contrib/test_heap.c contrib/test_inet_ntop.c \ - contrib/test_net.c contrib/test_net_shortwrite.c \ - contrib/test_qp-cow.c contrib/test_qp-trie.c \ - contrib/test_siphash.c contrib/test_sockaddr.c \ - contrib/test_spinlock.c contrib/test_string.c \ - contrib/test_strtonum.c contrib/test_time.c \ - contrib/test_toeplitz.c contrib/test_wire_ctx.c \ - $(am__knot_test_acl_SOURCES_DIST) knot/test_changeset.c \ - $(am__knot_test_conf_SOURCES_DIST) knot/test_conf_tools.c \ - $(am__knot_test_confdb_SOURCES_DIST) \ +DIST_SOURCES = $(libtap_la_SOURCES) contrib/test_atomic.c \ + contrib/test_base32hex.c contrib/test_base64.c \ + contrib/test_base64url.c contrib/test_heap.c \ + contrib/test_inet_ntop.c contrib/test_net.c \ + contrib/test_net_shortwrite.c contrib/test_qp-cow.c \ + contrib/test_qp-trie.c contrib/test_siphash.c \ + contrib/test_sockaddr.c contrib/test_spinlock.c \ + contrib/test_string.c contrib/test_strtonum.c \ + contrib/test_time.c contrib/test_toeplitz.c \ + contrib/test_wire_ctx.c $(am__knot_test_acl_SOURCES_DIST) \ + knot/test_changeset.c $(am__knot_test_conf_SOURCES_DIST) \ + knot/test_conf_tools.c $(am__knot_test_confdb_SOURCES_DIST) \ $(am__knot_test_confio_SOURCES_DIST) knot/test_digest.c \ knot/test_dthreads.c knot/test_fdset.c knot/test_journal.c \ knot/test_kasp_db.c knot/test_node.c \ @@ -1397,6 +1411,8 @@ infodir = @infodir@ install_sh = @install_sh@ libbpf_CFLAGS = @libbpf_CFLAGS@ libbpf_LIBS = @libbpf_LIBS@ +libdbus_CFLAGS = @libdbus_CFLAGS@ +libdbus_LIBS = @libdbus_LIBS@ libdir = @libdir@ libdnssec_SONAME = @libdnssec_SONAME@ libdnssec_SOVERSION = @libdnssec_SOVERSION@ @@ -1408,8 +1424,6 @@ libfstrm_CFLAGS = @libfstrm_CFLAGS@ libfstrm_LIBS = @libfstrm_LIBS@ libidn2_CFLAGS = @libidn2_CFLAGS@ libidn2_LIBS = @libidn2_LIBS@ -libidn_CFLAGS = @libidn_CFLAGS@ -libidn_LIBS = @libidn_LIBS@ libknot_SONAME = @libknot_SONAME@ libknot_SOVERSION = @libknot_SOVERSION@ libknot_VERSION_INFO = @libknot_VERSION_INFO@ @@ -1427,7 +1441,6 @@ libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@ libprotobuf_c_LIBS = @libprotobuf_c_LIBS@ liburcu_CFLAGS = @liburcu_CFLAGS@ liburcu_LIBS = @liburcu_LIBS@ -liburcu_PKGCONFIG = @liburcu_PKGCONFIG@ libxdp_CFLAGS = @libxdp_CFLAGS@ libxdp_LIBS = @libxdp_LIBS@ libzscanner_SONAME = @libzscanner_SONAME@ @@ -1609,6 +1622,12 @@ contrib/$(am__dirstamp): contrib/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) contrib/$(DEPDIR) @: > contrib/$(DEPDIR)/$(am__dirstamp) +contrib/test_atomic.$(OBJEXT): contrib/$(am__dirstamp) \ + contrib/$(DEPDIR)/$(am__dirstamp) + +contrib/test_atomic$(EXEEXT): $(contrib_test_atomic_OBJECTS) $(contrib_test_atomic_DEPENDENCIES) $(EXTRA_contrib_test_atomic_DEPENDENCIES) contrib/$(am__dirstamp) + @rm -f contrib/test_atomic$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(contrib_test_atomic_OBJECTS) $(contrib_test_atomic_LDADD) $(LIBS) contrib/test_base32hex.$(OBJEXT): contrib/$(am__dirstamp) \ contrib/$(DEPDIR)/$(am__dirstamp) @@ -2179,6 +2198,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@contrib/$(DEPDIR)/test_atomic.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/$(DEPDIR)/test_base32hex.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/$(DEPDIR)/test_base64.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/$(DEPDIR)/test_base64url.Po@am__quote@ # am--include-marker @@ -2486,7 +2506,8 @@ clean-am: clean-checkLTLIBRARIES clean-checkPROGRAMS clean-generic \ clean-libtool mostlyclean-am distclean: distclean-am - -rm -f contrib/$(DEPDIR)/test_base32hex.Po + -rm -f contrib/$(DEPDIR)/test_atomic.Po + -rm -f contrib/$(DEPDIR)/test_base32hex.Po -rm -f contrib/$(DEPDIR)/test_base64.Po -rm -f contrib/$(DEPDIR)/test_base64url.Po -rm -f contrib/$(DEPDIR)/test_heap.Po @@ -2621,7 +2642,8 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -f contrib/$(DEPDIR)/test_base32hex.Po + -rm -f contrib/$(DEPDIR)/test_atomic.Po + -rm -f contrib/$(DEPDIR)/test_base32hex.Po -rm -f contrib/$(DEPDIR)/test_base64.Po -rm -f contrib/$(DEPDIR)/test_base64url.Po -rm -f contrib/$(DEPDIR)/test_heap.Po diff --git a/tests/contrib/test_atomic.c b/tests/contrib/test_atomic.c new file mode 100644 index 0000000..88cae40 --- /dev/null +++ b/tests/contrib/test_atomic.c @@ -0,0 +1,165 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include +#include +#include + +#include "contrib/atomic.h" +#include "knot/server/dthreads.h" + +#define THREADS 16 +#define CYCLES1 100000 +#define CYCLES2 2000000 +#define CYCLES3 100000 +#define UPPER 0xffffffff00000000 +#define LOWER 0x00000000ffffffff +#define UPPER_PTR ((void *) UPPER) +#define LOWER_PTR ((void *) LOWER) + +static volatile knot_atomic_uint64_t counter_add = 0; +static volatile knot_atomic_uint64_t counter_sub = 0; +static volatile knot_atomic_uint64_t atomic_var; +static volatile knot_atomic_ptr_t atomic_var2; +static int errors = 0; +static int uppers; +static int lowers; +static int uppers_count = 0; +static int lowers_count = 0; +static pthread_mutex_t mx; + +static int thread_add(struct dthread *thread) +{ + for (int i = 0; i < CYCLES1; i++) { + ATOMIC_ADD(counter_add, 7); + ATOMIC_SUB(counter_sub, 7); + } + + return 0; +} + +static int thread_set(struct dthread *thread) +{ + u_int64_t val = (dt_get_id(thread) % 2) ? UPPER : LOWER; + + for (int i = 0; i < CYCLES2; i++) { + ATOMIC_SET(atomic_var, val); + volatile u_int64_t read = ATOMIC_GET(atomic_var); + if (read != UPPER && read != LOWER) { + // Non-atomic counter, won't be accurate! + // However, it's sufficient for fault detection. + errors++; + } + } + + return 0; +} + +static int thread_xchg(struct dthread *thread) +{ + void *val = (dt_get_id(thread) % 2) ? UPPER_PTR : LOWER_PTR; + + pthread_mutex_lock(&mx); + if (val == UPPER_PTR) { + uppers++; + } else { + lowers++; + }; + pthread_mutex_unlock(&mx); + + for (int i = 0; i < CYCLES3; i++) { + val = ATOMIC_XCHG(atomic_var2, val); + if (val != UPPER_PTR && val != LOWER_PTR) { + // Non-atomic counter, won't be accurate! + // However, it's sufficient for fault detection. + errors++; + return 0; + } + } + + pthread_mutex_lock(&mx); + if (val == UPPER_PTR) { + uppers_count++; + } else if (val == LOWER_PTR) { + lowers_count++; + }; + pthread_mutex_unlock(&mx); + + return 0; +} + +// Signal handler +static void interrupt_handle(int s) +{ +} + +int main(int argc, char *argv[]) +{ + plan_lazy(); + + // Register service and signal handler + struct sigaction sa; + sa.sa_handler = interrupt_handle; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGALRM, &sa, NULL); // Interrupt + + // Test for atomicity of ATOMIC_ADD and ATOMIC_SUB. + dt_unit_t *unit = dt_create(THREADS, thread_add, NULL, NULL); + dt_start(unit); + dt_join(unit); + dt_delete(&unit); + + is_int(THREADS * CYCLES1 * 7, counter_add, "atomicity of ATOMIC_ADD"); + is_int(THREADS * CYCLES1 * 7, -counter_sub, "atomicity of ATOMIC_SUB"); + + // Test for atomicity of ATOMIC_SET and ATOMIC_GET. + unit = dt_create(THREADS, thread_set, NULL, NULL); + dt_start(unit); + dt_join(unit); + dt_delete(&unit); + + is_int(0, errors, "atomicity of ATOMIC_SET / ATOMIC_GET"); + + // Test for atomicity of ATOMIC_XCHG. + errors = 0; + uppers = 0; // Initialize in code so as to calm down Coverity. + lowers = 0; // Idem. + + atomic_var2 = UPPER_PTR; + uppers++; + + pthread_mutex_init(&mx, NULL); + unit = dt_create(THREADS, thread_xchg, NULL, NULL); + dt_start(unit); + dt_join(unit); + dt_delete(&unit); + pthread_mutex_destroy(&mx); + + if (atomic_var2 == UPPER_PTR) { + uppers_count++; + } else if (atomic_var2 == LOWER_PTR) { + lowers_count++; + } else { + errors++; + } + + is_int(0, errors, "set/get atomicity of ATOMIC_XCHG"); + is_int(uppers, uppers_count, "atomicity of ATOMIC_XCHG"); + is_int(lowers, lowers_count, "atomicity of ATOMIC_XCHG"); + + return 0; +} diff --git a/tests/knot/semantic_check_data/soa.duplicate b/tests/knot/semantic_check_data/soa.duplicate new file mode 100644 index 0000000..8b84745 --- /dev/null +++ b/tests/knot/semantic_check_data/soa.duplicate @@ -0,0 +1,5 @@ +$ORIGIN example.com. + +@ SOA dns1 hostmaster 1 1000 360 10000 7200 +@ NS example.net. +@ SOA dns1 hostmaster 1 1000 360 10000 7200 diff --git a/tests/knot/semantic_check_data/soa.missing b/tests/knot/semantic_check_data/soa.missing new file mode 100644 index 0000000..cda9e84 --- /dev/null +++ b/tests/knot/semantic_check_data/soa.missing @@ -0,0 +1,3 @@ +$ORIGIN example.com. + +@ NS example.net. diff --git a/tests/knot/semantic_check_data/soa.multiple b/tests/knot/semantic_check_data/soa.multiple new file mode 100644 index 0000000..f41485c --- /dev/null +++ b/tests/knot/semantic_check_data/soa.multiple @@ -0,0 +1,5 @@ +$ORIGIN example.com. + +@ SOA dns1 hostmaster 1 1000 360 10000 7200 +@ NS example.net. +@ SOA dns1 hostmaster 2 1000 360 10000 7200 diff --git a/tests/knot/test_confdb.c b/tests/knot/test_confdb.c index e149f8d..28e4e0e 100644 --- a/tests/knot/test_confdb.c +++ b/tests/knot/test_confdb.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -392,7 +392,7 @@ static void test_conf_db_unset(conf_t *conf, knot_db_txn_t *txn) // Unset multivalued item with id - all data at one step (non-null data!). check_unset(conf, txn, C_ZONE, C_MASTER, (uint8_t *)"id", 2, KNOT_EOK, - NULL + 1, 0, NULL, 0); + (void *)8, 0, NULL, 0); // Unset group id. check_unset(conf, txn, C_ZONE, NULL, (uint8_t *)"id", 2, KNOT_EOK, diff --git a/tests/knot/test_confio.c b/tests/knot/test_confio.c index 44bc7c5..07bad05 100644 --- a/tests/knot/test_confio.c +++ b/tests/knot/test_confio.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -999,7 +999,7 @@ static const yp_item_t desc_server[] = { static const yp_item_t desc_xdp[] = { { C_UDP, YP_TBOOL, YP_VNONE }, { C_TCP, YP_TBOOL, YP_VNONE }, - { C_QUIC, YP_TBOOL, YP_VNONE }, + { C_QUIC, YP_TBOOL, YP_VNONE }, { C_TCP_MAX_CLIENTS, YP_TINT, YP_VNONE }, { C_TCP_INBUF_MAX_SIZE, YP_TINT, YP_VNONE }, { C_TCP_OUTBUF_MAX_SIZE,YP_TINT, YP_VNONE }, @@ -1007,6 +1007,9 @@ static const yp_item_t desc_xdp[] = { { C_TCP_IDLE_RESET, YP_TINT, YP_VNONE }, { C_TCP_RESEND, YP_TINT, YP_VNONE }, { C_ROUTE_CHECK, YP_TBOOL, YP_VNONE }, + { C_RING_SIZE, YP_TINT, YP_VNONE }, + { C_BUSYPOLL_BUDGET, YP_TINT, YP_VNONE }, + { C_BUSYPOLL_TIMEOUT, YP_TINT, YP_VNONE }, { NULL } }; diff --git a/tests/knot/test_query_module.c b/tests/knot/test_query_module.c index 4ab14d2..d31fa7c 100644 --- a/tests/knot/test_query_module.c +++ b/tests/knot/test_query_module.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,11 +20,10 @@ #include "libknot/libknot.h" #include "knot/nameserver/query_module.h" -#include "libknot/packet/pkt.h" /* Universal processing stage. */ -unsigned state_visit(unsigned state, knot_pkt_t *pkt, knotd_qdata_t *qdata, - knotd_mod_t *mod) +knotd_state_t state_visit(knotd_state_t state, knot_pkt_t *pkt, knotd_qdata_t *qdata, + knotd_mod_t *mod) { /* Visit current state */ bool *state_map = (bool *)mod; @@ -49,8 +48,8 @@ int main(int argc, char *argv[]) /* Register all stage visits. */ int ret = KNOT_EOK; - for (unsigned stage = KNOTD_STAGE_BEGIN; stage < KNOTD_STAGES; ++stage) { - ret = query_plan_step(plan, stage, state_visit, state_map); + for (unsigned stage = KNOTD_STAGE_PROTO_BEGIN; stage < KNOTD_STAGES; ++stage) { + ret = query_plan_step(plan, stage, QUERY_HOOK_TYPE_GENERAL, state_visit, state_map); if (ret != KNOT_EOK) { break; } @@ -59,10 +58,10 @@ int main(int argc, char *argv[]) /* Execute the plan. */ int state = 0, next_state = 0; - for (unsigned stage = KNOTD_STAGE_BEGIN; stage < KNOTD_STAGES; ++stage) { + for (unsigned stage = KNOTD_STAGE_PROTO_BEGIN; stage < KNOTD_STAGES; ++stage) { struct query_step *step = NULL; WALK_LIST(step, plan->stage[stage]) { - next_state = step->process(state, NULL, NULL, step->ctx); + next_state = step->general_hook(state, NULL, NULL, step->ctx); if (next_state != state + 1) { break; } diff --git a/tests/knot/test_semantic_check.in b/tests/knot/test_semantic_check.in index 73fb6e7..e91e9dc 100644 --- a/tests/knot/test_semantic_check.in +++ b/tests/knot/test_semantic_check.in @@ -48,6 +48,8 @@ if [ ! -x $KZONECHECK ]; then fi # error messages exported from knot/src/zone/semantic-check.c +SOA_NONE="missing SOA at the zone apex" +SOA_MULTIPLE="multiple SOA records" CDNSKEY_NONE="missing CDNSKEY" CDNSKEY_NO_CDS="CDNSKEY without corresponding CDS" CDNSKEY_DELETE="invalid CDNSKEY/CDS for DNSSEC delete algorithm" @@ -74,6 +76,8 @@ RRSIG_UNVERIFIABLE="no valid signature for a record" plan_lazy +expect_error "soa.missing" 1 1 "$SOA_MISSING" +expect_error "soa.multiple" 1 1 "$SOA_MULTIPLE" expect_error "cname_extra_01.zone" 1 1 "$CNAME_EXTRA_RECORDS" expect_error "cname_extra_02.signed" 1 1 "$CNAME_EXTRA_RECORDS" expect_error "cname_multiple.zone" 1 1 "$CNAME_MULTIPLE" @@ -127,6 +131,7 @@ expect_error "cdnskey.delete.invalid.cdnskey" 0 1 "$CDNSKEY_DELETE" expect_error "delegation.signed" 0 1 "$NSEC_RDATA_BITMAP" expect_error "nsec_nonauth.invalid" 0 1 "$NSEC_EXTRA" +test_correct "soa.duplicate" test_correct "rrsig_ttl.signed" test_correct "no_error_delegation_bitmap.signed" test_correct "no_error_nsec3_optout.signed" diff --git a/tests/libdnssec/test_key.c b/tests/libdnssec/test_key.c index 4f05405..effbe1a 100644 --- a/tests/libdnssec/test_key.c +++ b/tests/libdnssec/test_key.c @@ -192,9 +192,7 @@ int main(void) static const keyinfo_t keys[] = { { "RSA", &SAMPLE_RSA_KEY }, { "ECDSA", &SAMPLE_ECDSA_KEY }, -#ifdef HAVE_ED25519 { "ED25519", &SAMPLE_ED25519_KEY }, -#endif #ifdef HAVE_ED448 { "ED448", &SAMPLE_ED448_KEY }, #endif diff --git a/tests/libdnssec/test_key_algorithm.c b/tests/libdnssec/test_key_algorithm.c index 6c62106..75eace7 100644 --- a/tests/libdnssec/test_key_algorithm.c +++ b/tests/libdnssec/test_key_algorithm.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -59,9 +59,7 @@ static void check_defaults(void) { is_int(2048, dnssec_algorithm_key_size_default(DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3), "rsa default"); is_int(256, dnssec_algorithm_key_size_default(DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256), "ecc default"); -#ifdef HAVE_ED25519 is_int(256, dnssec_algorithm_key_size_default(DNSSEC_KEY_ALGORITHM_ED25519), "ed25519 default"); -#endif #ifdef HAVE_ED448 is_int(456, dnssec_algorithm_key_size_default(DNSSEC_KEY_ALGORITHM_ED448), "ed448 default"); #endif @@ -74,9 +72,7 @@ int main(void) // ranges ok_range(DNSSEC_KEY_ALGORITHM_RSA_SHA512, 1024, 4096, "RSA/SHA256"); ok_range(DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384, 384, 384, "ECDSA/SHA384"); -#ifdef HAVE_ED25519 ok_range(DNSSEC_KEY_ALGORITHM_ED25519, 256, 256, "ED25519"); -#endif #ifdef HAVE_ED448 ok_range(DNSSEC_KEY_ALGORITHM_ED448, 456, 456, "ED448"); #endif diff --git a/tests/libdnssec/test_key_ds.c b/tests/libdnssec/test_key_ds.c index 29acf05..e076243 100644 --- a/tests/libdnssec/test_key_ds.c +++ b/tests/libdnssec/test_key_ds.c @@ -101,17 +101,13 @@ int main(int argc, char *argv[]) test_key("RSA", &SAMPLE_RSA_KEY); test_key("ECDSA", &SAMPLE_ECDSA_KEY); -#ifdef HAVE_ED25519 test_key("ED25519", &SAMPLE_ED25519_KEY); -#endif #ifdef HAVE_ED448 test_key("ED448", &SAMPLE_ED448_KEY); #endif test_errors(&SAMPLE_ECDSA_KEY); -#ifdef HAVE_ED25519 test_errors(&SAMPLE_ED25519_KEY); -#endif #ifdef HAVE_ED448 test_errors(&SAMPLE_ED448_KEY); #endif diff --git a/tests/libdnssec/test_sign.c b/tests/libdnssec/test_sign.c index bdb19fb..933206f 100644 --- a/tests/libdnssec/test_sign.c +++ b/tests/libdnssec/test_sign.c @@ -57,7 +57,6 @@ static const dnssec_binary_t signed_ecdsa = { .size = 64, .data = (uint8_t []) { 0xad, 0x2f, }}; -#ifdef HAVE_ED25519 static const dnssec_binary_t signed_ed25519 = { .size = 64, .data = (uint8_t []) { 0x0a, 0x9e, 0x51, 0x5f, 0x16, 0x89, 0x49, 0x27, 0x0e, 0x98, 0x34, 0xd3, 0x48, 0xef, 0x5a, 0x6e, @@ -67,8 +66,7 @@ static const dnssec_binary_t signed_ed25519 = { .size = 64, .data = (uint8_t []) 0x1d, 0x08, 0x10, 0x20, 0x1c, 0x01, 0x77, 0x1b, 0x5a, 0x48, 0xd6, 0xe5, 0x1c, 0xf9, 0xe3, 0xe0, 0x70, 0x34, 0x5e, 0x02, 0x49, 0xfb, 0x9e, 0x05, - }}; -#endif +}}; #ifdef HAVE_ED448 static const dnssec_binary_t signed_ed448 = { .size = 114, .data = (uint8_t []) { @@ -82,7 +80,7 @@ static const dnssec_binary_t signed_ed448 = { .size = 114, .data = (uint8_t []) 0xe9, 0xb9, 0x76, 0xb8, 0xa6, 0xa9, 0x0a, 0x4f, 0x18, 0xe1, 0x62, 0x27, 0x74, 0x99, 0x01, 0x98, 0x5f, 0xdb, 0xea, 0xdf, 0xab, 0x59, 0x6c, 0x79, 0xe2, 0xc2, 0x2a, 0x91, 0x29, 0x00 - }}; +}}; #endif static dnssec_binary_t binary_set_string(char *str) @@ -188,10 +186,8 @@ int main(void) check_key(&SAMPLE_RSA_KEY, &input_data, &signed_rsa, true); diag("ECDSA signing"); check_key(&SAMPLE_ECDSA_KEY, &input_data, &signed_ecdsa, false); -#ifdef HAVE_ED25519 diag("ED25519 signing"); check_key(&SAMPLE_ED25519_KEY, &input_data, &signed_ed25519, true); -#endif #ifdef HAVE_ED448 diag("ED448 signing"); check_key(&SAMPLE_ED448_KEY, &input_data, &signed_ed448, true); diff --git a/tests/libknot/test_control.c b/tests/libknot/test_control.c index 3846f31..3467be4 100644 --- a/tests/libknot/test_control.c +++ b/tests/libknot/test_control.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -109,7 +109,7 @@ static void ctl_server(const char *socket, size_t argc, knot_ctl_data_t *argv) knot_ctl_t *ctl = knot_ctl_alloc(); ok(ctl != NULL, "Allocate control"); - int ret = knot_ctl_bind(ctl, socket); + int ret = knot_ctl_bind(ctl, socket, 5); is_int(KNOT_EOK, ret, "Bind control socket"); ret = knot_ctl_accept(ctl); diff --git a/tests/libknot/test_xdp_tcp.c b/tests/libknot/test_xdp_tcp.c index 7f3b994..4e02f57 100644 --- a/tests/libknot/test_xdp_tcp.c +++ b/tests/libknot/test_xdp_tcp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -213,7 +213,7 @@ void test_syn(void) knot_xdp_msg_t msg; knot_tcp_relay_t rl = { 0 }; prepare_msg(&msg, KNOT_XDP_MSG_SYN, 1, 2); - int ret = knot_tcp_recv(&rl, &msg, 1, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + int ret = knot_tcp_recv(&rl, &msg, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); is_int(KNOT_EOK, ret, "SYN: relay OK"); ret = knot_tcp_send(test_sock, &rl, 1, 1); is_int(KNOT_EOK, ret, "SYN: send OK"); @@ -241,7 +241,7 @@ void test_syn_ack_no(void) knot_xdp_msg_t msg; knot_tcp_relay_t rl = { 0 }; prepare_msg(&msg, KNOT_XDP_MSG_SYN | KNOT_XDP_MSG_ACK, 1, 2); - int ret = knot_tcp_recv(&rl, &msg, 1, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + int ret = knot_tcp_recv(&rl, &msg, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); is_int(KNOT_EOK, ret, "SYN+ACK deny: relay OK"); is_int(XDP_TCP_NOOP, rl.auto_answer, "SYN+ACK deny: no auto answer"); is_int(XDP_TCP_NOOP, rl.answer, "SYN+ACK deny: no answer"); @@ -256,7 +256,7 @@ void test_establish(void) knot_tcp_relay_t rl = { 0 }; prepare_msg(&msg, KNOT_XDP_MSG_ACK, 1, 2); prepare_seqack(&msg, 0, 1); - int ret = knot_tcp_recv(&rl, &msg, 1, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + int ret = knot_tcp_recv(&rl, &msg, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); is_int(KNOT_EOK, ret, "establish: relay OK"); is_int(0, test_syn_table->usage, "SYN: no connection in SYN table"); is_int(1, test_table->usage, "SYN: one connection in normal table"); @@ -274,7 +274,7 @@ void test_syn_ack(void) knot_xdp_msg_t msg; knot_tcp_relay_t rl = { 0 }; prepare_msg(&msg, KNOT_XDP_MSG_SYN | KNOT_XDP_MSG_ACK, 1000, 2000); - int ret = knot_tcp_recv(&rl, &msg, 1, test_table, NULL, XDP_TCP_IGNORE_NONE); + int ret = knot_tcp_recv(&rl, &msg, test_table, NULL, XDP_TCP_IGNORE_NONE); is_int(KNOT_EOK, ret, "SYN+ACK: relay OK"); ret = knot_tcp_send(test_sock, &rl, 1, 1); is_int(KNOT_EOK, ret, "SYN+ACK: send OK"); @@ -315,7 +315,10 @@ void test_data_fragments(void) prepare_data(&msgs[3], "\x02""AB""\xff\xff""abcdefghijklmnopqrstuvwxyz...", 34); assert(test_table); - int ret = knot_tcp_recv(rls, msgs, CONNS, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + int ret = KNOT_EOK; + for (int i = 0; i < CONNS && ret == KNOT_EOK; i++) { + ret = knot_tcp_recv(&rls[i], &msgs[i], test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + } is_int(KNOT_EOK, ret, "fragments: relay OK"); assert(test_sock); ret = knot_tcp_send(test_sock, rls, CONNS, CONNS); @@ -374,7 +377,7 @@ void test_close(void) knot_xdp_msg_t wrong = msg; wrong.seqno += INT32_MAX; wrong.ackno += INT32_MAX; - int ret = knot_tcp_recv(&rl, &wrong, 1, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + int ret = knot_tcp_recv(&rl, &wrong, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); is_int(KNOT_EOK, ret, "close: relay 0 OK"); is_int(KNOT_XDP_MSG_RST, rl.auto_answer, "close: reset wrong ackno"); is_int(rl.auto_seqno, wrong.ackno, "close: reset seqno"); @@ -383,7 +386,7 @@ void test_close(void) check_sent(0, 1, 0, 0); is_int(sent_seqno, wrong.ackno, "close: reset seqno sent"); - ret = knot_tcp_recv(&rl, &msg, 1, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + ret = knot_tcp_recv(&rl, &msg, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); is_int(KNOT_EOK, ret, "close: relay 1 OK"); ret = knot_tcp_send(test_sock, &rl, 1, 1); is_int(KNOT_EOK, ret, "close: send OK"); @@ -395,7 +398,7 @@ void test_close(void) msg.flags &= ~KNOT_XDP_MSG_FIN; prepare_seqack(&msg, 0, 0); - ret = knot_tcp_recv(&rl, &msg, 1, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + ret = knot_tcp_recv(&rl, &msg, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); is_int(KNOT_EOK, ret, "close: relay 2 OK"); ret = knot_tcp_send(test_sock, &rl, 1, 1); is_int(KNOT_EOK, ret, "close: send 2 OK"); @@ -418,7 +421,10 @@ void test_many(void) } knot_tcp_relay_t *rls = malloc(CONNS * sizeof(*rls)); - int ret = knot_tcp_recv(rls, msgs, CONNS, test_table, NULL, XDP_TCP_IGNORE_NONE); + int ret = KNOT_EOK; + for (int i = 0; i < CONNS && ret == KNOT_EOK; i++) { + ret = knot_tcp_recv(&rls[i], &msgs[i], test_table, NULL, XDP_TCP_IGNORE_NONE); + } is_int(KNOT_EOK, ret, "many: relay OK"); ret = knot_tcp_send(test_sock, rls, CONNS, CONNS); is_int(KNOT_EOK, ret, "many: relay send OK"); @@ -435,7 +441,7 @@ void test_many(void) fix_seqack(survive); prepare_data(survive, "\x00\x00", 2); assert(test_table); - ret = knot_tcp_recv(&surv_rl, survive, 1, test_table, NULL, XDP_TCP_IGNORE_NONE); + ret = knot_tcp_recv(&surv_rl, survive, test_table, NULL, XDP_TCP_IGNORE_NONE); is_int(KNOT_EOK, ret, "many/survivor: OK"); clean_sent(); @@ -479,7 +485,10 @@ void test_ibufs_size(void) for (int i = 0; i < CONNS; i++) { prepare_msg(&msgs[i], KNOT_XDP_MSG_SYN, i + 2000, 1); } - int ret = knot_tcp_recv(rls, msgs, CONNS, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + int ret = KNOT_EOK; + for (int i = 0; i < CONNS && ret == KNOT_EOK; i++) { + ret = knot_tcp_recv(&rls[i], &msgs[i], test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + } is_int(KNOT_EOK, ret, "ibufs: open OK"); ret = knot_tcp_send(test_sock, rls, CONNS, CONNS); is_int(KNOT_EOK, ret, "ibufs: first send OK"); @@ -488,14 +497,16 @@ void test_ibufs_size(void) msgs[i].flags = KNOT_XDP_MSG_TCP | KNOT_XDP_MSG_ACK; } fix_seqacks(msgs, CONNS); - (void)knot_tcp_recv(rls, msgs, CONNS, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + for (int i = 0; i < CONNS && ret == KNOT_EOK; i++) { + ret = knot_tcp_recv(&rls[i], &msgs[i], test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + } is_int(0, test_table->inbufs_total, "inbufs: initial total zero"); // first connection will start a fragment buf then finish it fix_seqack(&msgs[0]); prepare_data(&msgs[0], "\x00\x0a""lorem", 7); - ret = knot_tcp_recv(&rls[0], &msgs[0], 1, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + ret = knot_tcp_recv(&rls[0], &msgs[0], test_table, test_syn_table, XDP_TCP_IGNORE_NONE); is_int(KNOT_EOK, ret, "ibufs: must be OK"); ret = knot_tcp_send(test_sock, &rls[0], 1, 1); is_int(KNOT_EOK, ret, "ibufs: must send OK"); @@ -509,7 +520,9 @@ void test_ibufs_size(void) prepare_data(&msgs[1], "\x00\xff""12345", 7); prepare_data(&msgs[2], "\xff\xff""abcde", 7); prepare_data(&msgs[3], "\xff\xff""abcde", 7); - ret = knot_tcp_recv(rls, msgs, CONNS, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + for (int i = 0; i < CONNS && ret == KNOT_EOK; i++) { + ret = knot_tcp_recv(&rls[i], &msgs[i], test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + } is_int(KNOT_EOK, ret, "inbufs: relay OK"); ret = knot_tcp_send(test_sock, rls, CONNS, CONNS); is_int(KNOT_EOK, ret, "inbufs: send OK"); @@ -546,11 +559,11 @@ void test_obufs(void) knot_tcp_relay_t rl = { 0 }; prepare_msg(&msg, KNOT_XDP_MSG_SYN, 1, 2); - (void)knot_tcp_recv(&rl, &msg, 1, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); // SYN + (void)knot_tcp_recv(&rl, &msg, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); // SYN (void)knot_tcp_send(test_sock, &rl, 1, 1); // SYN+ACK prepare_msg(&msg, KNOT_XDP_MSG_ACK, 1, 2); prepare_seqack(&msg, 0, 1); - (void)knot_tcp_recv(&rl, &msg, 1, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); // ACK + (void)knot_tcp_recv(&rl, &msg, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); // ACK size_t TEST_MSS = 1111; size_t DATA_LEN = 65535; // with 2-byte len prefix, this is > 64k == window_size @@ -588,7 +601,7 @@ void test_obufs(void) memset(&rl, 0, sizeof(rl)); prepare_seqack(&msg, 0, TEST_MSS); - ret = knot_tcp_recv(&rl, &msg, 1, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); + ret = knot_tcp_recv(&rl, &msg, test_table, test_syn_table, XDP_TCP_IGNORE_NONE); is_int(KNOT_EOK, ret, "obufs: ACKed data"); assert(rl.conn); rl.conn->window_size = 65536; diff --git a/tests/libknot/test_yptrafo.c b/tests/libknot/test_yptrafo.c index cd26632..d76dbc4 100644 --- a/tests/libknot/test_yptrafo.c +++ b/tests/libknot/test_yptrafo.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -326,7 +326,10 @@ int main(int argc, char *argv[]) int_test("11s", 11LL * 1, YP_STIME, min, max); int_test("11m", 11LL * 60, YP_STIME, min, max); int_test("11h", 11LL * 3600, YP_STIME, min, max); - int_test("11d", 11LL * 24 * 3600, YP_STIME, min, max); + int_test("6d", 6LL * 24 * 3600, YP_STIME, min, max); + int_test("4w", 4LL * 7 * 24 * 3600, YP_STIME, min, max); + int_test("11M", 11LL * 30 * 24 * 3600, YP_STIME, min, max); + int_test("2y", 2LL * 365 * 24 * 3600, YP_STIME, min, max); int_test("1025B", 1025LL, YP_SSIZE, min, max); int_test("61s", 61LL, YP_STIME, min, max); int_bad_test("20000000001", KNOT_ERANGE, YP_SNONE, min, max); diff --git a/tests/modules/test_rrl.c b/tests/modules/test_rrl.c index 6a5210f..448ff9a 100644 --- a/tests/modules/test_rrl.c +++ b/tests/modules/test_rrl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,164 +15,404 @@ */ #include +#include +#include +#include +#include #include "libdnssec/crypto.h" #include "libdnssec/random.h" #include "libknot/libknot.h" +#include "contrib/openbsd/siphash.h" #include "contrib/sockaddr.h" + +#include "time.h" +int fakeclock_gettime(clockid_t clockid, struct timespec *tp); +#define clock_gettime fakeclock_gettime #include "knot/modules/rrl/functions.c" -#include "stdio.h" - -/* Enable time-dependent tests. */ -//#define ENABLE_TIMED_TESTS -#define RRL_SIZE 196613 -#define RRL_THREADS 8 -#define RRL_INSERTS (RRL_SIZE/(5*RRL_THREADS)) /* lf = 1/5 */ - -/* Disabled as default as it depends on random input. - * Table may be consistent even if some collision occur (and they may occur). - * Note: Disabled due to reported problems when running on VMs due to time - * flow inconsistencies. Should work alright on a host machine. - */ -#ifdef ENABLE_TIMED_TESTS -struct bucketmap { - unsigned i; - uint64_t x; +#undef clock_gettime + +#define RRL_THREADS 4 +//#define RRL_SYNC_WITH_REAL_TIME + +#define BATCH_QUERIES_LOG 3 // threads acquire queries in batches of 8 +#define HOSTS_LOG 3 // at most 6 attackers + 2 wildcard addresses for normal users +#define TICK_QUERIES_LOG 13 // at most 1024 queries per host per tick + +// Accessing RRL configuration of INSTANT/RATE limits for V4/V6 and specific prefix. +#define LIMIT(type, Vx, prefix) (RRL_MULT(Vx, prefix) * RRL_ ## type ## _LIMIT) + +#define RRL_CONFIG(Vx, name) RRL_ ## Vx ## _ ## name +#define RRL_MULT(Vx, prefix) get_mult(RRL_CONFIG(Vx, PREFIXES), RRL_CONFIG(Vx, RATE_MULT), RRL_CONFIG(Vx, PREFIXES_CNT), prefix) +static inline kru_price_t get_mult(uint8_t prefixes[], kru_price_t mults[], size_t cnt, uint8_t wanted_prefix) { + for (size_t i = 0; i < cnt; i++) + if (prefixes[i] == wanted_prefix) + return mults[i]; + assert(0); + return 0; +} + +// Macro correction depending on the table mode. +int DIFF = 0; + +// Instant limits and rate limits per msec. +#define INST(Vx, prefix) (LIMIT(INSTANT, Vx, prefix) + DIFF) +#define RATEM(Vx, prefix) (LIMIT(RATE, Vx, prefix) / 1000 + DIFF) + +// Expected range of limits for parallel test. +#define RANGE_INST(Vx, prefix) INST(Vx, prefix) - 1, INST(Vx, prefix) + RRL_THREADS - 1 +#define RANGE_RATEM(Vx, prefix) RATEM(Vx, prefix) - 1 - DIFF, RATEM(Vx, prefix) + RRL_THREADS - DIFF +#define RANGE_UNLIM(queries) queries, queries + +/* Fix seed for randomness in RLL module. Change if improbable collisions arise. (one byte) */ +#define RRL_SEED_GENERIC 1 +#define RRL_SEED_AVX2 1 + +struct kru_generic { + SIPHASH_KEY hash_key; + // ... +}; +struct kru_avx2 { + _Alignas(32) char hash_key[48]; + // ... +}; + +/* Override time in RRL module. */ +struct timespec fakeclock_start; +uint32_t fakeclock_tick = 0; + +void fakeclock_init(void) +{ + clock_gettime(CLOCK_MONOTONIC_COARSE, &fakeclock_start); + fakeclock_tick = 0; +} + +int fakeclock_gettime(clockid_t clockid, struct timespec *tp) +{ + uint32_t inc_msec = fakeclock_tick; + tp->tv_sec = fakeclock_start.tv_sec + (fakeclock_start.tv_nsec / 1000000 + inc_msec) / 1000; + tp->tv_nsec = (fakeclock_start.tv_nsec + (inc_msec % 1000) * 1000000) % 1000000000; + return 0; +} + +struct host { + uint32_t queries_per_tick; + int addr_family; + char *addr_format; + uint32_t min_passed, max_passed; + _Atomic uint32_t passed; +}; + +struct stage { + uint32_t first_tick, last_tick; + struct host hosts[1 << HOSTS_LOG]; }; -/*! \brief Unit runnable. */ struct runnable_data { - int passed; rrl_table_t *rrl; - struct sockaddr_storage *addr; - rrl_req_t *rq; - knot_dname_t *zone; + int prime; + _Atomic uint32_t *queries_acquired, *queries_done; + struct stage *stages; }; -static void* rrl_runnable(void *arg) +static void *rrl_runnable(void *arg) { struct runnable_data *d = (struct runnable_data *)arg; + size_t si = 0; + + char addr_str[40]; struct sockaddr_storage addr; - memcpy(&addr, d->addr, sizeof(struct sockaddr_storage)); - int lock = -1; - uint32_t now = time(NULL); - struct bucketmap *m = malloc(RRL_INSERTS * sizeof(struct bucketmap)); - for (unsigned i = 0; i < RRL_INSERTS; ++i) { - m[i].i = dnssec_random_uint32_t(); - ((struct sockaddr_in *) &addr)->sin_addr.s_addr = m[i].i; - rrl_item_t *b = rrl_hash(d->rrl, &addr, d->rq, d->zone, now, &lock); - rrl_unlock(d->rrl, lock); - m[i].x = b->netblk; + + while (true) { + uint32_t qi1 = atomic_fetch_add(d->queries_acquired, 1 << BATCH_QUERIES_LOG); + + /* increment time if needed; sync on incrementing using spinlock */ + uint32_t tick = qi1 >> TICK_QUERIES_LOG; + for (size_t i = 1; tick != fakeclock_tick; i++) { + if ((*d->queries_done >> TICK_QUERIES_LOG) >= tick) { + fakeclock_tick = tick; + } + if (i % (1<<14) == 0) sched_yield(); + __sync_synchronize(); + } + + /* increment stage if needed */ + while (tick > d->stages[si].last_tick) { + ++si; + if (!d->stages[si].first_tick) return NULL; + } + +#ifdef RRL_SYNC_WITH_REAL_TIME + { + struct timespec ts_fake, ts_real; + do { + fakeclock_gettime(CLOCK_MONOTONIC_COARSE, &ts_fake); + clock_gettime(CLOCK_MONOTONIC_COARSE, &ts_real); + } while (!((ts_real.tv_sec > ts_fake.tv_sec) || + ((ts_real.tv_sec == ts_fake.tv_sec) && (ts_real.tv_nsec >= ts_fake.tv_nsec)))); + } +#endif + + if (tick >= d->stages[si].first_tick) { + uint32_t qi2 = 0; + do { + uint32_t qi = qi1 + qi2; + + /* perform query qi */ + uint32_t hi = qi % (1 << HOSTS_LOG); + if (!d->stages[si].hosts[hi].queries_per_tick) continue; + uint32_t hqi = (qi % (1 << TICK_QUERIES_LOG)) >> HOSTS_LOG; // host query index within tick + if (hqi >= d->stages[si].hosts[hi].queries_per_tick) continue; + hqi += (qi >> TICK_QUERIES_LOG) * d->stages[si].hosts[hi].queries_per_tick; // across ticks + (void)snprintf(addr_str, sizeof(addr_str), d->stages[si].hosts[hi].addr_format, + hqi % 0xff, (hqi >> 8) % 0xff, (hqi >> 16) % 0xff); + sockaddr_set(&addr, d->stages[si].hosts[hi].addr_family, addr_str, 0); + + if (rrl_query(d->rrl, &addr, NULL) == KNOT_EOK) { + atomic_fetch_add(&d->stages[si].hosts[hi].passed, 1); + if (!d->rrl->rw_mode) { + rrl_update(d->rrl, &addr, 1); + } + } + + } while ((qi2 = (qi2 + d->prime) % (1 << BATCH_QUERIES_LOG))); + } + atomic_fetch_add(d->queries_done, 1 << BATCH_QUERIES_LOG); } - for (unsigned i = 0; i < RRL_INSERTS; ++i) { - ((struct sockaddr_in *) &addr)->sin_addr.s_addr = m[i].i; - rrl_item_t *b = rrl_hash(d->rrl, &addr, d->rq, d->zone, now, &lock); - rrl_unlock(d->rrl, lock); - if (b->netblk != m[i].x) { - d->passed = 0; +} + +char *impl_name = ""; +rrl_table_t *rrl = NULL; + +void count_test(char *desc, int expected_passing, double margin_fract, + int addr_family, char *addr_format, uint32_t min_value, uint32_t max_value) +{ + uint32_t max_queries = expected_passing > 0 ? 2 * expected_passing : -expected_passing; + struct sockaddr_storage addr; + char addr_str[40]; + int cnt = -1; + + for (size_t i = 0; i < max_queries; i++) { + (void)snprintf(addr_str, sizeof(addr_str), addr_format, + i % (max_value - min_value + 1) + min_value, + i / (max_value - min_value + 1) % 256); + sockaddr_set(&addr, addr_family, addr_str, 0); + if (rrl_query(rrl, &addr, NULL) != KNOT_EOK) { + cnt = i; + break; } + if (!rrl->rw_mode) { + rrl_update(rrl, &addr, 1); + } + } + + if (expected_passing < 0) expected_passing = -1; + if (margin_fract == 0) { + is_int(expected_passing, cnt, "rrl(%s): %-48s [%7d ]", impl_name, desc, expected_passing); + } else { + int max_diff = expected_passing * margin_fract; + ok((expected_passing - max_diff <= cnt) && (cnt <= expected_passing + max_diff), + "rrl(%s): %-48s [%7d <=%7d <=%7d ]", impl_name, desc, + expected_passing - max_diff, cnt, expected_passing + max_diff); } - free(m); - return NULL; } -static void rrl_hopscotch(struct runnable_data* rd) +void test_rrl(bool rw_mode) { - rd->passed = 1; + size_t RRL_TABLE_SIZE = (1 << 20); + uint32_t RRL_INSTANT_LIMIT = (1 << 7); + uint32_t RRL_RATE_LIMIT = (1 << 16); + if (rw_mode) { + RRL_INSTANT_LIMIT = (1 << 8); + RRL_RATE_LIMIT = (1 << 17); + } + + fakeclock_init(); + + /* create rrl table */ + rrl = rrl_create(RRL_TABLE_SIZE, RRL_INSTANT_LIMIT, RRL_RATE_LIMIT, rw_mode, 0); + ok(rrl != NULL, "rrl(%s): create", impl_name); + assert(rrl); + + if (KRU.initialize == KRU_GENERIC.initialize) { + struct kru_generic *kru = (struct kru_generic *) rrl->kru; + memset(&kru->hash_key, RRL_SEED_GENERIC, sizeof(kru->hash_key)); + } else if (KRU.initialize == KRU_AVX2.initialize) { + struct kru_avx2 *kru = (struct kru_avx2 *) rrl->kru; + memset(&kru->hash_key, RRL_SEED_AVX2, sizeof(kru->hash_key)); + } else { + assert(0); + } + + /* IPv4 multi-prefix tests */ + static_assert(RRL_V4_PREFIXES_CNT == 4, + "There are no more IPv4 limited prefixes (/32, /24, /20, /18 will be tested)."); + + count_test("IPv4 instant limit /32", INST(V4, 32), 0, + AF_INET, "128.0.0.0", 0, 0); + + count_test("IPv4 instant limit /32 not applied on /31", -1, 0, + AF_INET, "128.0.0.1", 0, 0); + + count_test("IPv4 instant limit /24", INST(V4, 24) - INST(V4, 32) - 1, 0, + AF_INET, "128.0.0.%d", 2, 255); + + count_test("IPv4 instant limit /24 not applied on /23", -1, 0, + AF_INET, "128.0.1.0", 0, 0); + + count_test("IPv4 instant limit /20", INST(V4, 20) - INST(V4, 24) - 1, 0.001, + AF_INET, "128.0.%d.%d", 2, 15); + + count_test("IPv4 instant limit /20 not applied on /19", -1, 0, + AF_INET, "128.0.16.0", 0, 0); + + count_test("IPv4 instant limit /18", INST(V4, 18) - INST(V4, 20) - 1, 0.01, + AF_INET, "128.0.%d.%d", 17, 63); + + count_test("IPv4 instant limit /18 not applied on /17", -1, 0, + AF_INET, "128.0.64.0", 0, 0); + + /* IPv6 multi-prefix tests */ + static_assert(RRL_V6_PREFIXES_CNT == 5, + "There are no more IPv6 limited prefixes (/128, /64, /56, /48, /32 will be tested)."); + + count_test("IPv6 instant limit /128, independent to IPv4", INST(V6, 128), 0, + AF_INET6, "8000::", 0, 0); + + count_test("IPv6 instant limit /128 not applied on /127", -1, 0, + AF_INET6, "8000::1", 0, 0); + + count_test("IPv6 instant limit /64", INST(V6, 64) - INST(V6, 128) - 1, 0, + AF_INET6, "8000:0:0:0:%02x%02x::", 0x01, 0xff); + + count_test("IPv6 instant limit /64 not applied on /63", -1, 0, + AF_INET6, "8000:0:0:1::", 0, 0); + + count_test("IPv6 instant limit /56", INST(V6, 56) - INST(V6, 64) - 1, rw_mode ? 0 : 0.01, + AF_INET6, "8000:0:0:00%02x:%02x00::", 0x02, 0xff); + + count_test("IPv6 instant limit /56 not applied on /55", -1, 0, + AF_INET6, "8000:0:0:0100::", 0, 0); + + count_test("IPv6 instant limit /48", INST(V6, 48) - INST(V6, 56) - 1, 0.01, + AF_INET6, "8000:0:0:%02x%02x::", 0x02, 0xff); + + count_test("IPv6 instant limit /48 not applied on /47", -1, 0, + AF_INET6, "8000:0:1::", 0, 0); + + count_test("IPv6 instant limit /32", INST(V6, 32) - INST(V6, 48) - 1, rw_mode ? 0.001 : 0, + AF_INET6, "8000:0:%02x%02x::", 0x02, 0xff); + + count_test("IPv6 instant limit /32 not applied on /31", -1, 0, + AF_INET6, "8000:1::", 0, 0); + + /* limit after 1 msec */ + fakeclock_tick++; + + count_test("IPv4 rate limit /32 after 1 msec", RATEM(V4, 32), 0, + AF_INET, "128.0.0.0", 0, 0); + + count_test("IPv6 rate limit /128 after 1 msec", RATEM(V6, 128), 0, + AF_INET6, "8000::", 0, 0); + + /* parallel tests */ + struct stage stages[] = { + /* first tick, last tick, hosts */ + {32, 32, { + /* queries per tick, family, address, min passed, max passed */ + {1024, AF_INET, "%d.%d.%d.1", RANGE_UNLIM ( 1024 )}, + {1024, AF_INET, "3.3.3.3", RANGE_INST ( V4, 32 )}, + { 512, AF_INET, "4.4.4.4", RANGE_INST ( V4, 32 )}, + {1024, AF_INET6, "%x%x:%x00::1", RANGE_UNLIM ( 1024 )}, + {1024, AF_INET6, "3333::3333", RANGE_INST ( V6, 128 )}, + { 512, AF_INET6, "4444::4444", RANGE_INST ( V6, 128 )} + }}, + {33, 255, { + {1024, AF_INET, "%d.%d.%d.1", RANGE_UNLIM ( 1024 )}, + {1024, AF_INET, "3.3.3.3", RANGE_RATEM ( V4, 32 )}, + { 512, AF_INET, "4.4.4.4", RANGE_RATEM ( V4, 32 )}, + {1024, AF_INET6, "%x%x:%x00::1", RANGE_UNLIM ( 1024 )}, + {1024, AF_INET6, "3333::3333", RANGE_RATEM ( V6, 128 )}, + { 512, AF_INET6, "4444::4444", RANGE_RATEM ( V6, 128 )}, + }}, + {256, 511, { + {1024, AF_INET, "3.3.3.3", RANGE_RATEM ( V4, 32 )}, + {1024, AF_INET6, "3333::3333", RANGE_RATEM ( V6, 128 )} + }}, + {512, 512, { + {1024, AF_INET, "%d.%d.%d.1", RANGE_UNLIM ( 1024 )}, + {1024, AF_INET, "3.3.3.3", RANGE_RATEM ( V4, 32 )}, + { 512, AF_INET, "4.4.4.4", RANGE_INST ( V4, 32 )}, + {1024, AF_INET6, "%x%x:%x00::1", RANGE_UNLIM ( 1024 )}, + {1024, AF_INET6, "3333::3333", RANGE_RATEM ( V6, 128 )}, + { 512, AF_INET6, "4444::4444", RANGE_INST ( V6, 128 )} + }}, + {0} + }; + pthread_t thr[RRL_THREADS]; + struct runnable_data rd[RRL_THREADS]; + _Atomic uint32_t queries_acquired = 0, queries_done = 0; + int primes[] = {3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61}; + assert(sizeof(primes)/sizeof(*primes) >= RRL_THREADS); + for (unsigned i = 0; i < RRL_THREADS; ++i) { - pthread_create(thr + i, NULL, &rrl_runnable, rd); + rd[i].rrl = rrl; + rd[i].queries_acquired = &queries_acquired; + rd[i].queries_done = &queries_done; + rd[i].prime = primes[i]; + rd[i].stages = stages; + pthread_create(thr + i, NULL, &rrl_runnable, rd + i); } for (unsigned i = 0; i < RRL_THREADS; ++i) { pthread_join(thr[i], NULL); } -} -#endif -int main(int argc, char *argv[]) -{ - plan_lazy(); + unsigned si = 0; + do { + struct host * const h = stages[si].hosts; + uint32_t ticks = stages[si].last_tick - stages[si].first_tick + 1; + for (size_t i = 0; h[i].queries_per_tick; i++) { + ok( h[i].min_passed * ticks <= h[i].passed && h[i].passed <= h[i].max_passed * ticks, + "rrl(%s): parallel stage %d, addr %-25s [%7d <=%12.4f <=%7d ]", impl_name, + si, h[i].addr_format, h[i].min_passed, (double)h[i].passed / ticks, h[i].max_passed); + } + } while (stages[++si].first_tick); - dnssec_crypto_init(); + rrl_destroy(rrl); +} - /* Prepare query. */ - knot_pkt_t *query = knot_pkt_new(NULL, 512, NULL); - if (query == NULL) { - return KNOT_ERROR; /* Fatal */ +void test_rrl_mode(bool test_avx2, bool rw_mode) +{ + if (!rw_mode) { + DIFF = 1; } - knot_dname_t *qname = knot_dname_from_str_alloc("beef."); - int ret = knot_pkt_put_question(query, qname, KNOT_CLASS_IN, KNOT_RRTYPE_A); - knot_dname_free(qname, NULL); - if (ret != KNOT_EOK) { - knot_pkt_free(query); - return KNOT_ERROR; /* Fatal */ - } + KRU = KRU_GENERIC; + impl_name = "KRU_GENERIC"; + test_rrl(rw_mode); - /* Prepare response */ - uint8_t rbuf[65535]; - size_t rlen = sizeof(rbuf); - memcpy(rbuf, query->wire, query->size); - knot_wire_flags_set_qr(rbuf); + if (test_avx2) { + KRU = KRU_AVX2; + impl_name = "KRU_AVX2"; + test_rrl(rw_mode); + } else { + diag("AVX2 NOT available"); + } +} - rrl_req_t rq; - rq.wire = rbuf; - rq.len = rlen; - rq.query = query; - rq.flags = 0; +int main(int argc, char *argv[]) +{ + plan_lazy(); - /* 1. create rrl table */ - const uint32_t rate = 10; - rrl_table_t *rrl = rrl_create(RRL_SIZE, rate); - ok(rrl != NULL, "rrl: create"); + dnssec_crypto_init(); - /* 2. N unlimited requests. */ - knot_dname_t *zone = knot_dname_from_str_alloc("rrl."); + assert(KRU_GENERIC.initialize != KRU_AVX2.initialize); + bool test_avx2 = (KRU.initialize == KRU_AVX2.initialize); - struct sockaddr_storage addr; - struct sockaddr_storage addr6; - sockaddr_set(&addr, AF_INET, "1.2.3.4", 0); - sockaddr_set(&addr6, AF_INET6, "1122:3344:5566:7788::aabb", 0); - ret = 0; - for (unsigned i = 0; i < rate * RRL_CAPACITY; ++i) { - if (rrl_query(rrl, &addr, &rq, zone, NULL) != KNOT_EOK || - rrl_query(rrl, &addr6, &rq, zone, NULL) != KNOT_EOK) { - ret = KNOT_ELIMIT; - break; - } - } - is_int(0, ret, "rrl: unlimited IPv4/v6 requests"); - - /* 3. Endian-independent hash input buffer. */ - uint8_t buf[RRL_CLSBLK_MAXLEN]; - // CLS_LARGE + remote + dname wire. - uint8_t expectedv4[] = "\x10\x01\x02\x03\x00\x00\x00\x00\x00\x04""beef"; - rrl_classify(buf, sizeof(buf), &addr, &rq, qname); - is_int(0, memcmp(buf, expectedv4, sizeof(expectedv4)), "rrl: IPv4 hash input buffer"); - uint8_t expectedv6[] = "\x10\x11\x22\x33\x44\x55\x66\x77\x00\x04""beef"; - rrl_classify(buf, sizeof(buf), &addr6, &rq, qname); - is_int(0, memcmp(buf, expectedv6, sizeof(expectedv6)), "rrl: IPv6 hash input buffer"); - -#ifdef ENABLE_TIMED_TESTS - /* 5. limited request */ - ret = rrl_query(rrl, &addr, &rq, zone, NULL); - is_int(KNOT_ELIMIT, ret, "rrl: throttled IPv4 request"); - - /* 6. limited IPv6 request */ - ret = rrl_query(rrl, &addr6, &rq, zone, NULL); - is_int(KNOT_ELIMIT, ret, "rrl: throttled IPv6 request"); - - /* 8. hopscotch test */ - struct runnable_data rd = { - 1, rrl, &addr, &rq, zone - }; - rrl_hopscotch(&rd); - ok(rd.passed, "rrl: hashtable is ~ consistent"); -#endif + test_rrl_mode(test_avx2, true); + test_rrl_mode(test_avx2, false); - knot_dname_free(zone, NULL); - knot_pkt_free(query); - rrl_destroy(rrl); dnssec_crypto_cleanup(); return 0; } diff --git a/tests/tap/files.c b/tests/tap/files.c index f979d07..ac85277 100644 --- a/tests/tap/files.c +++ b/tests/tap/files.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 CZ.NIC, z.s.p.o. +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -62,5 +62,5 @@ char *test_mkdtemp(void) bool test_rm_rf(const char *path) { - return remove_path(path); + return (remove_path(path, false) == KNOT_EOK); } -- cgit v1.2.3