From 9e8eadfa387619a2f3f3d82dc17f15651718972f Mon Sep 17 00:00:00 2001 From: "Internet Software Consortium, Inc" <@isc.org> Date: Wed, 3 Jun 2009 07:26:53 -0600 Subject: 9.6.1rc1 --- lib/dns/api | 2 +- lib/dns/cache.c | 11 +- lib/dns/dispatch.c | 5 +- lib/dns/include/dns/events.h | 5 +- lib/dns/rbtdb.c | 208 ++++++++++++++++++++++++++++++------- lib/dns/resolver.c | 88 ++++++++-------- lib/dns/sdb.c | 9 +- lib/dns/sdlz.c | 9 +- lib/dns/validator.c | 105 ++++++++++++++++--- lib/dns/zone.c | 4 +- lib/isc/alpha/include/isc/atomic.h | 40 ++++--- lib/isc/api | 2 +- lib/isc/hash.c | 10 +- lib/isc/unix/socket.c | 11 +- lib/lwres/api | 2 +- lib/lwres/getaddrinfo.c | 54 +++++----- 16 files changed, 406 insertions(+), 159 deletions(-) (limited to 'lib') diff --git a/lib/dns/api b/lib/dns/api index e5a8e69a..5ef8dc03 100644 --- a/lib/dns/api +++ b/lib/dns/api @@ -1,3 +1,3 @@ LIBINTERFACE = 51 -LIBREVISION = 0 +LIBREVISION = 1 LIBAGE = 1 diff --git a/lib/dns/cache.c b/lib/dns/cache.c index 4c19788d..aee824e5 100644 --- a/lib/dns/cache.c +++ b/lib/dns/cache.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: cache.c,v 1.80.50.2 2009/01/18 23:47:35 tbox Exp $ */ +/* $Id: cache.c,v 1.80.50.3 2009/05/06 23:34:30 jinmei Exp $ */ /*! \file */ @@ -174,6 +174,7 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, isc_result_t result; dns_cache_t *cache; int i; + isc_task_t *dbtask; REQUIRE(cachep != NULL); REQUIRE(*cachep == NULL); @@ -229,6 +230,14 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, result = cache_create_db(cache, &cache->db); if (result != ISC_R_SUCCESS) goto cleanup_dbargv; + if (taskmgr != NULL) { + dbtask = NULL; + result = isc_task_create(taskmgr, 1, &dbtask); + if (result != ISC_R_SUCCESS) + goto cleanup_db; + dns_db_settask(cache->db, dbtask); + isc_task_detach(&dbtask); + } cache->filename = NULL; diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 1356134d..9b4e9685 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.c,v 1.155.12.6 2009/01/31 00:38:25 marka Exp $ */ +/* $Id: dispatch.c,v 1.155.12.7 2009/04/28 21:39:45 jinmei Exp $ */ /*! \file */ @@ -808,7 +808,7 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest, dispsocket_t *dispsock; unsigned int nports; in_port_t *ports; - unsigned int bindoptions = 0; + unsigned int bindoptions; dispportentry_t *portentry = NULL; if (isc_sockaddr_pf(&disp->local) == AF_INET) { @@ -858,6 +858,7 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest, bucket = dns_hash(qid, dest, 0, port); if (socket_search(qid, dest, port, bucket) != NULL) continue; + bindoptions = 0; portentry = port_search(disp, port); if (portentry != NULL) bindoptions |= ISC_SOCKET_REUSEADDRESS; diff --git a/lib/dns/include/dns/events.h b/lib/dns/include/dns/events.h index 7692c1b6..bb61b9d4 100644 --- a/lib/dns/include/dns/events.h +++ b/lib/dns/include/dns/events.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: events.h,v 1.49 2007/06/19 23:47:16 tbox Exp $ */ +/* $Id: events.h,v 1.49.332.2 2009/05/07 23:47:12 tbox Exp $ */ #ifndef DNS_EVENTS_H #define DNS_EVENTS_H 1 @@ -68,6 +68,7 @@ #define DNS_EVENT_ACACHECONTROL (ISC_EVENTCLASS_DNS + 38) #define DNS_EVENT_ACACHECLEAN (ISC_EVENTCLASS_DNS + 39) #define DNS_EVENT_ACACHEOVERMEM (ISC_EVENTCLASS_DNS + 40) +#define DNS_EVENT_RBTPRUNE (ISC_EVENTCLASS_DNS + 41) #define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0) #define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535) diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 1019cd44..9741c157 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.270.12.4 2009/03/05 04:57:40 marka Exp $ */ +/* $Id: rbtdb.c,v 1.270.12.6 2009/05/06 23:34:30 jinmei Exp $ */ /*! \file */ @@ -344,7 +344,7 @@ struct acachectl { */ #ifdef DNS_RBTDB_CACHE_NODE_LOCK_COUNT #if DNS_RBTDB_CACHE_NODE_LOCK_COUNT <= 1 -#error "DNS_RBTDB_CACHE_NODE_LOCK_COUNT must be larger 1" +#error "DNS_RBTDB_CACHE_NODE_LOCK_COUNT must be larger than 1" #else #define DEFAULT_CACHE_NODE_LOCK_COUNT DNS_RBTDB_CACHE_NODE_LOCK_COUNT #endif @@ -533,6 +533,7 @@ static void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now, isc_boolean_t tree_locked); static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader); +static void prune_tree(isc_task_t *task, isc_event_t *event); static dns_rdatasetmethods_t rdataset_methods = { rdataset_disassociate, @@ -1551,7 +1552,7 @@ new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) { /* * This function is assumed to be called when a node is newly referenced * and can be in the deadnode list. In that case the node must be retrieved - * from the list because the it is going to be used. In addition, if the caller + * from the list because it is going to be used. In addition, if the caller * happens to hold a write lock on the tree, it's a good chance to purge dead * nodes. * Note: while a new reference is gained in multiple places, there are only very @@ -1604,13 +1605,15 @@ reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, static isc_boolean_t decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, rbtdb_serial_t least_serial, - isc_rwlocktype_t nlock, isc_rwlocktype_t tlock) + isc_rwlocktype_t nlock, isc_rwlocktype_t tlock, + isc_boolean_t pruning) { isc_result_t result; isc_boolean_t write_locked; rbtdb_nodelock_t *nodelock; unsigned int refs, nrefs; int bucket = node->locknum; + isc_boolean_t no_reference; nodelock = &rbtdb->node_locks[bucket]; @@ -1693,6 +1696,7 @@ 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) { /* * We can now delete the node if the reference counter is @@ -1701,35 +1705,97 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, * current thread locks the tree (e.g., in findnode()). */ - if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) { - char printname[DNS_NAME_FORMATSIZE]; + /* + * If this node is the only one in the level it's in, deleting + * this node may recursively make its parent the only node in + * the parent level; if so, and if no one is currently using + * the parent node, this is almost the only opportunity to + * clean it up. But the recursive cleanup is not that trivial + * since the child and parent may be in different lock buckets, + * which would cause a lock order reversal problem. To avoid + * the trouble, we'll dispatch a separate event for batch + * cleaning. We need to check whether we're deleting the node + * as a result of pruning to avoid infinite dispatching. + * Note: pruning happens only when a task has been set for the + * rbtdb. If the user of the rbtdb chooses not to set a task, + * it's their responsibility to purge stale leaves (e.g. by + * periodic walk-through). + */ + if (!pruning && node->parent != NULL && + node->parent->down == node && node->left == NULL && + node->right == NULL && rbtdb->task != NULL) { + isc_event_t *ev; + dns_db_t *db; + + ev = isc_event_allocate(rbtdb->common.mctx, NULL, + DNS_EVENT_RBTPRUNE, + prune_tree, node, + sizeof(isc_event_t)); + if (ev != NULL) { + new_reference(rbtdb, node); + db = NULL; + attach((dns_db_t *)rbtdb, &db); + ev->ev_sender = db; + isc_task_send(rbtdb->task, &ev); + no_reference = ISC_FALSE; + } else { + /* + * XXX: this is a weird situation. We could + * ignore this error case, but then the stale + * node will unlikely be purged except via a + * rare condition such as manual cleanup. So + * we queue it in the deadnodes list, hoping + * the memory shortage is temporary and the node + * will be deleted later. + */ + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, + ISC_LOG_INFO, + "decrement_reference: failed to " + "allocate pruning event"); + INSIST(!ISC_LINK_LINKED(node, deadlink)); + ISC_LIST_APPEND(rbtdb->deadnodes[bucket], node, + deadlink); + } + } else { + if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) { + char printname[DNS_NAME_FORMATSIZE]; + + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, + ISC_LOG_DEBUG(1), + "decrement_reference: " + "delete from rbt: %p %s", + node, + dns_rbt_formatnodename(node, + printname, + sizeof(printname))); + } - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1), - "decrement_reference: " - "delete from rbt: %p %s", - node, - dns_rbt_formatnodename(node, printname, - sizeof(printname))); + INSIST(!ISC_LINK_LINKED(node, deadlink)); + if (node->nsec3) + result = dns_rbt_deletenode(rbtdb->nsec3, node, + ISC_FALSE); + else + result = dns_rbt_deletenode(rbtdb->tree, node, + ISC_FALSE); + if (result != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, + ISC_LOG_WARNING, + "decrement_reference: " + "dns_rbt_deletenode: %s", + isc_result_totext(result)); + } } - - INSIST(!ISC_LINK_LINKED(node, deadlink)); - if (node->nsec3) - result = dns_rbt_deletenode(rbtdb->nsec3, node, - ISC_FALSE); - else - result = dns_rbt_deletenode(rbtdb->tree, node, - ISC_FALSE); - if (result != ISC_R_SUCCESS) - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_CACHE, ISC_LOG_WARNING, - "decrement_reference: " - "dns_rbt_deletenode: %s", - isc_result_totext(result)); } else if (dns_rbtnode_refcurrent(node) == 0) { INSIST(!ISC_LINK_LINKED(node, deadlink)); ISC_LIST_APPEND(rbtdb->deadnodes[bucket], node, deadlink); - } + } else + no_reference = ISC_FALSE; /* Restore the lock? */ if (nlock == isc_rwlocktype_read) @@ -1746,7 +1812,71 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, if (write_locked) isc_rwlock_downgrade(&rbtdb->tree_lock); - return (ISC_TRUE); + return (no_reference); +} + +/* + * Prune the tree by recursively cleaning-up single leaves. In the worst + * case, the number of iteration is the number of tree levels, which is at + * most the maximum number of domain name labels, i.e, 127. In practice, this + * should be much smaller (only a few times), and even the worst case would be + * acceptable for a single event. + */ +static void +prune_tree(isc_task_t *task, isc_event_t *event) { + dns_rbtdb_t *rbtdb = event->ev_sender; + dns_rbtnode_t *node = event->ev_arg; + dns_rbtnode_t *parent; + unsigned int locknum; + + UNUSED(task); + + isc_event_free(&event); + + RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); + locknum = node->locknum; + NODE_LOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write); + do { + parent = node->parent; + decrement_reference(rbtdb, node, 0, isc_rwlocktype_write, + isc_rwlocktype_write, ISC_TRUE); + + if (parent != NULL && parent->down == NULL) { + /* + * node was the only down child of the parent and has + * just been removed. We'll then need to examine the + * parent. Keep the lock if possible; otherwise, + * release the old lock and acquire one for the parent. + */ + if (parent->locknum != locknum) { + NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, + isc_rwlocktype_write); + locknum = parent->locknum; + NODE_LOCK(&rbtdb->node_locks[locknum].lock, + isc_rwlocktype_write); + } + + /* + * We need to gain a reference to the node before + * decrementing it in the next iteration. In addition, + * if the node is in the dead-nodes list, extract it + * from the list beforehand as we do in + * reactivate_node(). + */ + new_reference(rbtdb, parent); + if (ISC_LINK_LINKED(parent, deadlink)) { + ISC_LIST_UNLINK(rbtdb->deadnodes[locknum], + parent, deadlink); + } + } else + parent = NULL; + + node = parent; + } while (node != NULL); + NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write); + RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); + + detach((dns_db_t **)&rbtdb); } static inline void @@ -2163,8 +2293,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { NODE_UNLOCK(lock, isc_rwlocktype_write); } decrement_reference(rbtdb, header->node, least_serial, - isc_rwlocktype_write, - isc_rwlocktype_none); + isc_rwlocktype_write, isc_rwlocktype_none, + ISC_FALSE); } if (!EMPTY(cleanup_list)) { @@ -2197,7 +2327,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { rollback_node(rbtnode, serial); decrement_reference(rbtdb, rbtnode, least_serial, isc_rwlocktype_write, - isc_rwlocktype_write); + isc_rwlocktype_write, ISC_FALSE); NODE_UNLOCK(lock, isc_rwlocktype_write); @@ -3747,7 +3877,8 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, NODE_LOCK(lock, isc_rwlocktype_read); decrement_reference(search.rbtdb, node, 0, - isc_rwlocktype_read, isc_rwlocktype_none); + isc_rwlocktype_read, isc_rwlocktype_none, + ISC_FALSE); NODE_UNLOCK(lock, isc_rwlocktype_read); } @@ -4525,7 +4656,8 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, NODE_LOCK(lock, isc_rwlocktype_read); decrement_reference(search.rbtdb, node, 0, - isc_rwlocktype_read, isc_rwlocktype_none); + isc_rwlocktype_read, isc_rwlocktype_none, + ISC_FALSE); NODE_UNLOCK(lock, isc_rwlocktype_read); } @@ -4743,7 +4875,7 @@ detachnode(dns_db_t *db, dns_dbnode_t **targetp) { NODE_LOCK(&nodelock->lock, isc_rwlocktype_read); if (decrement_reference(rbtdb, node, 0, isc_rwlocktype_read, - isc_rwlocktype_none)) { + isc_rwlocktype_none, ISC_FALSE)) { if (isc_refcount_current(&nodelock->references) == 0 && nodelock->exiting) { inactive = ISC_TRUE; @@ -7469,7 +7601,7 @@ dereference_iter_node(rbtdb_dbiterator_t *rbtdbiter) { lock = &rbtdb->node_locks[node->locknum].lock; NODE_LOCK(lock, isc_rwlocktype_read); decrement_reference(rbtdb, node, 0, isc_rwlocktype_read, - rbtdbiter->tree_locked); + rbtdbiter->tree_locked, ISC_FALSE); NODE_UNLOCK(lock, isc_rwlocktype_read); rbtdbiter->node = NULL; @@ -7510,7 +7642,7 @@ flush_deletions(rbtdb_dbiterator_t *rbtdbiter) { NODE_LOCK(lock, isc_rwlocktype_read); decrement_reference(rbtdb, node, 0, isc_rwlocktype_read, - rbtdbiter->tree_locked); + rbtdbiter->tree_locked, ISC_FALSE); NODE_UNLOCK(lock, isc_rwlocktype_read); } @@ -8446,6 +8578,6 @@ expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, decrement_reference(rbtdb, header->node, 0, isc_rwlocktype_write, tree_locked ? isc_rwlocktype_write : - isc_rwlocktype_none); + isc_rwlocktype_none, ISC_FALSE); } } diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 39ff4bd1..a1c263e1 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.384.14.9 2009/02/27 23:05:22 marka Exp $ */ +/* $Id: resolver.c,v 1.384.14.12 2009/05/11 02:38:03 tbox Exp $ */ /*! \file */ @@ -4228,53 +4228,53 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, rdataset->trust = dns_trust_pending; if (sigrdataset != NULL) sigrdataset->trust = dns_trust_pending; - if (!need_validation) + if (!need_validation || !ANSWER(rdataset)) { addedrdataset = ardataset; - else - addedrdataset = NULL; - result = dns_db_addrdataset(fctx->cache, node, NULL, - now, rdataset, 0, - addedrdataset); - if (result == DNS_R_UNCHANGED) { - result = ISC_R_SUCCESS; - if (!need_validation && - ardataset != NULL && - ardataset->type == 0) { - /* - * The answer in the cache is better - * than the answer we found, and is - * a negative cache entry, so we - * must set eresult appropriately. - */ - if (NXDOMAIN(ardataset)) - eresult = DNS_R_NCACHENXDOMAIN; - else - eresult = DNS_R_NCACHENXRRSET; - /* - * We have a negative response from - * the cache so don't attempt to - * add the RRSIG rrset. - */ - continue; - } - } - if (result != ISC_R_SUCCESS) - break; - if (sigrdataset != NULL) { - if (!need_validation) - addedrdataset = asigrdataset; - else - addedrdataset = NULL; - result = dns_db_addrdataset(fctx->cache, - node, NULL, now, - sigrdataset, 0, - addedrdataset); - if (result == DNS_R_UNCHANGED) + result = dns_db_addrdataset(fctx->cache, node, + NULL, now, rdataset, + 0, addedrdataset); + if (result == DNS_R_UNCHANGED) { result = ISC_R_SUCCESS; + if (!need_validation && + ardataset != NULL && + ardataset->type == 0) { + /* + * The answer in the cache is + * better than the answer we + * found, and is a negative + * cache entry, so we must set + * eresult appropriately. + */ + if (NXDOMAIN(ardataset)) + eresult = + DNS_R_NCACHENXDOMAIN; + else + eresult = + DNS_R_NCACHENXRRSET; + /* + * We have a negative response + * from the cache so don't + * attempt to add the RRSIG + * rrset. + */ + continue; + } + } if (result != ISC_R_SUCCESS) break; - } else if (!ANSWER(rdataset)) - continue; + if (sigrdataset != NULL) { + addedrdataset = asigrdataset; + result = dns_db_addrdataset(fctx->cache, + node, NULL, now, + sigrdataset, 0, + addedrdataset); + if (result == DNS_R_UNCHANGED) + result = ISC_R_SUCCESS; + if (result != ISC_R_SUCCESS) + break; + } else if (!ANSWER(rdataset)) + continue; + } if (ANSWER(rdataset) && need_validation) { if (fctx->type != dns_rdatatype_any && diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c index f141a102..03fca9ed 100644 --- a/lib/dns/sdb.c +++ b/lib/dns/sdb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 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: sdb.c,v 1.66 2008/09/24 03:16:58 tbox Exp $ */ +/* $Id: sdb.c,v 1.66.48.2 2009/04/21 23:47:18 tbox Exp $ */ /*! \file */ @@ -880,9 +880,12 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, { result = DNS_R_ZONECUT; dns_rdataset_disassociate(rdataset); - if (sigrdataset != NULL) + if (sigrdataset != NULL && + dns_rdataset_isassociated + (sigrdataset)) { dns_rdataset_disassociate (sigrdataset); + } } else result = DNS_R_DELEGATION; break; diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index ec82c3e5..89cd0eea 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2005-2008 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2005-2009 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdlz.c,v 1.18 2008/09/24 02:46:22 marka Exp $ */ +/* $Id: sdlz.c,v 1.18.50.2 2009/04/21 23:47:18 tbox Exp $ */ /*! \file */ @@ -844,9 +844,12 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, { result = DNS_R_ZONECUT; dns_rdataset_disassociate(rdataset); - if (sigrdataset != NULL) + if (sigrdataset != NULL && + dns_rdataset_isassociated + (sigrdataset)) { dns_rdataset_disassociate (sigrdataset); + } } else result = DNS_R_DELEGATION; break; diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 3ef6b6dd..c62b7141 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: validator.c,v 1.164.12.5 2009/02/15 23:47:49 marka Exp $ */ +/* $Id: validator.c,v 1.164.12.9 2009/05/07 23:47:12 tbox Exp $ */ #include @@ -218,6 +218,37 @@ exit_check(dns_validator_t *val) { return (ISC_TRUE); } +/* + * Check that we have atleast one supported algorithm in the DLV RRset. + */ +static inline isc_boolean_t +dlv_algorithm_supported(dns_validator_t *val) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_dlv_t dlv; + isc_result_t result; + + for (result = dns_rdataset_first(&val->dlv); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&val->dlv)) { + dns_rdata_reset(&rdata); + dns_rdataset_current(&val->dlv, &rdata); + result = dns_rdata_tostruct(&rdata, &dlv, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + if (!dns_resolver_algorithm_supported(val->view->resolver, + val->event->name, + dlv.algorithm)) + continue; + + if (dlv.digest_type != DNS_DSDIGEST_SHA256 && + dlv.digest_type != DNS_DSDIGEST_SHA1) + continue; + + return (ISC_TRUE); + } + return (ISC_FALSE); +} + /*% * Look in the NSEC record returned from a DS query to see if there is * a NS RRset at this name. If it is found we are at a delegation point. @@ -2963,19 +2994,36 @@ dlvfetched(isc_task_t *task, isc_event_t *event) { sizeof(namebuf)); dns_rdataset_clone(&val->frdataset, &val->dlv); val->havedlvsep = ISC_TRUE; - validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf); - dlv_validator_start(val); + if (dlv_algorithm_supported(val)) { + validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", + namebuf); + dlv_validator_start(val); + } else { + validator_log(val, ISC_LOG_DEBUG(3), + "DLV %s found with no supported algorithms", + namebuf); + markanswer(val); + validator_done(val, ISC_R_SUCCESS); + } } else if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NXDOMAIN || eresult == DNS_R_NCACHENXRRSET || eresult == DNS_R_NCACHENXDOMAIN) { - result = finddlvsep(val, ISC_TRUE); + result = finddlvsep(val, ISC_TRUE); if (result == ISC_R_SUCCESS) { - dns_name_format(dns_fixedname_name(&val->dlvsep), - namebuf, sizeof(namebuf)); - validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", - namebuf); - dlv_validator_start(val); + if (dlv_algorithm_supported(val)) { + dns_name_format(dns_fixedname_name(&val->dlvsep), + namebuf, sizeof(namebuf)); + validator_log(val, ISC_LOG_DEBUG(3), + "DLV %s found", namebuf); + dlv_validator_start(val); + } else { + validator_log(val, ISC_LOG_DEBUG(3), + "DLV %s found with no supported " + "algorithms", namebuf); + markanswer(val); + validator_done(val, ISC_R_SUCCESS); + } } else if (result == ISC_R_NOTFOUND) { validator_log(val, ISC_LOG_DEBUG(3), "DLV not found"); markanswer(val); @@ -3038,9 +3086,16 @@ startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) { } dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf, sizeof(namebuf)); - validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf); - dlv_validator_start(val); - return (DNS_R_WAIT); + if (dlv_algorithm_supported(val)) { + validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf); + dlv_validator_start(val); + return (DNS_R_WAIT); + } + validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported " + "algorithms", namebuf); + markanswer(val); + validator_done(val, ISC_R_SUCCESS); + return (ISC_R_SUCCESS); } /*% @@ -3177,9 +3232,13 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) dns_name_t *secroot; dns_name_t *tname; char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_t *found; + dns_fixedname_t fixedfound; dns_fixedname_init(&fixedsecroot); secroot = dns_fixedname_name(&fixedsecroot); + dns_fixedname_init(&fixedfound); + found = dns_fixedname_name(&fixedfound); if (val->havedlvsep) dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL); else { @@ -3287,6 +3346,28 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) goto out; return (DNS_R_WAIT); } + /* + * Zones using NSEC3 don't return a NSEC RRset so + * we need to use dns_view_findzonecut2 to find + * the zone cut. + */ + if (result == DNS_R_NXRRSET && + !dns_rdataset_isassociated(&val->frdataset) && + dns_view_findzonecut2(val->view, tname, found, + 0, 0, ISC_FALSE, ISC_FALSE, + NULL, NULL) == ISC_R_SUCCESS && + dns_name_equal(tname, found)) { + if (val->mustbesecure) { + validator_log(val, ISC_LOG_WARNING, + "must be secure failure"); + return (DNS_R_MUSTBESECURE); + } + if (val->view->dlv == NULL || DLVTRIED(val)) { + markanswer(val); + return (ISC_R_SUCCESS); + } + return (startfinddlvsep(val, tname)); + } if (val->frdataset.trust < dns_trust_secure) { /* * This shouldn't happen, since the negative diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 732566fc..423b0057 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.483.36.5 2009/03/13 01:38:51 marka Exp $ */ +/* $Id: zone.c,v 1.483.36.6 2009/03/26 22:57:07 marka Exp $ */ /*! \file */ @@ -9560,7 +9560,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), "removing journal file"); - if (remove(zone->journal) < 0) { + if (remove(zone->journal) < 0 && errno != ENOENT) { char strbuf[ISC_STRERRORSIZE]; isc__strerror(errno, strbuf, sizeof(strbuf)); isc_log_write(dns_lctx, diff --git a/lib/isc/alpha/include/isc/atomic.h b/lib/isc/alpha/include/isc/atomic.h index 056d5fc3..bc1510ff 100644 --- a/lib/isc/alpha/include/isc/atomic.h +++ b/lib/isc/alpha/include/isc/atomic.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: atomic.h,v 1.5 2007/06/19 23:47:17 tbox Exp $ */ +/* $Id: atomic.h,v 1.5.332.2 2009/04/08 06:47:32 tbox Exp $ */ /* * This code was written based on FreeBSD's kernel source whose copyright @@ -62,16 +62,20 @@ /* * This routine atomically increments the value stored in 'p' by 'val', and - * returns the previous value. + * returns the previous value. Memory access ordering around this function + * can be critical, so we add explicit memory block instructions at the + * beginning and the end of it (same for other functions). */ -static inline isc_int32_t +static inline isc_int32_t isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { - return (asm("1:" + return (asm("mb;" + "1:" "ldl_l %t0, 0(%a0);" /* load old value */ "mov %t0, %v0;" /* copy the old value */ "addl %t0, %a1, %t0;" /* calculate new value */ "stl_c %t0, 0(%a0);" /* attempt to store */ - "beq %t0, 1b;", /* spin if failed */ + "beq %t0, 1b;" /* spin if failed */ + "mb;", p, val)); } @@ -80,11 +84,13 @@ isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { */ static inline void isc_atomic_store(isc_int32_t *p, isc_int32_t val) { - (void)asm("1:" + (void)asm("mb;" + "1:" "ldl_l %t0, 0(%a0);" /* load old value */ "mov %a1, %t0;" /* value to store */ "stl_c %t0, 0(%a0);" /* attempt to store */ - "beq %t0, 1b;", /* spin if failed */ + "beq %t0, 1b;" /* spin if failed */ + "mb;", p, val); } @@ -96,7 +102,8 @@ isc_atomic_store(isc_int32_t *p, isc_int32_t val) { static inline isc_int32_t isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { - return(asm("1:" + return(asm("mb;" + "1:" "ldl_l %t0, 0(%a0);" /* load old value */ "mov %t0, %v0;" /* copy the old value */ "cmpeq %t0, %a1, %t0;" /* compare */ @@ -104,22 +111,25 @@ isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { "mov %a2, %t0;" /* value to store */ "stl_c %t0, 0(%a0);" /* attempt to store */ "beq %t0, 1b;" /* if it failed, spin */ - "2:", + "2:" + "mb;", p, cmpval, val)); } #elif defined (ISC_PLATFORM_USEGCCASM) -static inline isc_int32_t +static inline isc_int32_t isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) { isc_int32_t temp, prev; __asm__ volatile( + "mb;" "1:" "ldl_l %0, %1;" /* load old value */ "mov %0, %2;" /* copy the old value */ "addl %0, %3, %0;" /* calculate new value */ "stl_c %0, %1;" /* attempt to store */ "beq %0, 1b;" /* spin if failed */ - : "=&r"(temp), "+m"(*p), "=r"(prev) + "mb;" + : "=&r"(temp), "+m"(*p), "=&r"(prev) : "r"(val) : "memory"); @@ -131,11 +141,13 @@ isc_atomic_store(isc_int32_t *p, isc_int32_t val) { isc_int32_t temp; __asm__ volatile( + "mb;" "1:" "ldl_l %0, %1;" /* load old value */ "mov %2, %0;" /* value to store */ "stl_c %0, %1;" /* attempt to store */ "beq %0, 1b;" /* if it failed, spin */ + "mb;" : "=&r"(temp), "+m"(*p) : "r"(val) : "memory"); @@ -146,6 +158,7 @@ isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { isc_int32_t temp, prev; __asm__ volatile( + "mb;" "1:" "ldl_l %0, %1;" /* load old value */ "mov %0, %2;" /* copy the old value */ @@ -155,7 +168,8 @@ isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) { "stl_c %0, %1;" /* attempt to store */ "beq %0, 1b;" /* if it failed, spin */ "2:" - : "=&r"(temp), "+m"(*p), "=r"(prev) + "mb;" + : "=&r"(temp), "+m"(*p), "=&r"(prev) : "r"(cmpval), "r"(val) : "memory"); diff --git a/lib/isc/api b/lib/isc/api index e5a8e69a..5ef8dc03 100644 --- a/lib/isc/api +++ b/lib/isc/api @@ -1,3 +1,3 @@ LIBINTERFACE = 51 -LIBREVISION = 0 +LIBREVISION = 1 LIBAGE = 1 diff --git a/lib/isc/hash.c b/lib/isc/hash.c index 41bb8842..9911bdee 100644 --- a/lib/isc/hash.c +++ b/lib/isc/hash.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,11 +15,11 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: hash.c,v 1.13 2007/06/19 23:47:17 tbox Exp $ */ +/* $Id: hash.c,v 1.13.332.3 2009/05/07 23:47:12 tbox Exp $ */ /*! \file * Some portion of this code was derived from universal hash function - * libraries of Rice University. + * libraries of Rice University. \section license UH Universal Hashing Library Copyright ((c)) 2002, Rice University @@ -244,7 +244,7 @@ isc_hash_ctxinit(isc_hash_t *hctx) { goto out; if (hctx->entropy) { - result = isc_entropy_getdata(hctx->entropy, + result = isc_entropy_getdata(hctx->entropy, hctx->rndvector, hctx->vectorlen, NULL, 0); INSIST(result == ISC_R_SUCCESS); @@ -276,7 +276,7 @@ isc_hash_ctxinit(isc_hash_t *hctx) { void isc_hash_init() { INSIST(hash != NULL && VALID_HASH(hash)); - + isc_hash_ctxinit(hash); } diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index f0a320e9..d09fe51a 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.308.12.7 2009/02/16 00:24:04 marka Exp $ */ +/* $Id: socket.c,v 1.308.12.8 2009/04/18 01:29:26 jinmei Exp $ */ /*! \file */ @@ -1878,6 +1878,9 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, goto error; } + memset(sock->name, 0, sizeof(sock->name)); + sock->tag = NULL; + /* * set up list of readers and writers to be initially empty */ @@ -2317,9 +2320,6 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, return (result); } - memset(sock->name, 0, sizeof(sock->name)); - sock->tag = NULL; - sock->references = 1; *socketp = sock; @@ -2525,11 +2525,14 @@ isc_socket_close(isc_socket_t *sock) { type = sock->type; fd = sock->fd; sock->fd = -1; + memset(sock->name, 0, sizeof(sock->name)); + sock->tag = NULL; sock->listener = 0; sock->connected = 0; sock->connecting = 0; sock->bound = 0; isc_sockaddr_any(&sock->peer_address); + UNLOCK(&sock->lock); closesocket(manager, sock, fd); diff --git a/lib/lwres/api b/lib/lwres/api index 2240cdda..39934b4f 100644 --- a/lib/lwres/api +++ b/lib/lwres/api @@ -1,3 +1,3 @@ LIBINTERFACE = 50 -LIBREVISION = 1 +LIBREVISION = 2 LIBAGE = 0 diff --git a/lib/lwres/getaddrinfo.c b/lib/lwres/getaddrinfo.c index b5a2bcd8..fc53e63a 100644 --- a/lib/lwres/getaddrinfo.c +++ b/lib/lwres/getaddrinfo.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * This code is derived from software contributed to ISC by @@ -18,7 +18,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: getaddrinfo.c,v 1.52 2007/09/13 04:45:18 each Exp $ */ +/* $Id: getaddrinfo.c,v 1.52.254.2 2009/03/31 23:47:16 tbox Exp $ */ /*! \file */ @@ -31,10 +31,10 @@ * string: a dotted decimal IPv4 address or an IPv6 address. servname is * either a decimal port number or a service name as listed in * /etc/services. - * + * * If the operating system does not provide a struct addrinfo, the * following structure is used: - * + * * \code * struct addrinfo { * int ai_flags; // AI_PASSIVE, AI_CANONNAME @@ -47,29 +47,29 @@ * struct addrinfo *ai_next; // next structure in linked list * }; * \endcode - * - * + * + * * hints is an optional pointer to a struct addrinfo. This structure can * be used to provide hints concerning the type of socket that the caller * supports or wishes to use. The caller can supply the following * structure elements in *hints: - * + * * - * + * * All other elements of the struct addrinfo passed via hints must be * zero. - * + * * A hints of NULL is treated as if the caller provided a struct addrinfo * initialized to zero with ai_familyset to PF_UNSPEC. - * + * * After a successful call to lwres_getaddrinfo(), *res is a pointer to a * linked list of one or more addrinfo structures. Each struct addrinfo * in this list cn be processed by following the ai_next pointer, until a @@ -109,7 +109,7 @@ * corresponding arguments for a call to socket(2). For each addrinfo * structure in the list, the ai_addr member points to a filled-in socket * address structure of length ai_addrlen. - * + * * All of the information returned by lwres_getaddrinfo() is dynamically * allocated: the addrinfo structures, and the socket address structures * and canonical host name strings pointed to by the addrinfostructures. @@ -117,15 +117,15 @@ * successful call to lwres_getaddrinfo() is released by * lwres_freeaddrinfo(). ai is a pointer to a struct addrinfo created by * a call to lwres_getaddrinfo(). - * + * * \section lwresreturn RETURN VALUES - * + * * lwres_getaddrinfo() returns zero on success or one of the error codes * listed in gai_strerror() if an error occurs. If both hostname and * servname are NULL lwres_getaddrinfo() returns #EAI_NONAME. - * + * * \section lwressee SEE ALSO - * + * * lwres(3), lwres_getaddrinfo(), lwres_freeaddrinfo(), * lwres_gai_strerror(), RFC2133, getservbyname(3), connect(2), * sendto(2), sendmsg(2), socket(2). @@ -145,7 +145,7 @@ #define SA(addr) ((struct sockaddr *)(addr)) #define SIN(addr) ((struct sockaddr_in *)(addr)) #define SIN6(addr) ((struct sockaddr_in6 *)(addr)) -#define SUN(addr) ((struct sockaddr_un *)(addr)) +#define SLOCAL(addr) ((struct sockaddr_un *)(addr)) /*! \struct addrinfo */ @@ -162,7 +162,7 @@ static int add_ipv4(const char *hostname, int flags, struct addrinfo **aip, static int add_ipv6(const char *hostname, int flags, struct addrinfo **aip, int socktype, int port); static void set_order(int, int (**)(const char *, int, struct addrinfo **, - int, int)); + int, int)); #define FOUND_IPV4 0x1 #define FOUND_IPV6 0x2 @@ -384,7 +384,7 @@ lwres_getaddrinfo(const char *hostname, const char *servname, scopeid = 0; #endif - if (lwres_net_pton(AF_INET, hostname, (struct in_addr *)abuf) + if (lwres_net_pton(AF_INET, hostname, (struct in_addr *)abuf) == 1) { if (family == AF_INET6) { @@ -709,17 +709,17 @@ lwres_freeaddrinfo(struct addrinfo *ai) { static int get_local(const char *name, int socktype, struct addrinfo **res) { struct addrinfo *ai; - struct sockaddr_un *sun; + struct sockaddr_un *slocal; if (socktype == 0) return (EAI_SOCKTYPE); - ai = ai_alloc(AF_LOCAL, sizeof(*sun)); + ai = ai_alloc(AF_LOCAL, sizeof(*slocal)); if (ai == NULL) return (EAI_MEMORY); - sun = SUN(ai->ai_addr); - strncpy(sun->sun_path, name, sizeof(sun->sun_path)); + slocal = SLOCAL(ai->ai_addr); + strncpy(slocal->sun_path, name, sizeof(slocal->sun_path)); ai->ai_socktype = socktype; /* -- cgit v1.2.3