]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
load: implemented option loading diff from ZF ignoring serial
authorLibor Peltan <libor.peltan@nic.cz>
Fri, 22 Jun 2018 09:52:53 +0000 (11:52 +0200)
committerDaniel Salzman <daniel.salzman@nic.cz>
Sat, 28 Jul 2018 21:38:55 +0000 (23:38 +0200)
doc/man/knot.conf.5in
doc/reference.rst
src/knot/conf/schema.c
src/knot/conf/schema.h
src/knot/events/handlers/load.c
src/knot/updates/changesets.c
src/knot/updates/changesets.h

index a3cf08ac5e6d33ddea83f0a549e13165965620bd..3f0c3c521295508024c324b0b534b333a01a473a 100644 (file)
@@ -982,7 +982,7 @@ zone:
     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
@@ -1141,8 +1141,11 @@ Possible values:
 .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
index 5cf31b5adcd5d25da4ead2e0eeeaf6bf761efbe5..dd6da553caf9cb21dc3664d3ca78554e9fb6985c 100644 (file)
@@ -1113,7 +1113,7 @@ Definition of zones served by the server.
      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
@@ -1288,8 +1288,10 @@ Selects how the zonefile contents are applied during zone load.
 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
index d8391cd18cc82928219a9aa7096cbc2cacc4702f..34743571a3fc90ecb213320f6e04007fa43dfb6e 100644 (file)
@@ -103,6 +103,7 @@ static const knot_lookup_t journal_content[] = {
 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 }
 };
index 16ee36321324412db0b5afb603b9c2f12a33973c..533215cb48ed465ff29c9e04901e23f72db7d80b 100644 (file)
@@ -145,6 +145,7 @@ enum {
        ZONEFILE_LOAD_NONE  = 0,
        ZONEFILE_LOAD_DIFF  = 1,
        ZONEFILE_LOAD_WHOLE = 2,
+       ZONEFILE_LOAD_DIFSE = 3,
 };
 
 extern const knot_lookup_t acl_actions[];
index 7fdb79977c7c064001da502e03f7d5ba58af4d8c..b02b1cd5338b0d10137744ace07d5122dd5d1b74 100644 (file)
@@ -95,6 +95,17 @@ int event_load(conf_t *conf, zone_t *zone)
                        }
                        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);
@@ -201,6 +212,17 @@ int event_load(conf_t *conf, zone_t *zone)
        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) {
index 26a048d9a244315d4d8ebfd57bdfcd7623b02eaf..b19e69fdca6cba3bf8ad0a286330612959d4ab87 100644 (file)
@@ -531,6 +531,25 @@ int changeset_cancelout(changeset_t *ch)
        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);
index 47be664582a45f7cdcc33faccd7cbe23c65fdf8e..4aa345b332a75089bd2331862ac95b3bb1f3776c 100644 (file)
@@ -158,6 +158,16 @@ int changeset_preapply_fix(const zone_contents_t *zone, changeset_t *ch);
  */
 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.
  *