void dns_dbtable_remove(dns_dbtable_t *dbtable, dns_db_t *db) { dns_db_t *stored_data = NULL; isc_result_t result; dns_name_t *name; REQUIRE(VALID_DBTABLE(dbtable)); name = dns_db_origin(db); /* * There is a requirement that the association of name with db * be verified. With the current rbt.c this is expensive to do, * because effectively two find operations are being done, but * deletion is relatively infrequent. * XXXDCL ... this could be cheaper now with dns_rbt_deletenode. */ RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write); result = dns_rbt_findname(dbtable->rbt, name, 0, NULL, (void **) (void *)&stored_data); if (result == ISC_R_SUCCESS) { INSIST(stored_data == db); (void)dns_rbt_deletename(dbtable->rbt, name, ISC_FALSE); } RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write); }
static int t1_search(char *name, dns_rbt_t *rbt, isc_mem_t *mctx, isc_result_t *dns_result) { int nprobs; dns_name_t *dns_searchname; dns_name_t *dns_foundname; dns_fixedname_t dns_fixedname; void *data; nprobs = 0; if (name && dns_result) { if (create_name(name, mctx, &dns_searchname) == 0) { dns_fixedname_init(&dns_fixedname); dns_foundname = dns_fixedname_name(&dns_fixedname); data = NULL; *dns_result = dns_rbt_findname(rbt, dns_searchname, 0, dns_foundname, &data); delete_name(dns_searchname, mctx); } else { ++nprobs; } } else { ++nprobs; } return(nprobs); }
isc_result_t dns_dbtable_find(dns_dbtable_t *dbtable, dns_name_t *name, unsigned int options, dns_db_t **dbp) { dns_db_t *stored_data = NULL; isc_result_t result; unsigned int rbtoptions = 0; REQUIRE(dbp != NULL && *dbp == NULL); if ((options & DNS_DBTABLEFIND_NOEXACT) != 0) rbtoptions |= DNS_RBTFIND_NOEXACT; RWLOCK(&dbtable->tree_lock, isc_rwlocktype_read); result = dns_rbt_findname(dbtable->rbt, name, rbtoptions, NULL, (void **) (void *)&stored_data); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) dns_db_attach(stored_data, dbp); else if (dbtable->default_db != NULL) { dns_db_attach(dbtable->default_db, dbp); result = DNS_R_PARTIALMATCH; } else result = ISC_R_NOTFOUND; RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_read); return (result); }
isc_result_t dns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name, dns_name_t *foundname) { isc_result_t result; void *data; /* * Search for the deepest match in 'keytable'. */ REQUIRE(VALID_KEYTABLE(keytable)); REQUIRE(dns_name_isabsolute(name)); REQUIRE(foundname != NULL); RWLOCK(&keytable->rwlock, isc_rwlocktype_read); data = NULL; result = dns_rbt_findname(keytable->table, name, 0, foundname, &data); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) result = ISC_R_SUCCESS; RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); return (result); }
isc_result_t dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name, isc_boolean_t *wantdnssecp) { isc_result_t result; void *data; /* * Is 'name' at or beneath a trusted key? */ REQUIRE(VALID_KEYTABLE(keytable)); REQUIRE(dns_name_isabsolute(name)); REQUIRE(wantdnssecp != NULL); RWLOCK(&keytable->rwlock, isc_rwlocktype_read); data = NULL; result = dns_rbt_findname(keytable->table, name, 0, NULL, &data); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { INSIST(data != NULL); *wantdnssecp = ISC_TRUE; result = ISC_R_SUCCESS; } else if (result == ISC_R_NOTFOUND) { *wantdnssecp = ISC_FALSE; result = ISC_R_SUCCESS; } RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); return (result); }
/* * Walk the tree and ensure that all the test nodes are present. */ static void check_test_data(dns_rbt_t *rbt) { dns_fixedname_t fixed; isc_result_t result; dns_name_t *foundname; size_t i; dns_fixedname_init(&fixed); foundname = dns_fixedname_name(&fixed); for (i = 0; i < domain_names_count; i++) { dns_fixedname_t fname; dns_name_t *name; size_t *n; build_name_from_str(domain_names[i], &fname); name = dns_fixedname_name(&fname); n = NULL; result = dns_rbt_findname(rbt, name, 0, foundname, (void *) &n); ATF_CHECK_EQ(result, ISC_R_SUCCESS); ATF_CHECK_EQ(*n, i + 1); } }
isc_result_t dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name, dns_name_t *algorithm, dns_tsig_keyring_t *ring) { dns_tsigkey_t *key; isc_stdtime_t now; isc_result_t result; REQUIRE(tsigkey != NULL); REQUIRE(*tsigkey == NULL); REQUIRE(name != NULL); REQUIRE(ring != NULL); RWLOCK(&ring->lock, isc_rwlocktype_write); cleanup_ring(ring); RWUNLOCK(&ring->lock, isc_rwlocktype_write); isc_stdtime_get(&now); RWLOCK(&ring->lock, isc_rwlocktype_read); key = NULL; result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key); if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) { RWUNLOCK(&ring->lock, isc_rwlocktype_read); return (ISC_R_NOTFOUND); } if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) { RWUNLOCK(&ring->lock, isc_rwlocktype_read); return (ISC_R_NOTFOUND); } if (key->inception != key->expire && isc_serial_lt(key->expire, now)) { /* * The key has expired. */ RWUNLOCK(&ring->lock, isc_rwlocktype_read); RWLOCK(&ring->lock, isc_rwlocktype_write); remove_fromring(key); RWUNLOCK(&ring->lock, isc_rwlocktype_write); return (ISC_R_NOTFOUND); } #if 0 /* * MPAXXX We really should look at the inception time. */ if (key->inception != key->expire && isc_serial_lt(key->inception, now)) { RWUNLOCK(&ring->lock, isc_rwlocktype_read); adjust_lru(key); return (ISC_R_NOTFOUND); } #endif isc_refcount_increment(&key->refs, NULL); RWUNLOCK(&ring->lock, isc_rwlocktype_read); adjust_lru(key); *tsigkey = key; return (ISC_R_SUCCESS); }
isc_result_t dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name, dns_secalg_t algorithm, dns_keytag_t tag, dns_keynode_t **keynodep) { isc_result_t result; dns_keynode_t *knode; void *data; /* * Search for a key named 'name', matching 'algorithm' and 'tag' in * 'keytable'. */ REQUIRE(VALID_KEYTABLE(keytable)); REQUIRE(dns_name_isabsolute(name)); REQUIRE(keynodep != NULL && *keynodep == NULL); RWLOCK(&keytable->rwlock, isc_rwlocktype_read); /* * Note we don't want the DNS_R_PARTIALMATCH from dns_rbt_findname() * as that indicates that 'name' was not found. * * DNS_R_PARTIALMATCH indicates that the name was found but we * didn't get a match on algorithm and key id arguments. */ knode = NULL; data = NULL; result = dns_rbt_findname(keytable->table, name, 0, NULL, &data); if (result == ISC_R_SUCCESS) { INSIST(data != NULL); for (knode = data; knode != NULL; knode = knode->next) { if (knode->key == NULL) { knode = NULL; break; } if (algorithm == dst_key_alg(knode->key) && tag == dst_key_id(knode->key)) break; } if (knode != NULL) { LOCK(&keytable->lock); keytable->active_nodes++; UNLOCK(&keytable->lock); dns_keynode_attach(knode, keynodep); } else result = DNS_R_PARTIALMATCH; } else if (result == DNS_R_PARTIALMATCH) result = ISC_R_NOTFOUND; RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); return (result); }
isc_result_t dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name, dns_forwarders_t **forwardersp) { isc_result_t result; REQUIRE(VALID_FWDTABLE(fwdtable)); RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read); result = dns_rbt_findname(fwdtable->table, name, 0, NULL, (void **)forwardersp); if (result == DNS_R_PARTIALMATCH) result = ISC_R_SUCCESS; RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read); return (result); }
isc_result_t dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name, dns_name_t *algorithm, dns_tsig_keyring_t *ring) { dns_tsigkey_t *key; isc_stdtime_t now; isc_result_t result; REQUIRE(tsigkey != NULL); REQUIRE(*tsigkey == NULL); REQUIRE(name != NULL); REQUIRE(ring != NULL); isc_stdtime_get(&now); RWLOCK(&ring->lock, isc_rwlocktype_read); key = NULL; result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key); if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) { RWUNLOCK(&ring->lock, isc_rwlocktype_read); return (ISC_R_NOTFOUND); } if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) { RWUNLOCK(&ring->lock, isc_rwlocktype_read); return (ISC_R_NOTFOUND); } if (key->inception != key->expire && key->expire < now) { /* * The key has expired. */ RWUNLOCK(&ring->lock, isc_rwlocktype_read); RWLOCK(&ring->lock, isc_rwlocktype_write); (void) dns_rbt_deletename(ring->keys, name, ISC_FALSE); RWUNLOCK(&ring->lock, isc_rwlocktype_write); return (ISC_R_NOTFOUND); } isc_refcount_increment(&key->refs, NULL); RWUNLOCK(&ring->lock, isc_rwlocktype_read); *tsigkey = key; return (ISC_R_SUCCESS); }
/* * Walk the tree and ensure that all the test nodes are present. */ static void check_test_data(dns_rbt_t *rbt) { char buffer[1024]; char *arg; dns_fixedname_t fname; dns_fixedname_t fixed; dns_name_t *name; isc_buffer_t b; data_holder_t *data; isc_result_t result; dns_name_t *foundname; rbt_testdata_t *testdatap = testdata; dns_fixedname_init(&fixed); foundname = dns_fixedname_name(&fixed); while (testdatap->name != NULL && testdatap->data.data != NULL) { memmove(buffer, testdatap->name, testdatap->name_len + 1); arg = buffer; isc_buffer_init(&b, arg, testdatap->name_len); isc_buffer_add(&b, testdatap->name_len); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { testdatap++; continue; } data = NULL; result = dns_rbt_findname(rbt, name, 0, foundname, (void *) &data); ATF_CHECK_STREQ(dns_result_totext(result), "success"); testdatap++; } }
isc_result_t dns_zt_find(dns_zt_t *zt, dns_name_t *name, unsigned int options, dns_name_t *foundname, dns_zone_t **zonep) { isc_result_t result; dns_zone_t *dummy = NULL; unsigned int rbtoptions = 0; REQUIRE(VALID_ZT(zt)); if ((options & DNS_ZTFIND_NOEXACT) != 0) rbtoptions |= DNS_RBTFIND_NOEXACT; RWLOCK(&zt->rwlock, isc_rwlocktype_read); result = dns_rbt_findname(zt->table, name, rbtoptions, foundname, (void **) (void*)&dummy); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) dns_zone_attach(dummy, zonep); RWUNLOCK(&zt->rwlock, isc_rwlocktype_read); return (result); }
int main(int argc, char **argv) { char *command, *arg, buffer[1024]; const char *whitespace; dns_name_t *name, *foundname; dns_fixedname_t fixedname; dns_rbt_t *rbt = NULL; int length, ch; isc_boolean_t show_final_mem = ISC_FALSE; isc_result_t result; void *data; progname = strrchr(*argv, '/'); if (progname != NULL) progname++; else progname = *argv; while ((ch = isc_commandline_parse(argc, argv, "m")) != -1) { switch (ch) { case 'm': show_final_mem = ISC_TRUE; break; } } argc -= isc_commandline_index; argv += isc_commandline_index; POST(argv); if (argc > 1) { printf("Usage: %s [-m]\n", progname); exit(1); } setbuf(stdout, NULL); /* * So isc_mem_stats() can report any allocation leaks. */ isc_mem_debugging = ISC_MEM_DEBUGRECORD; result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) { printf("isc_mem_create: %s: exiting\n", dns_result_totext(result)); exit(1); } result = dns_rbt_create(mctx, delete_name, NULL, &rbt); if (result != ISC_R_SUCCESS) { printf("dns_rbt_create: %s: exiting\n", dns_result_totext(result)); exit(1); } whitespace = " \t"; while (fgets(buffer, sizeof(buffer), stdin) != NULL) { length = strlen(buffer); if (buffer[length - 1] != '\n') { printf("line to long (%lu max), ignored\n", (unsigned long)sizeof(buffer) - 2); continue; } buffer[length - 1] = '\0'; command = buffer + strspn(buffer, whitespace); if (*command == '#') continue; arg = strpbrk(command, whitespace); if (arg != NULL) { *arg++ = '\0'; arg += strspn(arg, whitespace); } length = strlen(command); if (*command != '\0') { if (CMDCHECK("add")) { name = create_name(arg); if (name != NULL) { printf("adding name %s\n", arg); result = dns_rbt_addname(rbt, name, name); PRINTERR(result); } } else if (CMDCHECK("delete")) { name = create_name(arg); if (name != NULL) { printf("deleting name %s\n", arg); result = dns_rbt_deletename(rbt, name, ISC_FALSE); PRINTERR(result); delete_name(name, NULL); } } else if (CMDCHECK("nuke")) { name = create_name(arg); if (name != NULL) { printf("nuking name %s " "and its descendants\n", arg); result = dns_rbt_deletename(rbt, name, ISC_TRUE); PRINTERR(result); delete_name(name, NULL); } } else if (CMDCHECK("search")) { name = create_name(arg); if (name != NULL) { printf("searching for name %s ... ", arg); dns_fixedname_init(&fixedname); foundname = dns_fixedname_name(&fixedname); data = NULL; result = dns_rbt_findname(rbt, name, 0, foundname, &data); switch (result) { case ISC_R_SUCCESS: printf("found exact: "); print_name(data); putchar('\n'); break; case DNS_R_PARTIALMATCH: printf("found parent: "); print_name(data); printf("\n\t(foundname: "); print_name(foundname); printf(")\n"); break; case ISC_R_NOTFOUND: printf("NOT FOUND!\n"); break; case ISC_R_NOMEMORY: printf("OUT OF MEMORY!\n"); break; default: printf("UNEXPECTED RESULT\n"); } delete_name(name, NULL); } } else if (CMDCHECK("check")) { /* * Or "chain". I know, I know. Lame name. * I was having a hard time thinking of a * name (especially one that did not have * a conflicting first letter with another * command) that would differentiate this * from the search command. * * But it is just a test program, eh? */ name = create_name(arg); if (name != NULL) { detail(rbt, name); delete_name(name, NULL); } } else if (CMDCHECK("forward")) { iterate(rbt, ISC_TRUE); } else if (CMDCHECK("backward")) { iterate(rbt, ISC_FALSE); } else if (CMDCHECK("print")) { if (arg == NULL || *arg == '\0') dns_rbt_printall(rbt, NULL); else printf("usage: print\n"); } else if (CMDCHECK("quit")) { if (arg == NULL || *arg == '\0') break; else printf("usage: quit\n"); } else { printf("a(dd) NAME, d(elete) NAME, " "s(earch) NAME, p(rint), or q(uit)\n"); } } } dns_rbt_destroy(&rbt); if (show_final_mem) isc_mem_stats(mctx, stderr); return (0); }
isc_result_t cached_ldap_rdatalist_get(isc_mem_t *mctx, ldap_cache_t *cache, ldap_db_t *ldap_db, dns_name_t *name, dns_name_t *origin, ldapdb_rdatalist_t *rdatalist) { isc_result_t result; ldapdb_rdatalist_t rdlist; cache_node_t *node = NULL; int in_cache = 0; int is_locked = 0; REQUIRE(cache != NULL); if (cache->rbt == NULL) return ldapdb_rdatalist_get(mctx, ldap_db, name, origin, rdatalist); CONTROLED_LOCK(&cache->mutex); result = dns_rbt_findname(cache->rbt, name, 0, NULL, (void *)&node); if (result == ISC_R_SUCCESS) { isc_time_t now; CHECK(isc_time_now(&now)); /* Check if the record is still valid. */ if (isc_time_compare(&now, &node->valid_until) > 0) { CHECK(dns_rbt_deletename(cache->rbt, name, ISC_FALSE)); in_cache = 0; } else { rdlist = node->rdatalist; in_cache = 1; } } else if (result != ISC_R_NOTFOUND && result != DNS_R_PARTIALMATCH) { goto cleanup; } CONTROLED_UNLOCK(&cache->mutex); if (!in_cache) { INIT_LIST(rdlist); result = ldapdb_rdatalist_get(mctx, ldap_db, name, origin, &rdlist); /* TODO: Cache entries that are not found. */ if (result != ISC_R_SUCCESS) goto cleanup; CONTROLED_LOCK(&cache->mutex); /* Check again to make sure. */ node = NULL; result = dns_rbt_findname(cache->rbt, name, 0, NULL, (void *)&node); if (result == ISC_R_NOTFOUND || result == DNS_R_PARTIALMATCH) { node = NULL; CHECK(cache_node_create(cache, rdlist, &node)); CHECK(dns_rbt_addname(cache->rbt, name, (void *)node)); } CONTROLED_UNLOCK(&cache->mutex); } CHECK(ldap_rdatalist_copy(mctx, rdlist, rdatalist)); if (EMPTY(*rdatalist)) result = ISC_R_NOTFOUND; cleanup: CONTROLED_UNLOCK(&cache->mutex); return result; }