ddns\-master: remote_id
notify: remote_id | remotes_id ...
acl: acl_id ...
+ provide\-ixfr: BOOL
semantic\-checks: BOOL | soft
zonefile\-sync: TIME
zonefile\-load: none | difference | difference\-no\-serial | whole
or disallow zone transfers, updates or incoming notifies.
.sp
\fIDefault:\fP not set
+.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.
ddns-master: remote_id
notify: remote_id | remotes_id ...
acl: acl_id ...
+ provide-ixfr: BOOL
semantic-checks: BOOL | soft
zonefile-sync: TIME
zonefile-load: none | difference | difference-no-serial | whole
*Default:* not set
+.. _zone_provide-ixfr:
+
+provide-ixfr
+------------
+
+If disabled, the server is forced to respond with AXFR to IXFR queries.
+If enabled, IXFR requests are responded normally.
+
+*Default:* ``on``
+
.. _zone_semantic-checks:
semantic-checks
-/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{ C_DDNS_MASTER, YP_TREF, YP_VREF = { C_RMT }, YP_FNONE, { check_ref } }, \
{ C_NOTIFY, YP_TREF, YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI, { check_ref } }, \
{ C_ACL, YP_TREF, YP_VREF = { C_ACL }, YP_FMULTI, { check_ref } }, \
+ { C_PROVIDE_IXFR, YP_TBOOL, YP_VBOOL = { true } }, \
{ C_SEM_CHECKS, YP_TOPT, YP_VOPT = { semantic_checks, SEMCHECKS_OFF }, FLAGS }, \
{ C_ZONEFILE_SYNC, YP_TINT, YP_VINT = { -1, INT32_MAX, 0, YP_STIME } }, \
{ C_ZONEFILE_LOAD, YP_TOPT, YP_VOPT = { zonefile_load, ZONEFILE_LOAD_WHOLE } }, \
-/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#define C_PIDFILE "\x07""pidfile"
#define C_POLICY "\x06""policy"
#define C_PROPAG_DELAY "\x11""propagation-delay"
+#define C_PROVIDE_IXFR "\x0C""provide-ixfr"
#define C_PROXY_ALLOWLIST "\x0F""proxy-allowlist"
#define C_QUIC "\x04""quic"
#define C_QUIC_IDLE_CLOSE "\x17""quic-idle-close-timeout"
-/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return KNOT_EAGAIN;
}
+ conf_val_t provide = conf_zone_get(conf(), C_PROVIDE_IXFR,
+ qdata->extra->zone->name);
+ if (!conf_bool(&provide)) {
+ return KNOT_ENOTSUP;
+ }
+
const knot_pktsection_t *authority = knot_pkt_section(qdata->query, KNOT_AUTHORITY);
const knot_rrset_t *their_soa = knot_pkt_rr(authority, 0);
*serial_from = knot_soa_serial(their_soa->rrs.rdata);
case KNOT_EUPTODATE: /* Our zone is same age/older, send SOA. */
IXFROUT_LOG(LOG_INFO, qdata, "zone is up-to-date, serial %u", soa_from);
return ixfr_answer_soa(pkt, qdata);
+ case KNOT_ENOTSUP:
+ IXFROUT_LOG(LOG_INFO, qdata, "cannot provide, fallback to AXFR");
+ qdata->type = KNOTD_QUERY_TYPE_AXFR; /* Solve as AXFR. */
+ return axfr_process_query(pkt, qdata);
case KNOT_ERANGE: /* No history -> AXFR. */
case KNOT_ENOENT:
IXFROUT_LOG(LOG_INFO, qdata, "incomplete history, serial %u, fallback to AXFR", soa_from);
--- /dev/null
+#!/usr/bin/env python3
+
+'''Test for AXFR-style IXFR controlled by provide-ixfr configuration'''
+
+from dnstest.test import Test
+
+t = Test()
+
+master = t.server("knot")
+slave = t.server("knot")
+zone = t.zone("example.com")
+
+t.link(zone, master, slave, ixfr=True)
+
+t.start()
+
+serial_init = master.zones_wait(zone)
+
+# Update the zone to create some history.
+master.update_zonefile(zone, random=True)
+master.reload()
+slave.zones_wait(zone, serial_init)
+
+# Disable IXFR and check AXFR-style IXFR.
+master.provide_ixfr = False
+master.gen_confile()
+master.reload()
+master.zones_wait(zone, serial_init)
+
+t.check_axfr_style_ixfr(master, zone[0].name, serial_init[zone[0].name])
+
+# Enable IXFR and compare with slave.
+master.provide_ixfr = True
+master.gen_confile()
+master.reload()
+master.zones_wait(zone, serial_init)
+
+t.xfr_diff(master, slave, zone, serial_init)
+
+t.stop()
self.zone_size_limit = None
self.serial_policy = None
self.auto_acl = None
+ self.provide_ixfr = None
self.inquirer = None
self._str(s, "serial-policy", self.serial_policy)
s.item_str("journal-content", z.journal_content)
-
+
if z.reverse_from:
s.item_str("reverse-generate", z.reverse_from.name)
elif z.ixfr:
s.item_str("zonefile-load", "difference")
+ self._bool(s, "provide-ixfr", self.provide_ixfr)
+
if z.catalog_role == ZoneCatalogRole.GENERATE:
s.item_str("catalog-role", "generate")
elif z.catalog_role == ZoneCatalogRole.MEMBER: