]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
catalog: check catalog zone version
authorLibor Peltan <libor.peltan@nic.cz>
Tue, 14 Apr 2020 16:46:28 +0000 (18:46 +0200)
committerDaniel Salzman <daniel.salzman@nic.cz>
Mon, 13 Jul 2020 18:07:09 +0000 (20:07 +0200)
doc/configuration.rst
src/knot/updates/zone-update.c
src/knot/zone/catalog.c
src/knot/zone/catalog.h
tests-extra/tests/zone/catalog/data/catalog1.zone

index 7fe5da5921c755be9125a44daf88afe243eb41c9..1eed334069b08856c6a213c3a48a872d45cc01e9 100644 (file)
@@ -600,7 +600,8 @@ and ACLs. Being a catalog zone is indicated by setting the option
 :ref:`zone_catalog-template`. The difference is that standard DNS
 queries to a catalog zone are answered with REFUSED as if such a zone
 wouldn't exist, unless querying from an address with transfers enabled
-by ACL. The name of the catalog zone is arbitrary.
+by ACL. The name of the catalog zone is arbitrary. It's however required to
+include version record ``version 0 IN TXT "2"``.
 It's possible to configure more catalog zones.
 
 .. WARNING::
index 03ac4ef42b251199ab7bdbd3a69b74a9fd6b56a9..558f3cc79dd3b996ff5d286499675fecdc3417d5 100644 (file)
@@ -717,19 +717,24 @@ static int update_catalog(conf_t *conf, zone_update_t *update)
 
        int ret = KNOT_EOK;
        if ((update->flags & UPDATE_INCREMENTAL)) {
-               ret = knot_cat_update_from_zone(update->zone->catalog_upd, update->change.remove, true, update->zone->catalog);
+               ret = knot_cat_update_from_zone(update->zone->catalog_upd, update->change.remove,
+                                               true, false, update->zone->catalog);
                if (ret == KNOT_EOK) {
-                       ret = knot_cat_update_from_zone(update->zone->catalog_upd, update->change.add, false, NULL);
+                       ret = knot_cat_update_from_zone(update->zone->catalog_upd,
+                                                       update->change.add, false, false, NULL);
                }
        } else {
                ret = knot_cat_update_del_all(update->zone->catalog_upd, update->zone->catalog, update->zone->name);
                if (ret == KNOT_EOK) {
-                       ret = knot_cat_update_from_zone(update->zone->catalog_upd, update->zone->contents, false, NULL);
+                       ret = knot_cat_update_from_zone(update->zone->catalog_upd,
+                                                       update->zone->contents, false, true, NULL);
                }
        }
 
        if (ret == KNOT_EOK) {
-               kill(getpid(), SIGUSR1);
+               if (kill(getpid(), SIGUSR1) != 0) {
+                       ret = knot_map_errno();
+               }
        }
 
        return ret;
@@ -874,9 +879,12 @@ int zone_update_commit(conf_t *conf, zone_update_t *update)
        zone_contents_t *old_contents;
        old_contents = zone_switch_contents(update->zone, update->new_cont);
 
-       ret = commit_catalog(conf, update);
-       if (ret != KNOT_EOK) {
-               log_zone_warning(update->zone->name, "catalog zone not fully populated (%s)", knot_strerror(ret));
+       ret = update_catalog(conf, update);
+       if (ret == KNOT_EZONEINVAL) {
+               log_zone_warning(update->zone->name, "invalid catalog zone version");
+       } else if (ret != KNOT_EOK) {
+               log_zone_warning(update->zone->name, "catalog zone not fully populated (%s)",
+                                knot_strerror(ret));
        }
 
        if (update->flags & (UPDATE_INCREMENTAL | UPDATE_HYBRID)) {
index 8b21a84a13bbb7dc18c43918b86e83088ce83563..41265d954196e9e53a0377eeffdcbc9ab7551f09 100644 (file)
 #include "knot/zone/contents.h"
 
 #define CATALOG_VERSION "1.0"
+#define CATALOG_ZONE_VERSION "2" // must be just one char long
 
 const MDB_val knot_catalog_iter_prefix = { 1, "" };
 
+static bool check_zone_version(const zone_contents_t *zone)
+{
+       size_t zone_size = knot_dname_size(zone->apex->owner);
+       knot_dname_t sub[zone_size + 8];
+       memcpy(sub, "\x07""version", 8);
+       memcpy(sub + 8, zone->apex->owner, zone_size);
+
+       const zone_node_t *ver_node = zone_contents_find_node(zone, sub);
+       knot_rdataset_t *ver_rr = node_rdataset(ver_node, KNOT_RRTYPE_TXT);
+       if (ver_rr == NULL) {
+               return false;
+       }
+
+       knot_rdata_t *rd = ver_rr->rdata;
+       for (int i = 0; i < ver_rr->count; i++) {
+               if (rd->len == 2 && rd->data[1] == CATALOG_ZONE_VERSION[0]) {
+                       return true;
+               }
+               rd = knot_rdataset_next(rd);
+       }
+       return false;
+}
+
 void knot_catalog_init(knot_catalog_t *cat, const char *path, size_t mapsize)
 {
        knot_lmdb_init(&cat->db, path, mapsize, 0, NULL);
@@ -325,8 +349,12 @@ static int cat_update_add_node(zone_node_t *node, void *data)
 }
 
 int knot_cat_update_from_zone(knot_cat_update_t *u, struct zone_contents *zone,
-                              bool remove, knot_catalog_t *check)
+                              bool remove, bool check_ver, knot_catalog_t *check)
 {
+       if (check_ver && !check_zone_version(zone)) {
+               return KNOT_EZONEINVAL;
+       }
+
        size_t zone_size = knot_dname_size(zone->apex->owner);
        knot_dname_t sub[zone_size + 6];
        memcpy(sub, "\x05""zones", 6);
index 54d2af63cbed3c8efcab58ccef6a033de943d7cd..2e2c8967f101617c8181ee89a28765d9d76d9aa0 100644 (file)
@@ -101,7 +101,7 @@ knot_cat_upd_val_t *knot_cat_update_get(knot_cat_update_t *u, const knot_dname_t
 struct zone_contents;
 
 int knot_cat_update_from_zone(knot_cat_update_t *u, struct zone_contents *zone,
-                              bool remove, knot_catalog_t *check);
+                              bool remove, bool check_ver, knot_catalog_t *check);
 
 int knot_cat_update_del_all(knot_cat_update_t *u, knot_catalog_t *cat, const knot_dname_t *zone);
 
index cc802edfe611315e77bbc713bc0a5ebccafe78cd..4883a05bbd266cbe9ab5c0f337c6db16c3833602 100644 (file)
@@ -4,5 +4,6 @@ $TTL 0
 @ SOA ns admin 1 25 25 80 600
   NS ns
 ns AAAA ::0
+version TXT "2"
 foo.bar.zones PTR cataloged1.
 not.zones.in PTR not-cataloged1.