]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add a mechanism to record namespaces for synth-from-dnssec
authorMark Andrews <marka@isc.org>
Thu, 16 Jun 2022 06:31:10 +0000 (16:31 +1000)
committerMark Andrews <marka@isc.org>
Wed, 6 Jul 2022 21:47:45 +0000 (07:47 +1000)
When namespace is grafted on, the DNSSEC proofs for non existance
need to come from that namespace and not a higher namespace.  We
add 3 function dns_view_sfd_add, dns_view_sfd_del and dns_view_sfd_find
to add, remove and find the namespace that should be used when
checking NSEC records.

dns_view_sfd_add adds a name to a tree, creating the tree if needed.
If the name already existed in the tree the reference count is
increased otherwise it is initalised to 1.

dns_view_sfd_del removes a reference to a name in the tree, if the
count goes to 0 the node is removed.

dns_view_sfd_find returns the namespace to be used to entered name.
If there isn't an enclosing name in the tree, or the tree does not
yet exist, the root name is returned.

Access to the tree is controlled by a read/write lock.

(cherry picked from commit 3619cad1413d32715cf4fe67f955b10330b770d4)

lib/dns/include/dns/view.h
lib/dns/view.c

index 27d78820b8670a7c021218f867bc903d436be738..26aee1b4e9dee2f4297020bc1aaca769047ea006 100644 (file)
@@ -151,6 +151,8 @@ struct dns_view {
        dns_rbt_t            *denyanswernames;
        dns_rbt_t            *answernames_exclude;
        dns_rrl_t            *rrl;
+       dns_rbt_t            *sfd;
+       isc_rwlock_t          sfd_lock;
        bool                  provideixfr;
        bool                  requestnsid;
        bool                  sendcookie;
@@ -1362,4 +1364,40 @@ dns_view_staleanswerenabled(dns_view_t *view);
  *\li  'view' to be valid.
  */
 
+void
+dns_view_sfd_add(dns_view_t *view, const dns_name_t *name);
+/*%<
+ * Add 'name' to the synth-from-dnssec namespace tree for the
+ * view.  If the tree does not already exist create it.
+ *
+ * Requires:
+ *\li  'view' to be valid.
+ *\li  'name' to be valid.
+ */
+
+void
+dns_view_sfd_del(dns_view_t *view, const dns_name_t *name);
+/*%<
+ * Delete 'name' to the synth-from-dnssec namespace tree for
+ * the view when the count of previous adds and deletes becomes
+ * zero.
+ *
+ * Requires:
+ *\li  'view' to be valid.
+ *\li  'name' to be valid.
+ */
+
+void
+dns_view_sfd_find(dns_view_t *view, const dns_name_t *name,
+                 dns_name_t *foundname);
+/*%<
+ * Find the enclosing name to the synth-from-dnssec namespace tree for 'name'
+ * in the specified view.
+ *
+ * Requires:
+ *\li  'view' to be valid.
+ *\li  'name' to be valid.
+ *\li  'foundname' to be valid with a buffer sufficient to hold the name.
+ */
+
 ISC_LANG_ENDDECLS
index d6d29a0a3617b96a04b8df630e9bc5f06efa2411..f413cf252711ef55e051484bced9bfd9b500c463 100644 (file)
@@ -118,6 +118,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name,
 
        isc_mutex_init(&view->lock);
 
+       isc_rwlock_init(&view->sfd_lock, 0, 0);
+
        view->zonetable = NULL;
        result = dns_zt_create(mctx, rdclass, &view->zonetable);
        if (result != ISC_R_SUCCESS) {
@@ -210,6 +212,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name,
        view->denyanswernames = NULL;
        view->answernames_exclude = NULL;
        view->rrl = NULL;
+       view->sfd = NULL;
        view->provideixfr = true;
        view->maxcachettl = 7 * 24 * 3600;
        view->maxncachettl = 3 * 3600;
@@ -336,6 +339,7 @@ cleanup_zt:
        }
 
 cleanup_mutex:
+       isc_rwlock_destroy(&view->sfd_lock);
        isc_mutex_destroy(&view->lock);
 
        if (view->nta_file != NULL) {
@@ -506,6 +510,9 @@ destroy(dns_view_t *view) {
        if (view->answernames_exclude != NULL) {
                dns_rbt_destroy(&view->answernames_exclude);
        }
+       if (view->sfd != NULL) {
+               dns_rbt_destroy(&view->sfd);
+       }
        if (view->delonly != NULL) {
                dns_name_t *name;
                int i;
@@ -598,6 +605,7 @@ destroy(dns_view_t *view) {
                dns_badcache_destroy(&view->failcache);
        }
        isc_mutex_destroy(&view->new_zone_lock);
+       isc_rwlock_destroy(&view->sfd_lock);
        isc_mutex_destroy(&view->lock);
        isc_refcount_destroy(&view->references);
        isc_refcount_destroy(&view->weakrefs);
@@ -2581,3 +2589,77 @@ dns_view_staleanswerenabled(dns_view_t *view) {
 
        return (result);
 }
+
+static void
+free_sfd(void *data, void *arg) {
+       isc_mem_put(arg, data, sizeof(unsigned int));
+}
+
+void
+dns_view_sfd_add(dns_view_t *view, const dns_name_t *name) {
+       isc_result_t result;
+       dns_rbtnode_t *node = NULL;
+
+       REQUIRE(DNS_VIEW_VALID(view));
+
+       RWLOCK(&view->sfd_lock, isc_rwlocktype_write);
+       if (view->sfd == NULL) {
+               result = dns_rbt_create(view->mctx, free_sfd, view->mctx,
+                                       &view->sfd);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
+       }
+
+       result = dns_rbt_addnode(view->sfd, name, &node);
+       RUNTIME_CHECK(result == ISC_R_SUCCESS || result == ISC_R_EXISTS);
+       if (node->data != NULL) {
+               unsigned int *count = node->data;
+               (*count)++;
+       } else {
+               unsigned int *count = isc_mem_get(view->mctx,
+                                                 sizeof(unsigned int));
+               *count = 1;
+               node->data = count;
+       }
+       RWUNLOCK(&view->sfd_lock, isc_rwlocktype_write);
+}
+
+void
+dns_view_sfd_del(dns_view_t *view, const dns_name_t *name) {
+       isc_result_t result;
+       void *data = NULL;
+
+       REQUIRE(DNS_VIEW_VALID(view));
+
+       RWLOCK(&view->sfd_lock, isc_rwlocktype_write);
+       INSIST(view->sfd != NULL);
+       result = dns_rbt_findname(view->sfd, name, 0, NULL, &data);
+       if (result == ISC_R_SUCCESS) {
+               unsigned int *count = data;
+               INSIST(count != NULL);
+               if (--(*count) == 0U) {
+                       result = dns_rbt_deletename(view->sfd, name, false);
+                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+               }
+       }
+       RWUNLOCK(&view->sfd_lock, isc_rwlocktype_write);
+}
+
+void
+dns_view_sfd_find(dns_view_t *view, const dns_name_t *name,
+                 dns_name_t *foundname) {
+       REQUIRE(DNS_VIEW_VALID(view));
+
+       if (view->sfd != NULL) {
+               isc_result_t result;
+               void *data = NULL;
+
+               RWLOCK(&view->sfd_lock, isc_rwlocktype_read);
+               result = dns_rbt_findname(view->sfd, name, 0, foundname, &data);
+               RWUNLOCK(&view->sfd_lock, isc_rwlocktype_read);
+               if (result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) {
+                       dns_name_copy(dns_rootname, foundname);
+               }
+       } else {
+               dns_name_copy(dns_rootname, foundname);
+       }
+}