keytable.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2005, 2007, 2009, 2010, 2013-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000, 2001  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: keytable.c,v 1.41 2010/06/25 23:46:51 tbox Exp $ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <isc/mem.h>
00025 #include <isc/print.h>
00026 #include <isc/rwlock.h>
00027 #include <isc/string.h>         /* Required for HP/UX (and others?) */
00028 #include <isc/util.h>
00029 
00030 #include <dns/keytable.h>
00031 #include <dns/fixedname.h>
00032 #include <dns/rbt.h>
00033 #include <dns/result.h>
00034 
00035 static void
00036 free_keynode(void *node, void *arg) {
00037         dns_keynode_t *keynode = node;
00038         isc_mem_t *mctx = arg;
00039 
00040         dns_keynode_detachall(mctx, &keynode);
00041 }
00042 
00043 isc_result_t
00044 dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
00045         dns_keytable_t *keytable;
00046         isc_result_t result;
00047 
00048         /*
00049          * Create a keytable.
00050          */
00051 
00052         REQUIRE(keytablep != NULL && *keytablep == NULL);
00053 
00054         keytable = isc_mem_get(mctx, sizeof(*keytable));
00055         if (keytable == NULL)
00056                 return (ISC_R_NOMEMORY);
00057 
00058         keytable->table = NULL;
00059         result = dns_rbt_create(mctx, free_keynode, mctx, &keytable->table);
00060         if (result != ISC_R_SUCCESS)
00061                 goto cleanup_keytable;
00062 
00063         result = isc_mutex_init(&keytable->lock);
00064         if (result != ISC_R_SUCCESS)
00065                 goto cleanup_rbt;
00066 
00067         result = isc_rwlock_init(&keytable->rwlock, 0, 0);
00068         if (result != ISC_R_SUCCESS)
00069                 goto cleanup_lock;
00070 
00071         keytable->mctx = NULL;
00072         isc_mem_attach(mctx, &keytable->mctx);
00073         keytable->active_nodes = 0;
00074         keytable->references = 1;
00075         keytable->magic = KEYTABLE_MAGIC;
00076         *keytablep = keytable;
00077 
00078         return (ISC_R_SUCCESS);
00079 
00080    cleanup_lock:
00081         DESTROYLOCK(&keytable->lock);
00082 
00083    cleanup_rbt:
00084         dns_rbt_destroy(&keytable->table);
00085 
00086    cleanup_keytable:
00087         isc_mem_putanddetach(&mctx, keytable, sizeof(*keytable));
00088 
00089         return (result);
00090 }
00091 
00092 void
00093 dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
00094 
00095         /*
00096          * Attach *targetp to source.
00097          */
00098 
00099         REQUIRE(VALID_KEYTABLE(source));
00100         REQUIRE(targetp != NULL && *targetp == NULL);
00101 
00102         RWLOCK(&source->rwlock, isc_rwlocktype_write);
00103 
00104         INSIST(source->references > 0);
00105         source->references++;
00106         INSIST(source->references != 0);
00107 
00108         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
00109 
00110         *targetp = source;
00111 }
00112 
00113 void
00114 dns_keytable_detach(dns_keytable_t **keytablep) {
00115         isc_boolean_t destroy = ISC_FALSE;
00116         dns_keytable_t *keytable;
00117 
00118         /*
00119          * Detach *keytablep from its keytable.
00120          */
00121 
00122         REQUIRE(keytablep != NULL && VALID_KEYTABLE(*keytablep));
00123 
00124         keytable = *keytablep;
00125 
00126         RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
00127 
00128         INSIST(keytable->references > 0);
00129         keytable->references--;
00130         LOCK(&keytable->lock);
00131         if (keytable->references == 0 && keytable->active_nodes == 0)
00132                 destroy = ISC_TRUE;
00133         UNLOCK(&keytable->lock);
00134 
00135         RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
00136 
00137         if (destroy) {
00138                 dns_rbt_destroy(&keytable->table);
00139                 isc_rwlock_destroy(&keytable->rwlock);
00140                 DESTROYLOCK(&keytable->lock);
00141                 keytable->magic = 0;
00142                 isc_mem_putanddetach(&keytable->mctx,
00143                                      keytable, sizeof(*keytable));
00144         }
00145 
00146         *keytablep = NULL;
00147 }
00148 
00149 static isc_result_t
00150 insert(dns_keytable_t *keytable, isc_boolean_t managed,
00151        dns_name_t *keyname, dst_key_t **keyp)
00152 {
00153         isc_result_t result;
00154         dns_keynode_t *knode = NULL;
00155         dns_rbtnode_t *node;
00156 
00157         REQUIRE(keyp == NULL || *keyp != NULL);
00158         REQUIRE(VALID_KEYTABLE(keytable));
00159 
00160         result = dns_keynode_create(keytable->mctx, &knode);
00161         if (result != ISC_R_SUCCESS)
00162                 return (result);
00163 
00164         knode->managed = managed;
00165 
00166         RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
00167 
00168         node = NULL;
00169         result = dns_rbt_addnode(keytable->table, keyname, &node);
00170 
00171         if (keyp != NULL) {
00172                 if (result == ISC_R_EXISTS) {
00173                         /* Key already in table? */
00174                         dns_keynode_t *k;
00175                         for (k = node->data; k != NULL; k = k->next) {
00176                                 if (k->key == NULL) {
00177                                         k->key = *keyp;
00178                                         *keyp = NULL; /* transfer ownership */
00179                                         break;
00180                                 }
00181                                 if (dst_key_compare(k->key, *keyp) == ISC_TRUE)
00182                                         break;
00183                         }
00184 
00185                         if (k == NULL)
00186                                 result = ISC_R_SUCCESS;
00187                         else if (*keyp != NULL)
00188                                 dst_key_free(keyp);
00189                 }
00190 
00191                 if (result == ISC_R_SUCCESS) {
00192                         knode->key = *keyp;
00193                         knode->next = node->data;
00194                         *keyp = NULL;
00195                 }
00196         }
00197 
00198         if (result == ISC_R_SUCCESS) {
00199                 node->data = knode;
00200                 knode = NULL;
00201         }
00202 
00203         /* Key was already there?  That's the same as a success */
00204         if (result == ISC_R_EXISTS)
00205                 result = ISC_R_SUCCESS;
00206 
00207         RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
00208 
00209         if (knode != NULL)
00210                 dns_keynode_detach(keytable->mctx, &knode);
00211 
00212         return (result);
00213 }
00214 
00215 isc_result_t
00216 dns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed,
00217                  dst_key_t **keyp)
00218 {
00219         REQUIRE(keyp != NULL && *keyp != NULL);
00220         return (insert(keytable, managed, dst_key_name(*keyp), keyp));
00221 }
00222 
00223 isc_result_t
00224 dns_keytable_marksecure(dns_keytable_t *keytable, dns_name_t *name) {
00225         return (insert(keytable, ISC_TRUE, name, NULL));
00226 }
00227 
00228 isc_result_t
00229 dns_keytable_delete(dns_keytable_t *keytable, dns_name_t *keyname) {
00230         isc_result_t result;
00231         dns_rbtnode_t *node = NULL;
00232 
00233         REQUIRE(VALID_KEYTABLE(keytable));
00234         REQUIRE(keyname != NULL);
00235 
00236         RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
00237         result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
00238                                   DNS_RBTFIND_NOOPTIONS, NULL, NULL);
00239         if (result == ISC_R_SUCCESS) {
00240                 if (node->data != NULL)
00241                         result = dns_rbt_deletenode(keytable->table,
00242                                                     node, ISC_FALSE);
00243                 else
00244                         result = ISC_R_NOTFOUND;
00245         } else if (result == DNS_R_PARTIALMATCH)
00246                 result = ISC_R_NOTFOUND;
00247         RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
00248 
00249         return (result);
00250 }
00251 
00252 isc_result_t
00253 dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey) {
00254         isc_result_t result;
00255         dns_name_t *keyname;
00256         dns_rbtnode_t *node = NULL;
00257         dns_keynode_t *knode = NULL, **kprev = NULL;
00258 
00259         REQUIRE(VALID_KEYTABLE(keytable));
00260         REQUIRE(dstkey != NULL);
00261 
00262         keyname = dst_key_name(dstkey);
00263 
00264         RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
00265         result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
00266                                   DNS_RBTFIND_NOOPTIONS, NULL, NULL);
00267 
00268         if (result == DNS_R_PARTIALMATCH)
00269                 result = ISC_R_NOTFOUND;
00270         if (result != ISC_R_SUCCESS)
00271                 goto finish;
00272 
00273         if (node->data == NULL) {
00274                 result = ISC_R_NOTFOUND;
00275                 goto finish;
00276         }
00277 
00278         knode = node->data;
00279         if (knode->next == NULL && knode->key != NULL &&
00280             dst_key_compare(knode->key, dstkey) == ISC_TRUE)
00281         {
00282                 result = dns_rbt_deletenode(keytable->table, node, ISC_FALSE);
00283                 goto finish;
00284         }
00285 
00286         kprev = (dns_keynode_t **) &node->data;
00287         while (knode != NULL) {
00288                 if (knode->key != NULL &&
00289                     dst_key_compare(knode->key, dstkey) == ISC_TRUE)
00290                         break;
00291                 kprev = &knode->next;
00292                 knode = knode->next;
00293         }
00294 
00295         if (knode != NULL) {
00296                 if (knode->key != NULL)
00297                         dst_key_free(&knode->key);
00298                 /*
00299                  * This is equivalent to:
00300                  * dns_keynode_attach(knode->next, &tmp);
00301                  * dns_keynode_detach(kprev);
00302                  * dns_keynode_attach(tmp, &kprev);
00303                  * dns_keynode_detach(&tmp);
00304                  */
00305                 *kprev = knode->next;
00306                 knode->next = NULL;
00307                 dns_keynode_detach(keytable->mctx, &knode);
00308         } else
00309                 result = DNS_R_PARTIALMATCH;
00310   finish:
00311         RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
00312         return (result);
00313 }
00314 
00315 isc_result_t
00316 dns_keytable_find(dns_keytable_t *keytable, dns_name_t *keyname,
00317                   dns_keynode_t **keynodep)
00318 {
00319         isc_result_t result;
00320         dns_rbtnode_t *node = NULL;
00321 
00322         REQUIRE(VALID_KEYTABLE(keytable));
00323         REQUIRE(keyname != NULL);
00324         REQUIRE(keynodep != NULL && *keynodep == NULL);
00325 
00326         RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
00327         result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
00328                                   DNS_RBTFIND_NOOPTIONS, NULL, NULL);
00329         if (result == ISC_R_SUCCESS) {
00330                 if (node->data != NULL) {
00331                         LOCK(&keytable->lock);
00332                         keytable->active_nodes++;
00333                         UNLOCK(&keytable->lock);
00334                         dns_keynode_attach(node->data, keynodep);
00335                 } else
00336                         result = ISC_R_NOTFOUND;
00337         } else if (result == DNS_R_PARTIALMATCH)
00338                 result = ISC_R_NOTFOUND;
00339         RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
00340 
00341         return (result);
00342 }
00343 
00344 isc_result_t
00345 dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
00346                          dns_keynode_t **nextnodep)
00347 {
00348         /*
00349          * Return the next key after 'keynode', regardless of
00350          * properties.
00351          */
00352 
00353         REQUIRE(VALID_KEYTABLE(keytable));
00354         REQUIRE(VALID_KEYNODE(keynode));
00355         REQUIRE(nextnodep != NULL && *nextnodep == NULL);
00356 
00357         if (keynode->next == NULL)
00358                 return (ISC_R_NOTFOUND);
00359 
00360         dns_keynode_attach(keynode->next, nextnodep);
00361         LOCK(&keytable->lock);
00362         keytable->active_nodes++;
00363         UNLOCK(&keytable->lock);
00364 
00365         return (ISC_R_SUCCESS);
00366 }
00367 
00368 isc_result_t
00369 dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
00370                          dns_secalg_t algorithm, dns_keytag_t tag,
00371                          dns_keynode_t **keynodep)
00372 {
00373         isc_result_t result;
00374         dns_keynode_t *knode;
00375         void *data;
00376 
00377         /*
00378          * Search for a key named 'name', matching 'algorithm' and 'tag' in
00379          * 'keytable'.
00380          */
00381 
00382         REQUIRE(VALID_KEYTABLE(keytable));
00383         REQUIRE(dns_name_isabsolute(name));
00384         REQUIRE(keynodep != NULL && *keynodep == NULL);
00385 
00386         RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
00387 
00388         /*
00389          * Note we don't want the DNS_R_PARTIALMATCH from dns_rbt_findname()
00390          * as that indicates that 'name' was not found.
00391          *
00392          * DNS_R_PARTIALMATCH indicates that the name was found but we
00393          * didn't get a match on algorithm and key id arguments.
00394          */
00395         knode = NULL;
00396         data = NULL;
00397         result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);
00398 
00399         if (result == ISC_R_SUCCESS) {
00400                 INSIST(data != NULL);
00401                 for (knode = data; knode != NULL; knode = knode->next) {
00402                         if (knode->key == NULL) {
00403                                 knode = NULL;
00404                                 break;
00405                         }
00406                         if (algorithm == dst_key_alg(knode->key)
00407                             && tag == dst_key_id(knode->key))
00408                                 break;
00409                 }
00410                 if (knode != NULL) {
00411                         LOCK(&keytable->lock);
00412                         keytable->active_nodes++;
00413                         UNLOCK(&keytable->lock);
00414                         dns_keynode_attach(knode, keynodep);
00415                 } else
00416                         result = DNS_R_PARTIALMATCH;
00417         } else if (result == DNS_R_PARTIALMATCH)
00418                 result = ISC_R_NOTFOUND;
00419 
00420         RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
00421 
00422         return (result);
00423 }
00424 
00425 isc_result_t
00426 dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
00427                              dns_keynode_t **nextnodep)
00428 {
00429         isc_result_t result;
00430         dns_keynode_t *knode;
00431 
00432         /*
00433          * Search for the next key with the same properties as 'keynode' in
00434          * 'keytable'.
00435          */
00436 
00437         REQUIRE(VALID_KEYTABLE(keytable));
00438         REQUIRE(VALID_KEYNODE(keynode));
00439         REQUIRE(nextnodep != NULL && *nextnodep == NULL);
00440 
00441         for (knode = keynode->next; knode != NULL; knode = knode->next) {
00442                 if (knode->key == NULL) {
00443                         knode = NULL;
00444                         break;
00445                 }
00446                 if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) &&
00447                     dst_key_id(keynode->key) == dst_key_id(knode->key))
00448                         break;
00449         }
00450         if (knode != NULL) {
00451                 LOCK(&keytable->lock);
00452                 keytable->active_nodes++;
00453                 UNLOCK(&keytable->lock);
00454                 result = ISC_R_SUCCESS;
00455                 dns_keynode_attach(knode, nextnodep);
00456         } else
00457                 result = ISC_R_NOTFOUND;
00458 
00459         return (result);
00460 }
00461 
00462 isc_result_t
00463 dns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name,
00464                               dns_name_t *foundname)
00465 {
00466         isc_result_t result;
00467         void *data;
00468 
00469         /*
00470          * Search for the deepest match in 'keytable'.
00471          */
00472 
00473         REQUIRE(VALID_KEYTABLE(keytable));
00474         REQUIRE(dns_name_isabsolute(name));
00475         REQUIRE(foundname != NULL);
00476 
00477         RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
00478 
00479         data = NULL;
00480         result = dns_rbt_findname(keytable->table, name, 0, foundname, &data);
00481 
00482         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
00483                 result = ISC_R_SUCCESS;
00484 
00485         RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
00486 
00487         return (result);
00488 }
00489 
00490 void
00491 dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source,
00492                            dns_keynode_t **target)
00493 {
00494         /*
00495          * Give back a keynode found via dns_keytable_findkeynode().
00496          */
00497 
00498         REQUIRE(VALID_KEYTABLE(keytable));
00499         REQUIRE(VALID_KEYNODE(source));
00500         REQUIRE(target != NULL && *target == NULL);
00501 
00502         LOCK(&keytable->lock);
00503         keytable->active_nodes++;
00504         UNLOCK(&keytable->lock);
00505 
00506         dns_keynode_attach(source, target);
00507 }
00508 
00509 void
00510 dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
00511 {
00512         /*
00513          * Give back a keynode found via dns_keytable_findkeynode().
00514          */
00515 
00516         REQUIRE(VALID_KEYTABLE(keytable));
00517         REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
00518 
00519         LOCK(&keytable->lock);
00520         INSIST(keytable->active_nodes > 0);
00521         keytable->active_nodes--;
00522         UNLOCK(&keytable->lock);
00523 
00524         dns_keynode_detach(keytable->mctx, keynodep);
00525 }
00526 
00527 isc_result_t
00528 dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
00529                             dns_name_t *foundname, isc_boolean_t *wantdnssecp)
00530 {
00531         isc_result_t result;
00532         dns_rbtnode_t *node = NULL;
00533 
00534         /*
00535          * Is 'name' at or beneath a trusted key?
00536          */
00537 
00538         REQUIRE(VALID_KEYTABLE(keytable));
00539         REQUIRE(dns_name_isabsolute(name));
00540         REQUIRE(wantdnssecp != NULL);
00541 
00542         RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
00543 
00544         result = dns_rbt_findnode(keytable->table, name, foundname, &node,
00545                                   NULL, DNS_RBTFIND_NOOPTIONS, NULL, NULL);
00546         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
00547                 INSIST(node->data != NULL);
00548                 *wantdnssecp = ISC_TRUE;
00549                 result = ISC_R_SUCCESS;
00550         } else if (result == ISC_R_NOTFOUND) {
00551                 *wantdnssecp = ISC_FALSE;
00552                 result = ISC_R_SUCCESS;
00553         }
00554 
00555         RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
00556 
00557         return (result);
00558 }
00559 
00560 static isc_result_t
00561 putstr(isc_buffer_t **b, const char *str) {
00562         isc_result_t result;
00563 
00564         result = isc_buffer_reserve(b, strlen(str));
00565         if (result != ISC_R_SUCCESS)
00566                 return (result);
00567 
00568         isc_buffer_putstr(*b, str);
00569         return (ISC_R_SUCCESS);
00570 }
00571 
00572 isc_result_t
00573 dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) {
00574         isc_result_t result;
00575         isc_buffer_t *text = NULL;
00576 
00577         REQUIRE(VALID_KEYTABLE(keytable));
00578         REQUIRE(fp != NULL);
00579 
00580         result = isc_buffer_allocate(keytable->mctx, &text, 4096);
00581         if (result != ISC_R_SUCCESS)
00582                 return (result);
00583 
00584         result = dns_keytable_totext(keytable, &text);
00585 
00586         if (isc_buffer_usedlength(text) != 0) {
00587                 (void) putstr(&text, "\n");
00588         } else if (result == ISC_R_SUCCESS)
00589                 (void) putstr(&text, "none");
00590         else {
00591                 (void) putstr(&text, "could not dump key table: ");
00592                 (void) putstr(&text, isc_result_totext(result));
00593         }
00594 
00595         fprintf(fp, "%.*s", (int) isc_buffer_usedlength(text),
00596                 (char *) isc_buffer_base(text));
00597 
00598         isc_buffer_free(&text);
00599         return (result);
00600 }
00601 
00602 isc_result_t
00603 dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
00604         isc_result_t result;
00605         dns_keynode_t *knode;
00606         dns_rbtnode_t *node;
00607         dns_rbtnodechain_t chain;
00608 
00609         REQUIRE(VALID_KEYTABLE(keytable));
00610         REQUIRE(text != NULL && *text != NULL);
00611 
00612         RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
00613         dns_rbtnodechain_init(&chain, keytable->mctx);
00614         result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
00615         if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00616                 if (result == ISC_R_NOTFOUND)
00617                         result = ISC_R_SUCCESS;
00618                 goto cleanup;
00619         }
00620         for (;;) {
00621                 char pbuf[DST_KEY_FORMATSIZE];
00622 
00623                 dns_rbtnodechain_current(&chain, NULL, NULL, &node);
00624                 for (knode = node->data; knode != NULL; knode = knode->next) {
00625                         char obuf[DNS_NAME_FORMATSIZE + 200];
00626                         if (knode->key == NULL)
00627                                 continue;
00628                         dst_key_format(knode->key, pbuf, sizeof(pbuf));
00629                         snprintf(obuf, sizeof(obuf), "%s ; %s\n", pbuf,
00630                                 knode->managed ? "managed" : "trusted");
00631                         result = putstr(text, obuf);
00632                         if (result != ISC_R_SUCCESS)
00633                                 break;
00634                 }
00635                 result = dns_rbtnodechain_next(&chain, NULL, NULL);
00636                 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00637                         if (result == ISC_R_NOMORE)
00638                                 result = ISC_R_SUCCESS;
00639                         break;
00640                 }
00641         }
00642 
00643    cleanup:
00644         dns_rbtnodechain_invalidate(&chain);
00645         RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
00646         return (result);
00647 }
00648 
00649 dst_key_t *
00650 dns_keynode_key(dns_keynode_t *keynode) {
00651 
00652         /*
00653          * Get the DST key associated with keynode.
00654          */
00655 
00656         REQUIRE(VALID_KEYNODE(keynode));
00657 
00658         return (keynode->key);
00659 }
00660 
00661 isc_boolean_t
00662 dns_keynode_managed(dns_keynode_t *keynode) {
00663         /*
00664          * Is this a managed key?
00665          */
00666         REQUIRE(VALID_KEYNODE(keynode));
00667 
00668         return (keynode->managed);
00669 }
00670 
00671 isc_result_t
00672 dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
00673         isc_result_t result;
00674         dns_keynode_t *knode = NULL;
00675 
00676         REQUIRE(target != NULL && *target == NULL);
00677 
00678         knode = isc_mem_get(mctx, sizeof(dns_keynode_t));
00679         if (knode == NULL)
00680                 return (ISC_R_NOMEMORY);
00681 
00682         knode->magic = KEYNODE_MAGIC;
00683         knode->managed = ISC_FALSE;
00684         knode->key = NULL;
00685         knode->next = NULL;
00686 
00687         result = isc_refcount_init(&knode->refcount, 1);
00688         if (result != ISC_R_SUCCESS)
00689                 return (result);
00690 
00691         *target = knode;
00692         return (ISC_R_SUCCESS);
00693 }
00694 
00695 void
00696 dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
00697         REQUIRE(VALID_KEYNODE(source));
00698         isc_refcount_increment(&source->refcount, NULL);
00699         *target = source;
00700 }
00701 
00702 void
00703 dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) {
00704         unsigned int refs;
00705         dns_keynode_t *node = *keynode;
00706         REQUIRE(VALID_KEYNODE(node));
00707         isc_refcount_decrement(&node->refcount, &refs);
00708         if (refs == 0) {
00709                 if (node->key != NULL)
00710                         dst_key_free(&node->key);
00711                 isc_refcount_destroy(&node->refcount);
00712                 isc_mem_put(mctx, node, sizeof(dns_keynode_t));
00713         }
00714         *keynode = NULL;
00715 }
00716 
00717 void
00718 dns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **keynode) {
00719         dns_keynode_t *next = NULL, *node = *keynode;
00720         REQUIRE(VALID_KEYNODE(node));
00721         while (node != NULL) {
00722                 next = node->next;
00723                 dns_keynode_detach(mctx, &node);
00724                 node = next;
00725         }
00726         *keynode = NULL;
00727 }

Generated on Tue Apr 28 17:40:57 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha