"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/dbtable.c" (7 Sep 2020, 6381 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dbtable.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 #include <config.h>
   13 
   14 #include <stdbool.h>
   15 
   16 #include <isc/mem.h>
   17 #include <isc/rwlock.h>
   18 #include <isc/util.h>
   19 
   20 #include <dns/dbtable.h>
   21 #include <dns/db.h>
   22 #include <dns/rbt.h>
   23 #include <dns/result.h>
   24 
   25 struct dns_dbtable {
   26     /* Unlocked. */
   27     unsigned int        magic;
   28     isc_mem_t *     mctx;
   29     dns_rdataclass_t    rdclass;
   30     isc_mutex_t     lock;
   31     isc_rwlock_t        tree_lock;
   32     /* Locked by lock. */
   33     unsigned int        references;
   34     /* Locked by tree_lock. */
   35     dns_rbt_t *     rbt;
   36     dns_db_t *      default_db;
   37 };
   38 
   39 #define DBTABLE_MAGIC       ISC_MAGIC('D', 'B', '-', '-')
   40 #define VALID_DBTABLE(dbtable)  ISC_MAGIC_VALID(dbtable, DBTABLE_MAGIC)
   41 
   42 static void
   43 dbdetach(void *data, void *arg) {
   44     dns_db_t *db = data;
   45 
   46     UNUSED(arg);
   47 
   48     dns_db_detach(&db);
   49 }
   50 
   51 isc_result_t
   52 dns_dbtable_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
   53            dns_dbtable_t **dbtablep)
   54 {
   55     dns_dbtable_t *dbtable;
   56     isc_result_t result;
   57 
   58     REQUIRE(mctx != NULL);
   59     REQUIRE(dbtablep != NULL && *dbtablep == NULL);
   60 
   61     dbtable = (dns_dbtable_t *)isc_mem_get(mctx, sizeof(*dbtable));
   62     if (dbtable == NULL)
   63         return (ISC_R_NOMEMORY);
   64 
   65     dbtable->rbt = NULL;
   66     result = dns_rbt_create(mctx, dbdetach, NULL, &dbtable->rbt);
   67     if (result != ISC_R_SUCCESS)
   68         goto clean1;
   69 
   70     result = isc_mutex_init(&dbtable->lock);
   71     if (result != ISC_R_SUCCESS)
   72         goto clean2;
   73 
   74     result = isc_rwlock_init(&dbtable->tree_lock, 0, 0);
   75     if (result != ISC_R_SUCCESS)
   76         goto clean3;
   77 
   78     dbtable->default_db = NULL;
   79     dbtable->mctx = NULL;
   80     isc_mem_attach(mctx, &dbtable->mctx);
   81     dbtable->rdclass = rdclass;
   82     dbtable->magic = DBTABLE_MAGIC;
   83     dbtable->references = 1;
   84 
   85     *dbtablep = dbtable;
   86 
   87     return (ISC_R_SUCCESS);
   88 
   89  clean3:
   90     DESTROYLOCK(&dbtable->lock);
   91 
   92  clean2:
   93     dns_rbt_destroy(&dbtable->rbt);
   94 
   95  clean1:
   96     isc_mem_putanddetach(&mctx, dbtable, sizeof(*dbtable));
   97 
   98     return (result);
   99 }
  100 
  101 static inline void
  102 dbtable_free(dns_dbtable_t *dbtable) {
  103     /*
  104      * Caller must ensure that it is safe to call.
  105      */
  106 
  107     RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
  108 
  109     if (dbtable->default_db != NULL)
  110         dns_db_detach(&dbtable->default_db);
  111 
  112     dns_rbt_destroy(&dbtable->rbt);
  113 
  114     RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
  115 
  116     isc_rwlock_destroy(&dbtable->tree_lock);
  117 
  118     dbtable->magic = 0;
  119 
  120     isc_mem_putanddetach(&dbtable->mctx, dbtable, sizeof(*dbtable));
  121 }
  122 
  123 void
  124 dns_dbtable_attach(dns_dbtable_t *source, dns_dbtable_t **targetp) {
  125     REQUIRE(VALID_DBTABLE(source));
  126     REQUIRE(targetp != NULL && *targetp == NULL);
  127 
  128     LOCK(&source->lock);
  129 
  130     INSIST(source->references > 0);
  131     source->references++;
  132     INSIST(source->references != 0);
  133 
  134     UNLOCK(&source->lock);
  135 
  136     *targetp = source;
  137 }
  138 
  139 void
  140 dns_dbtable_detach(dns_dbtable_t **dbtablep) {
  141     dns_dbtable_t *dbtable;
  142     bool free_dbtable = false;
  143 
  144     REQUIRE(dbtablep != NULL);
  145     dbtable = *dbtablep;
  146     REQUIRE(VALID_DBTABLE(dbtable));
  147 
  148     LOCK(&dbtable->lock);
  149 
  150     INSIST(dbtable->references > 0);
  151     dbtable->references--;
  152     if (dbtable->references == 0)
  153         free_dbtable = true;
  154 
  155     UNLOCK(&dbtable->lock);
  156 
  157     if (free_dbtable)
  158         dbtable_free(dbtable);
  159 
  160     *dbtablep = NULL;
  161 }
  162 
  163 isc_result_t
  164 dns_dbtable_add(dns_dbtable_t *dbtable, dns_db_t *db) {
  165     isc_result_t result;
  166     dns_db_t *dbclone;
  167 
  168     REQUIRE(VALID_DBTABLE(dbtable));
  169     REQUIRE(dns_db_class(db) == dbtable->rdclass);
  170 
  171     dbclone = NULL;
  172     dns_db_attach(db, &dbclone);
  173 
  174     RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
  175     result = dns_rbt_addname(dbtable->rbt, dns_db_origin(dbclone), dbclone);
  176     RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
  177 
  178     return (result);
  179 }
  180 
  181 void
  182 dns_dbtable_remove(dns_dbtable_t *dbtable, dns_db_t *db) {
  183     dns_db_t *stored_data = NULL;
  184     isc_result_t result;
  185     dns_name_t *name;
  186 
  187     REQUIRE(VALID_DBTABLE(dbtable));
  188 
  189     name = dns_db_origin(db);
  190 
  191     /*
  192      * There is a requirement that the association of name with db
  193      * be verified.  With the current rbt.c this is expensive to do,
  194      * because effectively two find operations are being done, but
  195      * deletion is relatively infrequent.
  196      * XXXDCL ... this could be cheaper now with dns_rbt_deletenode.
  197      */
  198 
  199     RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
  200 
  201     result = dns_rbt_findname(dbtable->rbt, name, 0, NULL,
  202                   (void **) (void *)&stored_data);
  203 
  204     if (result == ISC_R_SUCCESS) {
  205         INSIST(stored_data == db);
  206 
  207         (void)dns_rbt_deletename(dbtable->rbt, name, false);
  208     }
  209 
  210     RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
  211 }
  212 
  213 void
  214 dns_dbtable_adddefault(dns_dbtable_t *dbtable, dns_db_t *db) {
  215     REQUIRE(VALID_DBTABLE(dbtable));
  216     REQUIRE(dbtable->default_db == NULL);
  217     REQUIRE(dns_name_compare(dns_db_origin(db), dns_rootname) == 0);
  218 
  219     RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
  220 
  221     dbtable->default_db = NULL;
  222     dns_db_attach(db, &dbtable->default_db);
  223 
  224     RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
  225 }
  226 
  227 void
  228 dns_dbtable_getdefault(dns_dbtable_t *dbtable, dns_db_t **dbp) {
  229     REQUIRE(VALID_DBTABLE(dbtable));
  230     REQUIRE(dbp != NULL && *dbp == NULL);
  231 
  232     RWLOCK(&dbtable->tree_lock, isc_rwlocktype_read);
  233 
  234     dns_db_attach(dbtable->default_db, dbp);
  235 
  236     RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_read);
  237 }
  238 
  239 void
  240 dns_dbtable_removedefault(dns_dbtable_t *dbtable) {
  241     REQUIRE(VALID_DBTABLE(dbtable));
  242 
  243     RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
  244 
  245     dns_db_detach(&dbtable->default_db);
  246 
  247     RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
  248 }
  249 
  250 isc_result_t
  251 dns_dbtable_find(dns_dbtable_t *dbtable, dns_name_t *name,
  252          unsigned int options, dns_db_t **dbp)
  253 {
  254     dns_db_t *stored_data = NULL;
  255     isc_result_t result;
  256     unsigned int rbtoptions = 0;
  257 
  258     REQUIRE(dbp != NULL && *dbp == NULL);
  259 
  260     if ((options & DNS_DBTABLEFIND_NOEXACT) != 0)
  261         rbtoptions |= DNS_RBTFIND_NOEXACT;
  262 
  263     RWLOCK(&dbtable->tree_lock, isc_rwlocktype_read);
  264 
  265     result = dns_rbt_findname(dbtable->rbt, name, rbtoptions, NULL,
  266                   (void **) (void *)&stored_data);
  267 
  268     if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
  269         dns_db_attach(stored_data, dbp);
  270     else if (dbtable->default_db != NULL) {
  271         dns_db_attach(dbtable->default_db, dbp);
  272         result = DNS_R_PARTIALMATCH;
  273     } else
  274         result = ISC_R_NOTFOUND;
  275 
  276     RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_read);
  277 
  278     return (result);
  279 }