semantic\-checks: BOOL
disable\-any: BOOL
zonefile\-sync: TIME
- zonefile\-load: none | difference | whole
+ zonefile\-load: none | difference | difference\-no\-serial | whole
journal\-content: none | changes | all
max\-journal\-usage: SIZE
max\-journal\-depth: INT
.IP \(bu 2
\fBnone\fP – The zonefile is not used at all.
.IP \(bu 2
-\fBdifference\fP – If the zone contents are available during server start or reload,
-the difference is computed between them and the zonefile, checked and applied afterwards.
+\fBdifference\fP – If the zone contents is available during server start or reload,
+the difference is computed between them and the zonefile, checked, and applied afterwards.
+.IP \(bu 2
+\fBdifference\-no\-serial\fP – Same as \fBdifference\fP, but the SOA serial in the zonefile is
+ignored, the server takes care of incrementing the serial automatically.
.IP \(bu 2
\fBwhole\fP – Zone contents are loaded from zonefile.
.UNINDENT
semantic-checks: BOOL
disable-any: BOOL
zonefile-sync: TIME
- zonefile-load: none | difference | whole
+ zonefile-load: none | difference | difference-no-serial | whole
journal-content: none | changes | all
max-journal-usage: SIZE
max-journal-depth: INT
Possible values:
- ``none`` – The zonefile is not used at all.
-- ``difference`` – If the zone contents are available during server start or reload,
- the difference is computed between them and the zonefile, checked and applied afterwards.
+- ``difference`` – If the zone contents is available during server start or reload,
+ the difference is computed between them and the zonefile, checked, and applied afterwards.
+- ``difference-no-serial`` – Same as ``difference``, but the SOA serial in the zonefile is
+ ignored, the server takes care of incrementing the serial automatically.
- ``whole`` – Zone contents are loaded from zonefile.
When ``difference`` is configured and there are no zone contents yet (cold start of Knot
static const knot_lookup_t zonefile_load[] = {
{ ZONEFILE_LOAD_NONE, "none" },
{ ZONEFILE_LOAD_DIFF, "difference" },
+ { ZONEFILE_LOAD_DIFSE, "difference-no-serial" },
{ ZONEFILE_LOAD_WHOLE, "whole" },
{ 0, NULL }
};
ZONEFILE_LOAD_NONE = 0,
ZONEFILE_LOAD_DIFF = 1,
ZONEFILE_LOAD_WHOLE = 2,
+ ZONEFILE_LOAD_DIFSE = 3,
};
extern const knot_lookup_t acl_actions[];
}
goto cleanup;
}
+
+ // If configured and possible, fix the SOA serial of zonefile.
+ if (zf_conts != NULL && zf_from == ZONEFILE_LOAD_DIFSE) {
+ zone_contents_t *relevant = (zone->contents != NULL ? zone->contents : journal_conts);
+ if (relevant != NULL) {
+ uint32_t serial = zone_contents_serial(relevant);
+ conf_val_t policy = conf_zone_get(conf, C_SERIAL_POLICY, zone->name);
+ zone_contents_set_soa_serial(zf_conts, serial_next(serial, conf_opt(&policy)));
+ }
+ }
+
// If configured and appliable to zonefile, load journal changes.
zone->zonefile.serial = zone_contents_serial(zf_conts);
zone->zonefile.exists = (zf_conts != NULL);
zf_conts = NULL;
journal_conts = NULL;
+ // If the change is only automatically incremented SOA serial, make it no change.
+ if (zf_from == ZONEFILE_LOAD_DIFSE && (up.flags & UPDATE_INCREMENTAL) &&
+ changeset_differs_just_serial(&up.change)) {
+ uint32_t orig_ser = knot_soa_serial(&up.change.soa_from->rrs);
+ ret = changeset_remove_addition(&up.change, up.change.soa_to);
+ zone_contents_set_soa_serial(up.new_cont, orig_ser);
+ if (ret != KNOT_EOK) {
+ goto cleanup;
+ }
+ }
+
// Sign zone using DNSSEC if configured.
zone_sign_reschedule_t dnssec_refresh = { .allow_rollover = true, .allow_nsec3resalt = true, };
if (dnssec_enable) {
return ret;
}
+bool changeset_differs_just_serial(const changeset_t *ch)
+{
+ if (ch == NULL || ch->soa_from == NULL || ch->soa_to == NULL) {
+ return false;
+ }
+
+ if (!zone_contents_is_empty(ch->remove) || !zone_contents_is_empty(ch->add)) {
+ return false;
+ }
+
+ knot_rrset_t *soa_to_cpy = knot_rrset_copy(ch->soa_to, NULL);
+ knot_soa_serial_set(&soa_to_cpy->rrs, knot_soa_serial(&ch->soa_from->rrs));
+
+ bool res = knot_rrset_equal(ch->soa_from, soa_to_cpy, KNOT_RRSET_COMPARE_WHOLE);
+ knot_rrset_free(soa_to_cpy, NULL);
+
+ return res;
+}
+
int changeset_to_contents(changeset_t *ch, zone_contents_t **out)
{
assert(ch->soa_from == NULL);
*/
int changeset_cancelout(changeset_t *ch);
+/*!
+ * \brief Check the changes and SOA, ignoring possibly updated SOA serial.
+ *
+ * \param ch Changeset in question.
+ *
+ * \return false if the changeset changes other records than SOA, or some SOA field other than serial changed
+ * true otherwise
+ */
+bool changeset_differs_just_serial(const changeset_t *ch);
+
/*!
* \brief Loads zone contents from botstrap changeset.
*