diff options
Diffstat (limited to 'contrib/bind9/lib/dns/rbtdb.c')
-rw-r--r-- | contrib/bind9/lib/dns/rbtdb.c | 381 |
1 files changed, 207 insertions, 174 deletions
diff --git a/contrib/bind9/lib/dns/rbtdb.c b/contrib/bind9/lib/dns/rbtdb.c index 10525d921233c..1550221ab252c 100644 --- a/contrib/bind9/lib/dns/rbtdb.c +++ b/contrib/bind9/lib/dns/rbtdb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.310.8.5.4.1 2011-11-16 09:32:08 marka Exp $ */ +/* $Id$ */ /*! \file */ @@ -365,9 +365,12 @@ typedef enum { dns_db_secure } dns_db_secure_t; +typedef struct dns_rbtdb dns_rbtdb_t; + typedef struct rbtdb_version { /* Not locked */ rbtdb_serial_t serial; + dns_rbtdb_t * rbtdb; /* * Protected in the refcount routines. * XXXJT: should we change the lock policy based on the refcount @@ -392,7 +395,7 @@ typedef struct rbtdb_version { typedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t; -typedef struct { +struct dns_rbtdb { /* Unlocked. */ dns_db_t common; /* Locks the data in this struct */ @@ -452,7 +455,7 @@ typedef struct { /* Unlocked */ unsigned int quantum; -} dns_rbtdb_t; +}; #define RBTDB_ATTR_LOADED 0x01 #define RBTDB_ATTR_LOADING 0x02 @@ -1105,6 +1108,7 @@ newversion(dns_db_t *db, dns_dbversion_t **versionp) { version = allocate_version(rbtdb->common.mctx, rbtdb->next_serial, 1, ISC_TRUE); if (version != NULL) { + version->rbtdb = rbtdb; version->commit_ok = ISC_TRUE; version->secure = rbtdb->current_version->secure; version->havensec3 = rbtdb->current_version->havensec3; @@ -1146,6 +1150,7 @@ attachversion(dns_db_t *db, dns_dbversion_t *source, unsigned int refs; REQUIRE(VALID_RBTDB(rbtdb)); + INSIST(rbtversion != NULL && rbtversion->rbtdb == rbtdb); isc_refcount_increment(&rbtversion->references, &refs); INSIST(refs > 1); @@ -1603,14 +1608,14 @@ cleanup_dead_nodes(dns_rbtdb_t *rbtdb, int bucketnum) { } /* - * Caller must be holding the node lock if its reference must be protected - * by the lock. + * Caller must be holding the node lock. */ static inline void new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) { unsigned int lockrefs, noderefs; isc_refcount_t *lockref; + INSIST(!ISC_LINK_LINKED(node, deadlink)); dns_rbtnode_refincrement0(node, &noderefs); if (noderefs == 1) { /* this is the first reference to the node */ lockref = &rbtdb->node_locks[node->locknum].references; @@ -1634,33 +1639,43 @@ static inline void reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, isc_rwlocktype_t treelocktype) { - isc_boolean_t need_relock = ISC_FALSE; + isc_rwlocktype_t locktype = isc_rwlocktype_read; + nodelock_t *nodelock = &rbtdb->node_locks[node->locknum].lock; + isc_boolean_t maybe_cleanup = ISC_FALSE; - NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock); - new_reference(rbtdb, node); + POST(locktype); + + NODE_STRONGLOCK(nodelock); + NODE_WEAKLOCK(nodelock, locktype); + + /* + * Check if we can possibly cleanup the dead node. If so, upgrade + * the node lock below to perform the cleanup. + */ + if (!ISC_LIST_EMPTY(rbtdb->deadnodes[node->locknum]) && + treelocktype == isc_rwlocktype_write) { + maybe_cleanup = ISC_TRUE; + } - NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock, - isc_rwlocktype_read); - if (ISC_LINK_LINKED(node, deadlink)) - need_relock = ISC_TRUE; - else if (!ISC_LIST_EMPTY(rbtdb->deadnodes[node->locknum]) && - treelocktype == isc_rwlocktype_write) - need_relock = ISC_TRUE; - NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock, - isc_rwlocktype_read); - if (need_relock) { - NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock, - isc_rwlocktype_write); + if (ISC_LINK_LINKED(node, deadlink) || maybe_cleanup) { + /* + * Upgrade the lock and test if we still need to unlink. + */ + NODE_WEAKUNLOCK(nodelock, locktype); + locktype = isc_rwlocktype_write; + POST(locktype); + NODE_WEAKLOCK(nodelock, locktype); if (ISC_LINK_LINKED(node, deadlink)) ISC_LIST_UNLINK(rbtdb->deadnodes[node->locknum], node, deadlink); - if (treelocktype == isc_rwlocktype_write) + if (maybe_cleanup) cleanup_dead_nodes(rbtdb, node->locknum); - NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock, - isc_rwlocktype_write); } - NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock); + new_reference(rbtdb, node); + + NODE_WEAKUNLOCK(nodelock, locktype); + NODE_STRONGUNLOCK(nodelock); } /* @@ -1684,7 +1699,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, rbtdb_nodelock_t *nodelock; unsigned int refs, nrefs; int bucket = node->locknum; - isc_boolean_t no_reference; + isc_boolean_t no_reference = ISC_TRUE; nodelock = &rbtdb->node_locks[bucket]; @@ -1704,6 +1719,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, NODE_WEAKUNLOCK(&nodelock->lock, isc_rwlocktype_read); NODE_WEAKLOCK(&nodelock->lock, isc_rwlocktype_write); } + dns_rbtnode_refdecrement(node, &nrefs); INSIST((int)nrefs >= 0); if (nrefs > 0) { @@ -1713,7 +1729,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, return (ISC_FALSE); } - if (node->dirty && dns_rbtnode_refcurrent(node) == 0) { + if (node->dirty) { if (IS_CACHE(rbtdb)) clean_cache_node(rbtdb, node); else { @@ -1731,19 +1747,6 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, } } - isc_refcount_decrement(&nodelock->references, &refs); - INSIST((int)refs >= 0); - - /* - * XXXDCL should this only be done for cache zones? - */ - if (node->data != NULL || node->down != NULL) { - /* Restore the lock? */ - if (nlock == isc_rwlocktype_read) - NODE_WEAKDOWNGRADE(&nodelock->lock); - return (ISC_TRUE); - } - /* * Attempt to switch to a write lock on the tree. If this fails, * we will add this node to a linked list of nodes in this locking @@ -1767,13 +1770,18 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, } else write_locked = ISC_TRUE; - no_reference = ISC_TRUE; - if (write_locked && dns_rbtnode_refcurrent(node) == 0) { + isc_refcount_decrement(&nodelock->references, &refs); + INSIST((int)refs >= 0); + + /* + * XXXDCL should this only be done for cache zones? + */ + if (node->data != NULL || node->down != NULL) + goto restore_locks; + + if (write_locked) { /* - * We can now delete the node if the reference counter is - * zero. This should be typically the case, but a different - * thread may still gain a (new) reference just before the - * current thread locks the tree (e.g., in findnode()). + * We can now delete the node. */ /* @@ -1825,6 +1833,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, ISC_LOG_INFO, "decrement_reference: failed to " "allocate pruning event"); + INSIST(node->data == NULL); INSIST(!ISC_LINK_LINKED(node, deadlink)); ISC_LIST_APPEND(rbtdb->deadnodes[bucket], node, deadlink); @@ -1847,12 +1856,13 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, delete_node(rbtdb, node); } - } else if (dns_rbtnode_refcurrent(node) == 0) { + } else { + INSIST(node->data == NULL); INSIST(!ISC_LINK_LINKED(node, deadlink)); ISC_LIST_APPEND(rbtdb->deadnodes[bucket], node, deadlink); - } else - no_reference = ISC_FALSE; + } + restore_locks: /* Restore the lock? */ if (nlock == isc_rwlocktype_read) NODE_WEAKDOWNGRADE(&nodelock->lock); @@ -1919,11 +1929,10 @@ prune_tree(isc_task_t *task, isc_event_t *event) { * from the list beforehand as we do in * reactivate_node(). */ - new_reference(rbtdb, parent); - if (ISC_LINK_LINKED(parent, deadlink)) { + if (ISC_LINK_LINKED(parent, deadlink)) ISC_LIST_UNLINK(rbtdb->deadnodes[locknum], parent, deadlink); - } + new_reference(rbtdb, parent); } else parent = NULL; @@ -1998,9 +2007,9 @@ iszonesecure(dns_db_t *db, rbtdb_version_t *version, dns_dbnode_t *origin) { result = dns_db_findrdataset(db, origin, version, dns_rdatatype_dnskey, 0, 0, &keyset, NULL); if (result == ISC_R_SUCCESS) { - dns_rdata_t keyrdata = DNS_RDATA_INIT; result = dns_rdataset_first(&keyset); while (result == ISC_R_SUCCESS) { + dns_rdata_t keyrdata = DNS_RDATA_INIT; dns_rdataset_current(&keyset, &keyrdata); if (dns_zonekey_iszonekey(&keyrdata)) { haszonekey = ISC_TRUE; @@ -2182,6 +2191,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { REQUIRE(VALID_RBTDB(rbtdb)); version = (rbtdb_version_t *)*versionp; + INSIST(version->rbtdb == rbtdb); cleanup_version = NULL; ISC_LIST_INIT(cleanup_list); @@ -2494,20 +2504,19 @@ add_empty_wildcards(dns_rbtdb_t *rbtdb, dns_name_t *name) { } static isc_result_t -findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, - dns_dbnode_t **nodep) +findnodeintree(dns_rbtdb_t *rbtdb, dns_rbt_t *tree, dns_name_t *name, + isc_boolean_t create, dns_dbnode_t **nodep) { - dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; dns_rbtnode_t *node = NULL; dns_name_t nodename; isc_result_t result; isc_rwlocktype_t locktype = isc_rwlocktype_read; - REQUIRE(VALID_RBTDB(rbtdb)); + INSIST(tree == rbtdb->tree || tree == rbtdb->nsec3); dns_name_init(&nodename, NULL); RWLOCK(&rbtdb->tree_lock, locktype); - result = dns_rbt_findnode(rbtdb->tree, name, NULL, &node, NULL, + result = dns_rbt_findnode(tree, name, NULL, &node, NULL, DNS_RBTFIND_EMPTYDATA, NULL, NULL); if (result != ISC_R_SUCCESS) { RWUNLOCK(&rbtdb->tree_lock, locktype); @@ -2523,10 +2532,10 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, locktype = isc_rwlocktype_write; RWLOCK(&rbtdb->tree_lock, locktype); node = NULL; - result = dns_rbt_addnode(rbtdb->tree, name, &node); + result = dns_rbt_addnode(tree, name, &node); if (result == ISC_R_SUCCESS) { #ifdef BIND9 - if (rbtdb->rpz_cidr != NULL) { + if (tree == rbtdb->tree && rbtdb->rpz_cidr != NULL) { dns_fixedname_t fnamef; dns_name_t *fname; @@ -2543,20 +2552,28 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, node->locknum = dns_name_hash(&nodename, ISC_TRUE) % rbtdb->node_lock_count; #endif - add_empty_wildcards(rbtdb, name); - - if (dns_name_iswildcard(name)) { - result = add_wildcard_magic(rbtdb, name); - if (result != ISC_R_SUCCESS) { - RWUNLOCK(&rbtdb->tree_lock, locktype); - return (result); + if (tree == rbtdb->tree) { + add_empty_wildcards(rbtdb, name); + + if (dns_name_iswildcard(name)) { + result = add_wildcard_magic(rbtdb, name); + if (result != ISC_R_SUCCESS) { + RWUNLOCK(&rbtdb->tree_lock, locktype); + return (result); + } } } + if (tree == rbtdb->nsec3) + node->nsec = DNS_RBT_NSEC_NSEC3; } else if (result != ISC_R_EXISTS) { RWUNLOCK(&rbtdb->tree_lock, locktype); return (result); } } + + if (tree == rbtdb->nsec3) + INSIST(node->nsec == DNS_RBT_NSEC_NSEC3); + reactivate_node(rbtdb, node, locktype); RWUNLOCK(&rbtdb->tree_lock, locktype); @@ -2566,60 +2583,25 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, } static isc_result_t -findnsec3node(dns_db_t *db, dns_name_t *name, isc_boolean_t create, - dns_dbnode_t **nodep) +findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, + dns_dbnode_t **nodep) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; - dns_rbtnode_t *node = NULL; - dns_name_t nodename; - isc_result_t result; - isc_rwlocktype_t locktype = isc_rwlocktype_read; REQUIRE(VALID_RBTDB(rbtdb)); - dns_name_init(&nodename, NULL); - RWLOCK(&rbtdb->tree_lock, locktype); - result = dns_rbt_findnode(rbtdb->nsec3, name, NULL, &node, NULL, - DNS_RBTFIND_EMPTYDATA, NULL, NULL); - if (result != ISC_R_SUCCESS) { - RWUNLOCK(&rbtdb->tree_lock, locktype); - if (!create) { - if (result == DNS_R_PARTIALMATCH) - result = ISC_R_NOTFOUND; - return (result); - } - /* - * It would be nice to try to upgrade the lock instead of - * unlocking then relocking. - */ - locktype = isc_rwlocktype_write; - RWLOCK(&rbtdb->tree_lock, locktype); - node = NULL; - result = dns_rbt_addnode(rbtdb->nsec3, name, &node); - if (result == ISC_R_SUCCESS) { - dns_rbt_namefromnode(node, &nodename); -#ifdef DNS_RBT_USEHASH - node->locknum = node->hashval % rbtdb->node_lock_count; -#else - node->locknum = dns_name_hash(&nodename, ISC_TRUE) % - rbtdb->node_lock_count; -#endif - node->nsec = DNS_RBT_NSEC_NSEC3; - } else if (result != ISC_R_EXISTS) { - RWUNLOCK(&rbtdb->tree_lock, locktype); - return (result); - } - } else { - INSIST(node->nsec == DNS_RBT_NSEC_NSEC3); - } - NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock); - new_reference(rbtdb, node); - NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock); - RWUNLOCK(&rbtdb->tree_lock, locktype); + return (findnodeintree(rbtdb, rbtdb->tree, name, create, nodep)); +} - *nodep = (dns_dbnode_t *)node; +static isc_result_t +findnsec3node(dns_db_t *db, dns_name_t *name, isc_boolean_t create, + dns_dbnode_t **nodep) +{ + dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; - return (ISC_R_SUCCESS); + REQUIRE(VALID_RBTDB(rbtdb)); + + return (findnodeintree(rbtdb, rbtdb->nsec3, name, create, nodep)); } static isc_result_t @@ -3649,6 +3631,8 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, search.rbtdb = (dns_rbtdb_t *)db; REQUIRE(VALID_RBTDB(search.rbtdb)); + INSIST(version == NULL || + ((rbtdb_version_t *)version)->rbtdb == (dns_rbtdb_t *)db); /* * We don't care about 'now'. @@ -4580,15 +4564,19 @@ get_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st) * Search the CDIR block tree of a response policy tree of trees for all of * the IP addresses in an A or AAAA rdataset. * Among the policies for all IPv4 and IPv6 addresses for a name, choose - * the longest prefix. Among those with the longest prefix, the first - * configured policy. Among answers for with the longest prefixes for - * two or more IP addresses in the A and AAAA rdatasets the lexically - * smallest address. + * the earliest configured policy, + * QNAME over IP over NSDNAME over NSIP, + * the longest prefix, + * the lexically smallest address. + * The caller must have already checked that any existing policy was not + * configured earlier than this policy zone and does not have a higher + * precedence type. */ static isc_result_t rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, - dns_rdataset_t *ardataset, dns_rpz_st_t *st) + dns_rdataset_t *ardataset, dns_rpz_st_t *st, + dns_name_t *query_qname) { dns_rbtdb_t *rbtdb; struct in_addr ina; @@ -4609,8 +4597,6 @@ rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, if (rbtdb->rpz_cidr == NULL) { RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); - dns_db_detach(&db); - dns_zone_detach(&zone); return (ISC_R_UNEXPECTED); } @@ -4645,17 +4631,19 @@ rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, continue; /* - * Choose the policy with the longest matching prefix. - * Between policies with the same prefix, choose the first - * configured. + * If we already have a rule, discard this new rule if + * is not better. + * The caller has checked that st->m.rpz->num > rpz->num + * or st->m.rpz->num == rpz->num and st->m.type >= rpz_type */ - if (st->m.policy != DNS_RPZ_POLICY_MISS) { - if (prefix < st->m.prefix) - continue; - if (prefix == st->m.prefix && - rpz->num > st->m.rpz->num) - continue; - } + if (st->m.policy != DNS_RPZ_POLICY_MISS && + st->m.rpz->num == rpz->num && + (st->m.type < rpz_type || + (st->m.type == rpz_type && + (st->m.prefix > prefix || + (st->m.prefix == prefix && + 0 > dns_name_rdatacompare(st->qname, qname)))))) + continue; /* * We have rpz_st an entry with a prefix at least as long as @@ -4669,8 +4657,8 @@ rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(qname, namebuf, sizeof(namebuf)); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_CACHE, DNS_RPZ_ERROR_LEVEL, + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, + DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, "rpz_findips findnode(%s): %s", namebuf, isc_result_totext(result)); continue; @@ -4694,7 +4682,8 @@ rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, } else { rpz_policy = dns_rpz_decode_cname(&zrdataset, selfname); - if (rpz_policy == DNS_RPZ_POLICY_RECORD) + if (rpz_policy == DNS_RPZ_POLICY_RECORD || + rpz_policy == DNS_RPZ_POLICY_WILDCNAME) result = DNS_R_CNAME; } ttl = zrdataset.ttl; @@ -4707,44 +4696,60 @@ rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, /* * Use an overriding action specified in the configuration file */ - if (rpz->policy != DNS_RPZ_POLICY_GIVEN && - rpz_policy != DNS_RPZ_POLICY_NO_OP) + if (rpz->policy != DNS_RPZ_POLICY_GIVEN) { + /* + * only log DNS_RPZ_POLICY_DISABLED hits + */ + if (rpz->policy == DNS_RPZ_POLICY_DISABLED) { + if (isc_log_wouldlog(dns_lctx, + DNS_RPZ_INFO_LEVEL)) { + char qname_buf[DNS_NAME_FORMATSIZE]; + char rpz_qname_buf[DNS_NAME_FORMATSIZE]; + dns_name_format(query_qname, qname_buf, + sizeof(qname_buf)); + dns_name_format(qname, rpz_qname_buf, + sizeof(rpz_qname_buf)); + + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_RPZ, + DNS_LOGMODULE_RBTDB, + DNS_RPZ_INFO_LEVEL, + "disabled rpz %s %s rewrite" + " %s via %s", + dns_rpz_type2str(rpz_type), + dns_rpz_policy2str(rpz_policy), + qname_buf, rpz_qname_buf); + } + continue; + } + rpz_policy = rpz->policy; + } - /* - * We know the new prefix is at least as long as the current. - * Prefer the new answer if the new prefix is longer. - * Prefer the zone configured first if the prefixes are equal. - * With two actions from the same zone, prefer the action - * on the "smallest" name. - */ - if (st->m.policy == DNS_RPZ_POLICY_MISS || - prefix > st->m.prefix || - rpz->num <= st->m.rpz->num || - 0 > dns_name_compare(qname, st->qname)) { - if (dns_rdataset_isassociated(st->m.rdataset)) - dns_rdataset_disassociate(st->m.rdataset); - if (st->m.node != NULL) - dns_db_detachnode(st->m.db, &st->m.node); - if (st->m.db != NULL) - dns_db_detach(&st->m.db); - if (st->m.zone != NULL) - dns_zone_detach(&st->m.zone); - st->m.rpz = rpz; - st->m.type = rpz_type; - st->m.prefix = prefix; - st->m.policy = rpz_policy; - st->m.ttl = ttl; - st->m.result = result; - dns_name_copy(qname, st->qname, NULL); - if (rpz_policy == DNS_RPZ_POLICY_RECORD && - result != DNS_R_NXRRSET) { - dns_rdataset_clone(&zrdataset,st->m.rdataset); - dns_db_attachnode(db, node, &st->m.node); - } - dns_db_attach(db, &st->m.db); - dns_zone_attach(zone, &st->m.zone); + if (dns_rdataset_isassociated(st->m.rdataset)) + dns_rdataset_disassociate(st->m.rdataset); + if (st->m.node != NULL) + dns_db_detachnode(st->m.db, &st->m.node); + if (st->m.db != NULL) + dns_db_detach(&st->m.db); + if (st->m.zone != NULL) + dns_zone_detach(&st->m.zone); + st->m.rpz = rpz; + st->m.type = rpz_type; + st->m.prefix = prefix; + st->m.policy = rpz_policy; + st->m.ttl = ttl; + st->m.result = result; + dns_name_copy(qname, st->qname, NULL); + if ((rpz_policy == DNS_RPZ_POLICY_RECORD || + rpz_policy == DNS_RPZ_POLICY_WILDCNAME) && + result != DNS_R_NXRRSET) { + dns_rdataset_clone(&zrdataset,st->m.rdataset); + dns_db_attachnode(db, node, &st->m.node); } + dns_db_attach(db, &st->m.db); + st->m.version = version; + dns_zone_attach(zone, &st->m.zone); if (dns_rdataset_isassociated(&zrdataset)) dns_rdataset_disassociate(&zrdataset); } @@ -5544,6 +5549,7 @@ zone_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, REQUIRE(VALID_RBTDB(rbtdb)); REQUIRE(type != dns_rdatatype_any); + INSIST(rbtversion == NULL || rbtversion->rbtdb == rbtdb); if (rbtversion == NULL) { currentversion(db, (dns_dbversion_t **) (void *)(&rbtversion)); @@ -5732,6 +5738,8 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, else { unsigned int refs; + INSIST(rbtversion->rbtdb == rbtdb); + isc_refcount_increment(&rbtversion->references, &refs); INSIST(refs > 1); @@ -6122,6 +6130,19 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, addedrdataset); return (ISC_R_SUCCESS); } + /* + * If we have will be replacing a NS RRset force its TTL + * to be no more than the current NS RRset's TTL. This + * ensures the delegations that are withdrawn are honoured. + */ + if (IS_CACHE(rbtdb) && header->rdh_ttl > now && + header->type == dns_rdatatype_ns && + !header_nx && !newheader_nx && + header->trust <= newheader->trust) { + if (newheader->rdh_ttl > header->rdh_ttl) { + newheader->rdh_ttl = header->rdh_ttl; + } + } if (IS_CACHE(rbtdb) && header->rdh_ttl > now && (header->type == dns_rdatatype_a || header->type == dns_rdatatype_aaaa) && @@ -6401,6 +6422,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_boolean_t cache_is_overmem = ISC_FALSE; REQUIRE(VALID_RBTDB(rbtdb)); + INSIST(rbtversion == NULL || rbtversion->rbtdb == rbtdb); if (rbtdb->common.methods == &zone_methods) REQUIRE(((rbtnode->nsec == DNS_RBT_NSEC_NSEC3 && @@ -6417,8 +6439,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, now = 0; result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx, - ®ion, - sizeof(rdatasetheader_t)); + ®ion, sizeof(rdatasetheader_t)); if (result != ISC_R_SUCCESS) return (result); @@ -6591,6 +6612,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, rbtdb_changed_t *changed; REQUIRE(VALID_RBTDB(rbtdb)); + REQUIRE(rbtversion != NULL && rbtversion->rbtdb == rbtdb); if (rbtdb->common.methods == &zone_methods) REQUIRE(((rbtnode->nsec == DNS_RBT_NSEC_NSEC3 && @@ -6771,6 +6793,7 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, rdatasetheader_t *newheader; REQUIRE(VALID_RBTDB(rbtdb)); + INSIST(rbtversion == NULL || rbtversion->rbtdb == rbtdb); if (type == dns_rdatatype_any) return (ISC_R_NOTIMPLEMENTED); @@ -7064,10 +7087,12 @@ static isc_result_t dump(dns_db_t *db, dns_dbversion_t *version, const char *filename, dns_masterformat_t masterformat) { dns_rbtdb_t *rbtdb; + rbtdb_version_t *rbtversion = version; rbtdb = (dns_rbtdb_t *)db; REQUIRE(VALID_RBTDB(rbtdb)); + INSIST(rbtversion == NULL || rbtversion->rbtdb == rbtdb); #ifdef BIND9 return (dns_master_dump2(rbtdb->common.mctx, db, version, @@ -7206,6 +7231,7 @@ getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash, rbtdb = (dns_rbtdb_t *)db; REQUIRE(VALID_RBTDB(rbtdb)); + INSIST(rbtversion == NULL || rbtversion->rbtdb == rbtdb); RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); @@ -7335,11 +7361,16 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) REQUIRE(VALID_RBTDB(rbtdb)); REQUIRE(rdataset != NULL); + REQUIRE(rdataset->methods == &rdataset_methods); REQUIRE(rbtdb->future_version == rbtversion); + REQUIRE(rbtversion != NULL); REQUIRE(rbtversion->writer); + REQUIRE(rbtversion->rbtdb == rbtdb); node = rdataset->private2; + INSIST(node != NULL); header = rdataset->private3; + INSIST(header != NULL); header--; RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); @@ -7750,6 +7781,7 @@ dns_rbtdb_create free_rbtdb(rbtdb, ISC_FALSE, NULL); return (ISC_R_NOMEMORY); } + rbtdb->current_version->rbtdb = rbtdb; rbtdb->current_version->secure = dns_db_insecure; rbtdb->current_version->havensec3 = ISC_FALSE; rbtdb->current_version->flags = 0; @@ -8480,7 +8512,7 @@ dbiterator_last(dns_dbiterator_t *iterator) { static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) { - isc_result_t result; + isc_result_t result, tresult; rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator; dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db; dns_name_t *iname, *origin; @@ -8523,13 +8555,14 @@ dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) { DNS_RBTFIND_EMPTYDATA, NULL, NULL); if (result == DNS_R_PARTIALMATCH) { dns_rbtnode_t *node = NULL; - result = dns_rbt_findnode(rbtdb->nsec3, name, NULL, + tresult = dns_rbt_findnode(rbtdb->nsec3, name, NULL, &node, &rbtdbiter->nsec3chain, DNS_RBTFIND_EMPTYDATA, NULL, NULL); - if (result == ISC_R_SUCCESS) { + if (tresult == ISC_R_SUCCESS) { rbtdbiter->node = node; rbtdbiter->current = &rbtdbiter->nsec3chain; + result = tresult; } } } |