diff options
Diffstat (limited to 'usr.sbin/bind/lib/dns')
-rw-r--r-- | usr.sbin/bind/lib/dns/adb.c | 12 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/api | 4 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/cache.c | 27 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/include/dns/rdataset.h | 37 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/message.c | 62 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/name.c | 28 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/rbt.c | 9 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/rbtdb.c | 43 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/rdata.c | 14 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/rdata/any_255/tsig_250.c | 16 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/rdata/generic/ds_43.c | 12 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/rdata/generic/rt_21.c | 6 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/resolver.c | 224 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/tsig.c | 6 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/validator.c | 618 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/xfrin.c | 10 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/zone.c | 245 |
17 files changed, 795 insertions, 578 deletions
diff --git a/usr.sbin/bind/lib/dns/adb.c b/usr.sbin/bind/lib/dns/adb.c index e21965a91ae..9dd4f19bebc 100644 --- a/usr.sbin/bind/lib/dns/adb.c +++ b/usr.sbin/bind/lib/dns/adb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: adb.c,v 1.181.2.11.2.20 2004/11/10 22:32:40 marka Exp $ */ +/* $ISC: adb.c,v 1.181.2.11.2.24 2005/10/14 05:19:00 marka Exp $ */ /* * Implementation notes @@ -1784,7 +1784,7 @@ shutdown_task(isc_task_t *task, isc_event_t *ev) { static isc_boolean_t check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) { dns_adbname_t *name; - isc_result_t result = ISC_FALSE; + isc_boolean_t result = ISC_FALSE; INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep)); name = *namep; @@ -1861,7 +1861,7 @@ static isc_boolean_t cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) { dns_adbname_t *name; dns_adbname_t *next_name; - isc_result_t result = ISC_FALSE; + isc_boolean_t result = ISC_FALSE; DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket); @@ -3347,7 +3347,7 @@ dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *zone, bucket = addr->entry->lock_bucket; LOCK(&adb->entrylocks[bucket]); zi = ISC_LIST_HEAD(addr->entry->zoneinfo); - while (zi != NULL && dns_name_equal(zone, &zi->zone)) + while (zi != NULL && !dns_name_equal(zone, &zi->zone)) zi = ISC_LIST_NEXT(zi, plink); if (zi != NULL) { if (expire_time > zi->lame_timer) @@ -3366,7 +3366,7 @@ dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *zone, unlock: UNLOCK(&adb->entrylocks[bucket]); - return (ISC_R_SUCCESS); + return (result); } void diff --git a/usr.sbin/bind/lib/dns/api b/usr.sbin/bind/lib/dns/api index c06a62ec803..7df81573fd7 100644 --- a/usr.sbin/bind/lib/dns/api +++ b/usr.sbin/bind/lib/dns/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 20 -LIBREVISION = 2 +LIBINTERFACE = 21 +LIBREVISION = 1 LIBAGE = 0 diff --git a/usr.sbin/bind/lib/dns/cache.c b/usr.sbin/bind/lib/dns/cache.c index 83f4629ee81..8175a0a0144 100644 --- a/usr.sbin/bind/lib/dns/cache.c +++ b/usr.sbin/bind/lib/dns/cache.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: cache.c,v 1.45.2.4.8.7 2004/03/08 02:07:52 marka Exp $ */ +/* $ISC: cache.c,v 1.45.2.4.8.9 2005/03/17 03:58:30 marka Exp $ */ #include <config.h> @@ -1021,27 +1021,10 @@ dns_cache_flushname(dns_cache_t *cache, dns_name_t *name) { dns_rdataset_init(&rdataset); dns_rdatasetiter_current(iter, &rdataset); - - for (result = dns_rdataset_first(&rdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(&rdataset)) - { - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdatatype_t covers; - - dns_rdataset_current(&rdataset, &rdata); - if (rdata.type == dns_rdatatype_rrsig) - covers = dns_rdata_covers(&rdata); - else - covers = 0; - result = dns_db_deleterdataset(cache->db, node, NULL, - rdata.type, covers); - if (result != ISC_R_SUCCESS && - result != DNS_R_UNCHANGED) - break; - } + result = dns_db_deleterdataset(cache->db, node, NULL, + rdataset.type, rdataset.covers); dns_rdataset_disassociate(&rdataset); - if (result != ISC_R_NOMORE) + if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) break; } if (result == ISC_R_NOMORE) diff --git a/usr.sbin/bind/lib/dns/include/dns/rdataset.h b/usr.sbin/bind/lib/dns/include/dns/rdataset.h index 595a9af30fd..ca06b0e34cb 100644 --- a/usr.sbin/bind/lib/dns/include/dns/rdataset.h +++ b/usr.sbin/bind/lib/dns/include/dns/rdataset.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: rdataset.h,v 1.41.2.5.2.6 2004/03/08 02:08:01 marka Exp $ */ +/* $ISC: rdataset.h,v 1.41.2.5.2.8 2005/03/17 03:58:31 marka Exp $ */ #ifndef DNS_RDATASET_H #define DNS_RDATASET_H 1 @@ -130,22 +130,23 @@ struct dns_rdataset { * Used by message.c to indicate that the rdataset's rdata had differing * TTL values, and the rdataset->ttl holds the smallest. */ -#define DNS_RDATASETATTR_QUESTION 0x0001 -#define DNS_RDATASETATTR_RENDERED 0x0002 /* Used by message.c */ -#define DNS_RDATASETATTR_ANSWERED 0x0004 /* Used by server. */ -#define DNS_RDATASETATTR_CACHE 0x0008 /* Used by resolver. */ -#define DNS_RDATASETATTR_ANSWER 0x0010 /* Used by resolver. */ -#define DNS_RDATASETATTR_ANSWERSIG 0x0020 /* Used by resolver. */ -#define DNS_RDATASETATTR_EXTERNAL 0x0040 /* Used by resolver. */ -#define DNS_RDATASETATTR_NCACHE 0x0080 /* Used by resolver. */ -#define DNS_RDATASETATTR_CHAINING 0x0100 /* Used by resolver. */ -#define DNS_RDATASETATTR_TTLADJUSTED 0x0200 /* Used by message.c */ -#define DNS_RDATASETATTR_FIXEDORDER 0x0400 -#define DNS_RDATASETATTR_RANDOMIZE 0x0800 -#define DNS_RDATASETATTR_CHASE 0x1000 /* Used by resolver. */ -#define DNS_RDATASETATTR_NXDOMAIN 0x2000 -#define DNS_RDATASETATTR_NOQNAME 0x4000 -#define DNS_RDATASETATTR_CHECKNAMES 0x8000 /* Used by resolver. */ +#define DNS_RDATASETATTR_QUESTION 0x00000001 +#define DNS_RDATASETATTR_RENDERED 0x00000002 /* Used by message.c */ +#define DNS_RDATASETATTR_ANSWERED 0x00000004 /* Used by server. */ +#define DNS_RDATASETATTR_CACHE 0x00000008 /* Used by resolver. */ +#define DNS_RDATASETATTR_ANSWER 0x00000010 /* Used by resolver. */ +#define DNS_RDATASETATTR_ANSWERSIG 0x00000020 /* Used by resolver. */ +#define DNS_RDATASETATTR_EXTERNAL 0x00000040 /* Used by resolver. */ +#define DNS_RDATASETATTR_NCACHE 0x00000080 /* Used by resolver. */ +#define DNS_RDATASETATTR_CHAINING 0x00000100 /* Used by resolver. */ +#define DNS_RDATASETATTR_TTLADJUSTED 0x00000200 /* Used by message.c */ +#define DNS_RDATASETATTR_FIXEDORDER 0x00000400 +#define DNS_RDATASETATTR_RANDOMIZE 0x00000800 +#define DNS_RDATASETATTR_CHASE 0x00001000 /* Used by resolver. */ +#define DNS_RDATASETATTR_NXDOMAIN 0x00002000 +#define DNS_RDATASETATTR_NOQNAME 0x00004000 +#define DNS_RDATASETATTR_CHECKNAMES 0x00008000 /* Used by resolver. */ +#define DNS_RDATASETATTR_REQUIREDGLUE 0x00010000 /* * _OMITDNSSEC: diff --git a/usr.sbin/bind/lib/dns/message.c b/usr.sbin/bind/lib/dns/message.c index ea6f863e1af..5dbaa35c31a 100644 --- a/usr.sbin/bind/lib/dns/message.c +++ b/usr.sbin/bind/lib/dns/message.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: message.c,v 1.194.2.10.2.17 2004/05/05 01:32:16 marka Exp $ */ +/* $ISC: message.c,v 1.194.2.10.2.20 2005/06/07 01:42:23 marka Exp $ */ /*** *** Imports @@ -1476,6 +1476,13 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, free_name = ISC_FALSE; } + if (seen_problem) { + if (free_name) + isc_mempool_put(msg->namepool, name); + if (free_rdataset) + isc_mempool_put(msg->rdspool, rdataset); + free_name = free_rdataset = ISC_FALSE; + } INSIST(free_name == ISC_FALSE); INSIST(free_rdataset == ISC_FALSE); } @@ -1783,6 +1790,57 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0) partial = ISC_TRUE; + /* + * Render required glue first. Set TC if it won't fit. + */ + name = ISC_LIST_HEAD(*section); + if (name != NULL) { + rdataset = ISC_LIST_HEAD(name->list); + if (rdataset != NULL && + (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 && + (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) { + void *order_arg = msg->order_arg; + st = *(msg->buffer); + count = 0; + if (partial) + result = dns_rdataset_towirepartial(rdataset, + name, + msg->cctx, + msg->buffer, + msg->order, + order_arg, + rd_options, + &count, + NULL); + else + result = dns_rdataset_towiresorted(rdataset, + name, + msg->cctx, + msg->buffer, + msg->order, + order_arg, + rd_options, + &count); + total += count; + if (partial && result == ISC_R_NOSPACE) { + msg->flags |= DNS_MESSAGEFLAG_TC; + msg->buffer->length += msg->reserved; + msg->counts[sectionid] += total; + return (result); + } + if (result != ISC_R_SUCCESS) { + INSIST(st.used < 65536); + dns_compress_rollback(msg->cctx, + (isc_uint16_t)st.used); + *(msg->buffer) = st; /* rollback */ + msg->buffer->length += msg->reserved; + msg->counts[sectionid] += total; + return (result); + } + rdataset->attributes |= DNS_RDATASETATTR_RENDERED; + } + } + do { name = ISC_LIST_HEAD(*section); if (name == NULL) { diff --git a/usr.sbin/bind/lib/dns/name.c b/usr.sbin/bind/lib/dns/name.c index f32f7636317..4a176c7e0ce 100644 --- a/usr.sbin/bind/lib/dns/name.c +++ b/usr.sbin/bind/lib/dns/name.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: name.c,v 1.127.2.7.2.11 2004/09/01 05:19:59 marka Exp $ */ +/* $ISC: name.c,v 1.127.2.7.2.14 2005/10/14 01:38:48 marka Exp $ */ #include <config.h> @@ -945,9 +945,9 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, unsigned char *ndata, *label; char *tdata; char c; - ft_state state, kind; - unsigned int value, count, tbcount, bitlength, maxlength; - unsigned int n1, n2, vlen, tlen, nrem, nused, digits, labels, tused; + ft_state state; + unsigned int value, count; + unsigned int n1, n2, tlen, nrem, nused, digits, labels, tused; isc_boolean_t done; unsigned char *offsets; dns_offsets_t odata; @@ -985,15 +985,10 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, */ n1 = 0; n2 = 0; - vlen = 0; label = NULL; digits = 0; value = 0; count = 0; - tbcount = 0; - bitlength = 0; - maxlength = 0; - kind = ft_init; /* * Make 'name' empty in case of failure. @@ -1051,7 +1046,6 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, state = ft_initialescape; break; } - kind = ft_ordinary; state = ft_ordinary; if (nrem == 0) return (ISC_R_NOSPACE); @@ -1094,7 +1088,6 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, */ return (DNS_R_BADLABELTYPE); } - kind = ft_ordinary; state = ft_escape; /* FALLTHROUGH */ case ft_escape: @@ -1305,13 +1298,14 @@ dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot, trem--; nlen--; } else { - char buf[5]; if (trem < 4) return (ISC_R_NOSPACE); - snprintf(buf, sizeof(buf), - "\\%03u", c); - memcpy(tdata, buf, 4); - tdata += 4; + *tdata++ = 0x5c; + *tdata++ = 0x30 + + ((c / 100) % 10); + *tdata++ = 0x30 + + ((c / 10) % 10); + *tdata++ = 0x30 + (c % 10); trem -= 4; ndata++; nlen--; diff --git a/usr.sbin/bind/lib/dns/rbt.c b/usr.sbin/bind/lib/dns/rbt.c index aef9d996ede..fcaee76f80e 100644 --- a/usr.sbin/bind/lib/dns/rbt.c +++ b/usr.sbin/bind/lib/dns/rbt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: rbt.c,v 1.115.2.2.2.11 2004/10/25 01:36:07 marka Exp $ */ +/* $ISC: rbt.c,v 1.115.2.2.2.13 2005/06/18 01:03:24 marka Exp $ */ /* Principal Authors: DCL */ @@ -2060,7 +2060,10 @@ dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum, if (DATA(node) != NULL && rbt->data_deleter != NULL) rbt->data_deleter(DATA(node), rbt->deleter_arg); - unhash_node(rbt, node); + /* + * Note: we don't call unhash_node() here as we are destroying + * the complete rbt tree. + */ #if DNS_RBT_USEMAGIC node->magic = 0; #endif diff --git a/usr.sbin/bind/lib/dns/rbtdb.c b/usr.sbin/bind/lib/dns/rbtdb.c index 32d787e1219..3c08492e17a 100644 --- a/usr.sbin/bind/lib/dns/rbtdb.c +++ b/usr.sbin/bind/lib/dns/rbtdb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: rbtdb.c,v 1.168.2.11.2.16 2004/05/23 11:07:23 marka Exp $ */ +/* $ISC: rbtdb.c,v 1.168.2.11.2.22 2005/10/14 01:38:48 marka Exp $ */ /* * Principal Author: Bob Halley @@ -97,6 +97,12 @@ typedef isc_uint32_t rbtdb_rdatatype_t; #define RBTDB_RDATATYPE_NCACHEANY \ RBTDB_RDATATYPE_VALUE(0, dns_rdatatype_any) +/* + * Allow clients with a virtual time of upto 5 minutes in the past to see + * records that would have otherwise have expired. + */ +#define RBTDB_VIRTUAL 300 + struct noqname { dns_name_t name; void * nsec; @@ -413,7 +419,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) { again: if (rbtdb->tree != NULL) { result = dns_rbt_destroy2(&rbtdb->tree, - (rbtdb->task != NULL) ? 5 : 0); + (rbtdb->task != NULL) ? 1000 : 0); if (result == ISC_R_QUOTA) { INSIST(rbtdb->task != NULL); if (event == NULL) @@ -2752,10 +2758,9 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep, isc_result_t result; dns_fixedname_t fname, forigin; dns_name_t *name, *origin; - rbtdb_rdatatype_t matchtype, sigmatchtype, nsectype; + rbtdb_rdatatype_t matchtype, sigmatchtype; matchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_nsec, 0); - nsectype = RBTDB_RDATATYPE_VALUE(0, dns_rdatatype_nsec); sigmatchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_nsec); @@ -2786,7 +2791,9 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep, * node as dirty, so it will get cleaned up * later. */ - if (node->references == 0) { + if (header->ttl > search->now - RBTDB_VIRTUAL) + header_prev = header; + else if (node->references == 0) { INSIST(header->down == NULL); if (header_prev != NULL) header_prev->next = @@ -2943,7 +2950,9 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * mark it as stale, and the node as dirty, so it will * get cleaned up later. */ - if (node->references == 0) { + if (header->ttl > now - RBTDB_VIRTUAL) + header_prev = header; + else if (node->references == 0) { INSIST(header->down == NULL); if (header_prev != NULL) header_prev->next = header->next; @@ -3210,7 +3219,9 @@ cache_findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options, * mark it as stale, and the node as dirty, so it will * get cleaned up later. */ - if (node->references == 0) { + if (header->ttl > now - RBTDB_VIRTUAL) + header_prev = header; + else if (node->references == 0) { INSIST(header->down == NULL); if (header_prev != NULL) header_prev->next = header->next; @@ -3398,7 +3409,7 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) { LOCK(&rbtdb->node_locks[rbtnode->locknum].lock); for (header = rbtnode->data; header != NULL; header = header->next) - if (header->ttl <= now) { + if (header->ttl <= now - RBTDB_VIRTUAL) { /* * We don't check if rbtnode->references == 0 and try * to free like we do in cache_find(), because @@ -3640,8 +3651,10 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, * rbtnode->references must be non-zero. This is so * because 'node' is an argument to the function. */ - header->attributes |= RDATASET_ATTR_STALE; - rbtnode->dirty = 1; + if (header->ttl <= now - RBTDB_VIRTUAL) { + header->attributes |= RDATASET_ATTR_STALE; + rbtnode->dirty = 1; + } } else if (EXISTS(header)) { if (header->type == matchtype) found = header; @@ -4344,6 +4357,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, changed = add_changed(rbtdb, rbtversion, rbtnode); if (changed == NULL) { free_rdataset(rbtdb->common.mctx, newheader); + UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock); return (ISC_R_NOMEMORY); } @@ -4909,6 +4923,11 @@ dns_rbtdb_create isc_mem_attach(mctx, &rbtdb->common.mctx); /* + * Must be initalized before free_rbtdb() is called. + */ + isc_ondestroy_init(&rbtdb->common.ondest); + + /* * Make a copy of the origin name. */ result = dns_name_dupwithoffsets(origin, mctx, &rbtdb->common.origin); @@ -4986,8 +5005,6 @@ dns_rbtdb_create rbtdb->future_version = NULL; ISC_LIST_INIT(rbtdb->open_versions); - isc_ondestroy_init(&rbtdb->common.ondest); - rbtdb->common.magic = DNS_DB_MAGIC; rbtdb->common.impmagic = RBTDB_MAGIC; diff --git a/usr.sbin/bind/lib/dns/rdata.c b/usr.sbin/bind/lib/dns/rdata.c index 6527157414d..9626b3231f5 100644 --- a/usr.sbin/bind/lib/dns/rdata.c +++ b/usr.sbin/bind/lib/dns/rdata.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: rdata.c,v 1.147.2.11.2.16 2004/10/06 05:37:40 marka Exp $ */ +/* $ISC: rdata.c,v 1.147.2.11.2.20 2005/07/22 05:27:52 marka Exp $ */ #include <config.h> #include <ctype.h> @@ -985,11 +985,15 @@ txt_totext(isc_region_t *source, isc_buffer_t *target) { if (*sp < 0x20 || *sp >= 0x7f) { if (tl < 4) return (ISC_R_NOSPACE); - snprintf(tp, 5, "\\%03u", *sp++); - tp += 4; + *tp++ = 0x5c; + *tp++ = 0x30 + ((*sp / 100) % 10); + *tp++ = 0x30 + ((*sp / 10) % 10); + *tp++ = 0x30 + (*sp % 10); + sp++; tl -= 4; continue; } + /* double quote, semi-colon, backslash */ if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c) { if (tl < 2) return (ISC_R_NOSPACE); @@ -1212,7 +1216,7 @@ name_tobuffer(dns_name_t *name, isc_buffer_t *target) { static isc_uint32_t uint32_fromregion(isc_region_t *region) { - unsigned long value; + isc_uint32_t value; REQUIRE(region->length >= 4); value = region->base[0] << 24; diff --git a/usr.sbin/bind/lib/dns/rdata/any_255/tsig_250.c b/usr.sbin/bind/lib/dns/rdata/any_255/tsig_250.c index 11734f0288d..a9f0ce25bbc 100644 --- a/usr.sbin/bind/lib/dns/rdata/any_255/tsig_250.c +++ b/usr.sbin/bind/lib/dns/rdata/any_255/tsig_250.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: tsig_250.c,v 1.52.2.1.2.6 2004/03/08 09:04:40 marka Exp $ */ +/* $ISC: tsig_250.c,v 1.52.2.1.2.8 2005/03/20 22:34:01 marka Exp $ */ /* Reviewed: Thu Mar 16 13:39:43 PST 2000 by gson */ @@ -162,8 +162,10 @@ totext_any_tsig(ARGS_TOTEXT) { */ sigtime = ((isc_uint64_t)sr.base[0] << 40) | ((isc_uint64_t)sr.base[1] << 32) | - (sr.base[2] << 24) | (sr.base[3] << 16) | - (sr.base[4] << 8) | sr.base[5]; + ((isc_uint64_t)sr.base[2] << 24) | + ((isc_uint64_t)sr.base[3] << 16) | + ((isc_uint64_t)sr.base[4] << 8) | + (isc_uint64_t)sr.base[5]; isc_region_consume(&sr, 6); bufp = &buf[sizeof(buf) - 1]; *bufp-- = 0; @@ -457,8 +459,10 @@ tostruct_any_tsig(ARGS_TOSTRUCT) { INSIST(sr.length >= 6); tsig->timesigned = ((isc_uint64_t)sr.base[0] << 40) | ((isc_uint64_t)sr.base[1] << 32) | - (sr.base[2] << 24) | (sr.base[3] << 16) | - (sr.base[4] << 8) | sr.base[5]; + ((isc_uint64_t)sr.base[2] << 24) | + ((isc_uint64_t)sr.base[3] << 16) | + ((isc_uint64_t)sr.base[4] << 8) | + (isc_uint64_t)sr.base[5]; isc_region_consume(&sr, 6); /* diff --git a/usr.sbin/bind/lib/dns/rdata/generic/ds_43.c b/usr.sbin/bind/lib/dns/rdata/generic/ds_43.c index 807d5a4f38f..90724c87e1e 100644 --- a/usr.sbin/bind/lib/dns/rdata/generic/ds_43.c +++ b/usr.sbin/bind/lib/dns/rdata/generic/ds_43.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2002 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: ds_43.c,v 1.6.2.2 2004/03/16 12:38:14 marka Exp $ */ +/* $ISC: ds_43.c,v 1.6.2.4 2005/09/06 07:29:31 marka Exp $ */ /* draft-ietf-dnsext-delegation-signer-05.txt */ @@ -28,6 +28,7 @@ static inline isc_result_t fromtext_ds(ARGS_FROMTEXT) { isc_token_t token; + unsigned char c; REQUIRE(type == 43); @@ -49,11 +50,10 @@ fromtext_ds(ARGS_FROMTEXT) { /* * Algorithm. */ - RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, ISC_FALSE)); - if (token.value.as_ulong > 0xffU) - RETTOK(ISC_R_RANGE); - RETERR(uint8_tobuffer(token.value.as_ulong, target)); + RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &c, 1)); /* * Digest type. diff --git a/usr.sbin/bind/lib/dns/rdata/generic/rt_21.c b/usr.sbin/bind/lib/dns/rdata/generic/rt_21.c index 85e5764b9d3..4523dad9182 100644 --- a/usr.sbin/bind/lib/dns/rdata/generic/rt_21.c +++ b/usr.sbin/bind/lib/dns/rdata/generic/rt_21.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: rt_21.c,v 1.37.2.1.2.3 2004/03/06 08:14:11 marka Exp $ */ +/* $ISC: rt_21.c,v 1.37.2.1.2.5 2005/03/17 03:58:31 marka Exp $ */ /* reviewed: Thu Mar 16 15:02:31 PST 2000 by brister */ @@ -300,7 +300,7 @@ checknames_rt(ARGS_CHECKNAMES) { isc_region_consume(®ion, 2); dns_name_init(&name, NULL); dns_name_fromregion(&name, ®ion); - if (dns_name_ishostname(&name, ISC_FALSE)) { + if (!dns_name_ishostname(&name, ISC_FALSE)) { if (bad != NULL) dns_name_clone(&name, bad); return (ISC_FALSE); diff --git a/usr.sbin/bind/lib/dns/resolver.c b/usr.sbin/bind/lib/dns/resolver.c index 3644c606c7a..5c963917d24 100644 --- a/usr.sbin/bind/lib/dns/resolver.c +++ b/usr.sbin/bind/lib/dns/resolver.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: resolver.c,v 1.218.2.18.4.51 2005/02/08 23:59:44 marka Exp $ */ +/* $ISC: resolver.c,v 1.218.2.18.4.56 2005/10/14 01:38:48 marka Exp $ */ #include <config.h> @@ -244,6 +244,11 @@ struct fetchctx { #define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0) #define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0) +typedef struct { + dns_adbaddrinfo_t * addrinfo; + fetchctx_t * fctx; +} dns_valarg_t; + struct dns_fetch { unsigned int magic; fetchctx_t * private; @@ -342,6 +347,35 @@ static isc_result_t ncache_adderesult(dns_message_t *message, isc_stdtime_t now, dns_ttl_t maxttl, dns_rdataset_t *ardataset, isc_result_t *eresultp); +static void validated(isc_task_t *task, isc_event_t *event); + +static isc_result_t +valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name, + dns_rdatatype_t type, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, unsigned int valoptions, + isc_task_t *task) +{ + dns_validator_t *validator = NULL; + dns_valarg_t *valarg; + isc_result_t result; + + valarg = isc_mem_get(fctx->res->mctx, sizeof(*valarg)); + if (valarg == NULL) + return (ISC_R_NOMEMORY); + + valarg->fctx = fctx; + valarg->addrinfo = addrinfo; + + result = dns_validator_create(fctx->res->view, name, type, rdataset, + sigrdataset, fctx->rmessage, + valoptions, task, validated, valarg, + &validator); + if (result == ISC_R_SUCCESS) + ISC_LIST_APPEND(fctx->validators, validator, link); + else + isc_mem_put(fctx->res->mctx, valarg, sizeof(*valarg)); + return (result); +} static isc_boolean_t fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) { @@ -1424,6 +1458,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { case ISC_R_CONNREFUSED: case ISC_R_NOPERM: case ISC_R_ADDRNOTAVAIL: + case ISC_R_CONNECTIONRESET: /* * No route to remote. */ @@ -1855,7 +1890,6 @@ fctx_getaddresses(fetchctx_t *fctx) { isc_boolean_t pruned, all_bad; dns_rdata_ns_t ns; isc_boolean_t need_alternate = ISC_FALSE; - isc_boolean_t unshared; FCTXTRACE("getaddresses"); @@ -1871,7 +1905,6 @@ fctx_getaddresses(fetchctx_t *fctx) { res = fctx->res; pruned = ISC_FALSE; stdoptions = 0; /* Keep compiler happy. */ - unshared = ISC_TF((fctx->options | DNS_FETCHOPT_UNSHARED) != 0); /* * Forwarders. @@ -2668,7 +2701,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, isc_result_t result; isc_result_t iresult; isc_interval_t interval; - dns_fixedname_t qdomain; + dns_fixedname_t fixed; unsigned int findoptions = 0; char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE]; char typebuf[DNS_RDATATYPE_FORMATSIZE]; @@ -2747,8 +2780,10 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, dns_name_getlabelsequence(name, 1, labels - 1, &suffix); name = &suffix; } - result = dns_fwdtable_find(fctx->res->view->fwdtable, name, - &forwarders); + dns_fixedname_init(&fixed); + domain = dns_fixedname_name(&fixed); + result = dns_fwdtable_find2(fctx->res->view->fwdtable, name, + domain, &forwarders); if (result == ISC_R_SUCCESS) fctx->fwdpolicy = forwarders->fwdpolicy; @@ -2760,27 +2795,22 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, */ if (dns_rdatatype_atparent(type)) findoptions |= DNS_DBFIND_NOEXACT; - dns_fixedname_init(&qdomain); - result = dns_view_findzonecut(res->view, name, - dns_fixedname_name(&qdomain), 0, - findoptions, ISC_TRUE, + result = dns_view_findzonecut(res->view, name, domain, + 0, findoptions, ISC_TRUE, &fctx->nameservers, NULL); if (result != ISC_R_SUCCESS) goto cleanup_name; - result = dns_name_dup(dns_fixedname_name(&qdomain), - res->mctx, &fctx->domain); + result = dns_name_dup(domain, res->mctx, &fctx->domain); if (result != ISC_R_SUCCESS) { dns_rdataset_disassociate(&fctx->nameservers); goto cleanup_name; } } else { /* - * We're in forward-only mode. Set the query domain - * to ".". + * We're in forward-only mode. Set the query domain. */ - result = dns_name_dup(dns_rootname, res->mctx, - &fctx->domain); + result = dns_name_dup(domain, res->mctx, &fctx->domain); if (result != ISC_R_SUCCESS) goto cleanup_name; } @@ -3090,11 +3120,15 @@ validated(isc_task_t *task, isc_event_t *event) { dns_name_t *name; dns_rdataset_t *rdataset; dns_rdataset_t *sigrdataset; + dns_valarg_t *valarg; + dns_adbaddrinfo_t *addrinfo; UNUSED(task); /* for now */ REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE); - fctx = event->ev_arg; + valarg = event->ev_arg; + fctx = valarg->fctx; + addrinfo = valarg->addrinfo; REQUIRE(VALID_FCTX(fctx)); REQUIRE(!ISC_LIST_EMPTY(fctx->validators)); @@ -3109,6 +3143,7 @@ validated(isc_task_t *task, isc_event_t *event) { * destroy the fctx if necessary. */ dns_validator_destroy(&vevent->validator); + isc_mem_put(fctx->res->mctx, valarg, sizeof(*valarg)); negative = ISC_TF(vevent->rdataset == NULL); @@ -3166,21 +3201,27 @@ validated(isc_task_t *task, isc_event_t *event) { if (vevent->result != ISC_R_SUCCESS) { FCTXTRACE("validation failed"); - if (vevent->rdataset != NULL) { + result = ISC_R_NOTFOUND; + if (vevent->rdataset != NULL) result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node); - if (result != ISC_R_SUCCESS) - goto noanswer_response; + if (result == ISC_R_SUCCESS) (void)dns_db_deleterdataset(fctx->cache, node, NULL, vevent->type, 0); - if (vevent->sigrdataset != NULL) - (void)dns_db_deleterdataset(fctx->cache, - node, NULL, - dns_rdatatype_rrsig, - vevent->type); - } + if (result == ISC_R_SUCCESS && vevent->sigrdataset != NULL) + (void)dns_db_deleterdataset(fctx->cache, node, NULL, + dns_rdatatype_rrsig, + vevent->type); + if (result == ISC_R_SUCCESS) + dns_db_detachnode(fctx->cache, &node); result = vevent->result; - goto noanswer_response; + add_bad(fctx, &addrinfo->sockaddr, result); + isc_event_free(&event); + if (sentresponse) + fctx_done(fctx, result); + else + fctx_try(fctx); + return; } isc_stdtime_get(&now); @@ -3350,7 +3391,8 @@ validated(isc_task_t *task, isc_event_t *event) { } static inline isc_result_t -cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { +cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, + isc_stdtime_t now) { dns_rdataset_t *rdataset, *sigrdataset; dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset; dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL; @@ -3363,8 +3405,8 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { dns_fetchevent_t *event; unsigned int options; isc_task_t *task; - dns_validator_t *validator; isc_boolean_t fail; + unsigned int valoptions = 0; /* * The appropriate bucket lock must be held. @@ -3385,8 +3427,10 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { if (result != ISC_R_SUCCESS) return (result); - if (res->view->dlv != NULL) + if (!secure_domain && res->view->dlv != NULL) { + valoptions = DNS_VALIDATOR_DLV; secure_domain = ISC_TRUE; + } if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0) need_validation = ISC_FALSE; @@ -3437,7 +3481,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { /* * Cache or validate each cacheable rdataset. */ - fail = (fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0; + fail = ISC_TF((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0); for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { @@ -3569,23 +3613,11 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { * having to remember which * rdatasets needed validation. */ - validator = NULL; - result = dns_validator_create( - res->view, - name, - rdataset->type, - rdataset, - sigrdataset, - fctx->rmessage, - 0, - task, - validated, - fctx, - &validator); - if (result == ISC_R_SUCCESS) - ISC_LIST_APPEND( - fctx->validators, - validator, link); + result = valcreate(fctx, addrinfo, + name, rdataset->type, + rdataset, + sigrdataset, + valoptions, task); } } else if (CHAINING(rdataset)) { if (rdataset->type == dns_rdatatype_cname) @@ -3660,22 +3692,10 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { } } - if (valrdataset != NULL) { - validator = NULL; - result = dns_validator_create(res->view, - name, - fctx->type, - valrdataset, - valsigrdataset, - fctx->rmessage, - 0, - task, - validated, - fctx, - &validator); - if (result == ISC_R_SUCCESS) - ISC_LIST_APPEND(fctx->validators, validator, link); - } + if (valrdataset != NULL) + result = valcreate(fctx, addrinfo, name, fctx->type, + valrdataset, valsigrdataset, valoptions, + task); if (result == ISC_R_SUCCESS && have_answer) { fctx->attributes |= FCTX_ATTR_HAVEANSWER; @@ -3695,7 +3715,8 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { } static inline isc_result_t -cache_message(fetchctx_t *fctx, isc_stdtime_t now) { +cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now) +{ isc_result_t result; dns_section_t section; dns_name_t *name; @@ -3715,7 +3736,7 @@ cache_message(fetchctx_t *fctx, isc_stdtime_t now) { dns_message_currentname(fctx->rmessage, section, &name); if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) { - result = cache_name(fctx, name, now); + result = cache_name(fctx, name, addrinfo, now); if (result != ISC_R_SUCCESS) break; } @@ -3783,7 +3804,9 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, } static inline isc_result_t -ncache_message(fetchctx_t *fctx, dns_rdatatype_t covers, isc_stdtime_t now) { +ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, + dns_rdatatype_t covers, isc_stdtime_t now) +{ isc_result_t result, eresult; dns_name_t *name; dns_resolver_t *res; @@ -3794,6 +3817,7 @@ ncache_message(fetchctx_t *fctx, dns_rdatatype_t covers, isc_stdtime_t now) { dns_name_t *aname; dns_fetchevent_t *event; isc_uint32_t ttl; + unsigned int valoptions = 0; FCTXTRACE("ncache_message"); @@ -3820,8 +3844,10 @@ ncache_message(fetchctx_t *fctx, dns_rdatatype_t covers, isc_stdtime_t now) { if (result != ISC_R_SUCCESS) return (result); - if (res->view->dlv != NULL) + if (!secure_domain && res->view->dlv != NULL) { + valoptions = DNS_VALIDATOR_DLV; secure_domain = ISC_TRUE; + } if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0) need_validation = ISC_FALSE; @@ -3858,23 +3884,15 @@ ncache_message(fetchctx_t *fctx, dns_rdatatype_t covers, isc_stdtime_t now) { /* * Do negative response validation. */ - dns_validator_t *validator = NULL; - isc_task_t *task = res->buckets[fctx->bucketnum].task; - - result = dns_validator_create(res->view, name, fctx->type, - NULL, NULL, - fctx->rmessage, 0, task, - validated, fctx, - &validator); - if (result != ISC_R_SUCCESS) - return (result); - ISC_LIST_APPEND(fctx->validators, validator, link); + result = valcreate(fctx, addrinfo, name, fctx->type, + NULL, NULL, valoptions, + res->buckets[fctx->bucketnum].task); /* * If validation is necessary, return now. Otherwise continue * to process the message, letting the validation complete * in its own good time. */ - return (ISC_R_SUCCESS); + return (result); } LOCK(&res->buckets[fctx->bucketnum].lock); @@ -4992,6 +5010,43 @@ checknames(dns_message_t *message) { } static void +log_packet(dns_message_t *message, int level, isc_mem_t *mctx) { + isc_buffer_t buffer; + char *buf = NULL; + int len = 1024; + isc_result_t result; + + if (! isc_log_wouldlog(dns_lctx, level)) + return; + + /* + * Note that these are multiline debug messages. We want a newline + * to appear in the log after each message. + */ + + do { + buf = isc_mem_get(mctx, len); + if (buf == NULL) + break; + isc_buffer_init(&buffer, buf, len); + result = dns_message_totext(message, &dns_master_style_debug, + 0, &buffer); + if (result == ISC_R_NOSPACE) { + isc_mem_put(mctx, buf, len); + len += 1024; + } else if (result == ISC_R_SUCCESS) + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, level, + "received packet:\n%.*s", + (int)isc_buffer_usedlength(&buffer), + buf); + } while (result == ISC_R_NOSPACE); + + if (buf != NULL) + isc_mem_put(mctx, buf, len); +} + +static void resquery_response(isc_task_t *task, isc_event_t *event) { isc_result_t result = ISC_R_SUCCESS; resquery_t *query = event->ev_arg; @@ -5160,6 +5215,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) { } /* + * Log the incoming packet. + */ + log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx); + + /* * If the message is signed, check the signature. If not, this * returns success anyway. */ @@ -5427,7 +5487,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { * work to be queued to the DNSSEC validator. */ if (WANTCACHE(fctx)) { - result = cache_message(fctx, now); + result = cache_message(fctx, query->addrinfo, now); if (result != ISC_R_SUCCESS) goto done; } @@ -5446,7 +5506,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { /* * Cache any negative cache entries in the message. */ - result = ncache_message(fctx, covers, now); + result = ncache_message(fctx, query->addrinfo, covers, now); } done: diff --git a/usr.sbin/bind/lib/dns/tsig.c b/usr.sbin/bind/lib/dns/tsig.c index 3e4db83633f..1428497e13e 100644 --- a/usr.sbin/bind/lib/dns/tsig.c +++ b/usr.sbin/bind/lib/dns/tsig.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -16,7 +16,7 @@ */ /* - * $ISC: tsig.c,v 1.112.2.3.8.4 2004/03/08 09:04:32 marka Exp $ + * $ISC: tsig.c,v 1.112.2.3.8.6 2005/03/17 03:58:31 marka Exp $ */ #include <config.h> @@ -167,7 +167,7 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, goto cleanup_name; } } else { - if (key != NULL) { + if (dstkey != NULL) { ret = DNS_R_BADALG; goto cleanup_name; } diff --git a/usr.sbin/bind/lib/dns/validator.c b/usr.sbin/bind/lib/dns/validator.c index 7a5f87c1db7..17709ffa4f2 100644 --- a/usr.sbin/bind/lib/dns/validator.c +++ b/usr.sbin/bind/lib/dns/validator.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: validator.c,v 1.91.2.5.8.15 2005/02/09 05:13:02 marka Exp $ */ +/* $ISC: validator.c,v 1.91.2.5.8.21 2005/11/02 02:07:47 marka Exp $ */ #include <config.h> @@ -51,9 +51,7 @@ #define VALATTR_TRIEDVERIFY 0x0004 #define VALATTR_NEGATIVE 0x0008 #define VALATTR_INSECURITY 0x0010 -#define VALATTR_DLV 0x0020 -#define VALATTR_DLVTRIED 0x0040 -#define VALATTR_DLVSEPTRIED 0x0080 +#define VALATTR_DLVTRIED 0x0020 #define VALATTR_NEEDNOQNAME 0x0100 #define VALATTR_NEEDNOWILDCARD 0x0200 @@ -63,13 +61,10 @@ #define VALATTR_FOUNDNOWILDCARD 0x2000 #define VALATTR_FOUNDNODATA 0x4000 - #define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0) #define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0) #define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0) -#define DLV(val) ((val->attributes & VALATTR_DLV) != 0) #define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0) -#define DLVSEPTRIED(val) ((val->attributes & VALATTR_DLVSEPTRIED) != 0) #define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0) @@ -110,8 +105,20 @@ static isc_result_t dlv_validatezonekey(dns_validator_t *val); static isc_result_t +dlv_validator_start(dns_validator_t *val); + +static isc_result_t finddlvsep(dns_validator_t *val, isc_boolean_t resume); +static inline void +markanswer(dns_validator_t *val) { + validator_log(val, ISC_LOG_DEBUG(3), "marking as answer"); + if (val->event->rdataset) + val->event->rdataset->trust = dns_trust_answer; + if (val->event->sigrdataset) + val->event->sigrdataset->trust = dns_trust_answer; +} + static void validator_done(dns_validator_t *val, isc_result_t result) { isc_task_t *task; @@ -219,6 +226,13 @@ fetch_callback_validator(isc_task_t *task, isc_event_t *event) { rdataset = &val->frdataset; eresult = devent->result; + /* Free resources which are not of interest. */ + if (devent->node != NULL) + dns_db_detachnode(devent->db, &devent->node); + if (devent->db != NULL) + dns_db_detach(&devent->db); + if (dns_rdataset_isassociated(&val->fsigrdataset)) + dns_rdataset_disassociate(&val->fsigrdataset); isc_event_free(&event); dns_resolver_destroyfetch(&val->fetch); @@ -271,6 +285,13 @@ dsfetched(isc_task_t *task, isc_event_t *event) { rdataset = &val->frdataset; eresult = devent->result; + /* Free resources which are not of interest. */ + if (devent->node != NULL) + dns_db_detachnode(devent->db, &devent->node); + if (devent->db != NULL) + dns_db_detach(&devent->db); + if (dns_rdataset_isassociated(&val->fsigrdataset)) + dns_rdataset_disassociate(&val->fsigrdataset); isc_event_free(&event); dns_resolver_destroyfetch(&val->fetch); @@ -285,18 +306,6 @@ dsfetched(isc_task_t *task, isc_event_t *event) { result = validatezonekey(val); if (result != DNS_R_WAIT) validator_done(val, result); - } else if (val->view->dlv != NULL && !DLVTRIED(val) && - (eresult == DNS_R_NXRRSET || - eresult == DNS_R_NCACHENXRRSET) && - !dns_name_issubdomain(val->event->name, - val->view->dlv)) - { - validator_log(val, ISC_LOG_DEBUG(2), - "no DS record: looking for DLV"); - - result = dlv_validatezonekey(val); - if (result != DNS_R_WAIT) - validator_done(val, result); } else if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET) { @@ -328,7 +337,6 @@ static void dsfetched2(isc_task_t *task, isc_event_t *event) { dns_fetchevent_t *devent; dns_validator_t *val; - dns_rdataset_t *rdataset; dns_name_t *tname; isc_boolean_t want_destroy; isc_result_t result; @@ -338,9 +346,15 @@ dsfetched2(isc_task_t *task, isc_event_t *event) { INSIST(event->ev_type == DNS_EVENT_FETCHDONE); devent = (dns_fetchevent_t *)event; val = devent->ev_arg; - rdataset = &val->frdataset; eresult = devent->result; + /* Free resources which are not of interest. */ + if (devent->node != NULL) + dns_db_detachnode(devent->db, &devent->node); + if (devent->db != NULL) + dns_db_detach(&devent->db); + if (dns_rdataset_isassociated(&val->fsigrdataset)) + dns_rdataset_disassociate(&val->fsigrdataset); dns_resolver_destroyfetch(&val->fetch); INSIST(val->event != NULL); @@ -358,7 +372,7 @@ dsfetched2(isc_task_t *task, isc_event_t *event) { "must be secure failure"); validator_done(val, DNS_R_MUSTBESECURE); } else { - val->event->rdataset->trust = dns_trust_answer; + markanswer(val); validator_done(val, ISC_R_SUCCESS); } } else { @@ -553,7 +567,7 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname, "nsec proves name exists (owner) data=%d", *data); return (ISC_R_SUCCESS); - } + } if (relation == dns_namereln_subdomain && dns_nsec_typepresent(&rdata, dns_rdatatype_ns) && @@ -627,7 +641,7 @@ static void authvalidated(isc_task_t *task, isc_event_t *event) { dns_validatorevent_t *devent; dns_validator_t *val; - dns_rdataset_t *rdataset, *sigrdataset; + dns_rdataset_t *rdataset; isc_boolean_t want_destroy; isc_result_t result; isc_boolean_t exists, data; @@ -637,7 +651,6 @@ authvalidated(isc_task_t *task, isc_event_t *event) { devent = (dns_validatorevent_t *)event; rdataset = devent->rdataset; - sigrdataset = devent->sigrdataset; val = devent->ev_arg; result = devent->result; dns_validator_destroy(&val->subvalidator); @@ -916,8 +929,10 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, rdataset, sigrdataset, NULL, 0, val->task, action, val, &val->subvalidator); - if (result == ISC_R_SUCCESS) + if (result == ISC_R_SUCCESS) { val->subvalidator->parent = val; + val->subvalidator->depth = val->depth + 1; + } return (result); } @@ -1252,10 +1267,7 @@ validate(dns_validator_t *val, isc_boolean_t resume) { "must be secure failure"); return (DNS_R_MUSTBESECURE); } - event->rdataset->trust = dns_trust_answer; - event->sigrdataset->trust = dns_trust_answer; - validator_log(val, ISC_LOG_DEBUG(3), - "marking as answer"); + markanswer(val); return (ISC_R_SUCCESS); } @@ -1344,110 +1356,9 @@ validate(dns_validator_t *val, isc_boolean_t resume) { return (DNS_R_NOVALIDSIG); } - -static void -dlv_validated(isc_task_t *task, isc_event_t *event) { - dns_validatorevent_t *devent; - dns_validator_t *val; - isc_boolean_t want_destroy; - isc_result_t result; - isc_result_t eresult; - - UNUSED(task); - INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE); - - devent = (dns_validatorevent_t *)event; - val = devent->ev_arg; - eresult = devent->result; - - isc_event_free(&event); - dns_validator_destroy(&val->subvalidator); - - INSIST(val->event != NULL); - - validator_log(val, ISC_LOG_DEBUG(3), "in dsvalidated"); - LOCK(&val->lock); - if (eresult == ISC_R_SUCCESS) { - validator_log(val, ISC_LOG_DEBUG(3), - "dlv with trust %d", val->frdataset.trust); - if ((val->attributes & VALATTR_INSECURITY) != 0) - result = proveunsecure(val, ISC_TRUE); - else - result = validatezonekey(val); - if (result != DNS_R_WAIT) - validator_done(val, result); - } else { - validator_log(val, ISC_LOG_DEBUG(3), - "dlv_validated: got %s", - isc_result_totext(eresult)); - validator_done(val, eresult); - } - want_destroy = exit_check(val); - UNLOCK(&val->lock); - if (want_destroy) - destroy(val); -} - -static void -dlv_fetched(isc_task_t *task, isc_event_t *event) { - dns_fetchevent_t *devent; - dns_validator_t *val; - dns_rdataset_t *rdataset; - isc_boolean_t want_destroy; - isc_result_t result; - isc_result_t eresult; - - UNUSED(task); - INSIST(event->ev_type == DNS_EVENT_FETCHDONE); - devent = (dns_fetchevent_t *)event; - val = devent->ev_arg; - rdataset = &val->frdataset; - eresult = devent->result; - - isc_event_free(&event); - dns_resolver_destroyfetch(&val->fetch); - - INSIST(val->event != NULL); - - validator_log(val, ISC_LOG_DEBUG(3), "in dlv_fetched"); - LOCK(&val->lock); - if (eresult == ISC_R_SUCCESS) { - validator_log(val, ISC_LOG_DEBUG(3), - "dlv set with trust %d", rdataset->trust); - val->dlv = &val->frdataset; - result = dlv_validatezonekey(val); - if (result != DNS_R_WAIT) - validator_done(val, result); - } else if (eresult == DNS_R_NXRRSET || - eresult == DNS_R_NCACHENXRRSET) - { - validator_log(val, ISC_LOG_DEBUG(3), - "falling back to insecurity proof"); - val->attributes |= VALATTR_INSECURITY; - result = proveunsecure(val, ISC_FALSE); - if (result != DNS_R_WAIT) - validator_done(val, result); - } else { - validator_log(val, ISC_LOG_DEBUG(3), - "dlv_fetched: got %s", - isc_result_totext(eresult)); - if (eresult == ISC_R_CANCELED) - validator_done(val, eresult); - else - validator_done(val, DNS_R_NOVALIDDS); - } - want_destroy = exit_check(val); - UNLOCK(&val->lock); - if (want_destroy) - destroy(val); -} - static isc_result_t dlv_validatezonekey(dns_validator_t *val) { - dns_fixedname_t fixed; dns_keytag_t keytag; - dns_name_t *name; - dns_name_t tname; dns_rdata_dlv_t dlv; dns_rdata_dnskey_t key; dns_rdata_rrsig_t sig; @@ -1460,91 +1371,8 @@ dlv_validatezonekey(dns_validator_t *val) { isc_boolean_t supported_algorithm; isc_result_t result; unsigned char dsbuf[DNS_DS_BUFFERSIZE]; - unsigned int labels; - - val->attributes |= VALATTR_DLVTRIED; - - dns_name_init(&tname, NULL); - dns_fixedname_init(&fixed); - name = dns_fixedname_name(&fixed); - labels = dns_name_countlabels(val->event->name); - dns_name_getlabelsequence(val->event->name, 0, labels - 1, &tname); - result = dns_name_concatenate(&tname, val->view->dlv, name, NULL); - if (result != ISC_R_SUCCESS) { - validator_log(val, ISC_LOG_DEBUG(2), - "DLV concatenate failed"); - return (DNS_R_NOVALIDSIG); - } - if (val->dlv == NULL) { - result = view_find(val, name, dns_rdatatype_dlv); - if (result == ISC_R_SUCCESS) { - /* - * We have DLV records. - */ - val->dsset = &val->frdataset; - if (val->frdataset.trust == dns_trust_pending && - dns_rdataset_isassociated(&val->fsigrdataset)) - { - result = create_validator(val, - val->event->name, - dns_rdatatype_ds, - &val->frdataset, - &val->fsigrdataset, - dlv_validated, - "dlv_validatezonekey"); - if (result != ISC_R_SUCCESS) - return (result); - return (DNS_R_WAIT); - } else if (val->frdataset.trust == dns_trust_pending) { - /* - * There should never be an unsigned DLV. - */ - dns_rdataset_disassociate(&val->frdataset); - validator_log(val, ISC_LOG_DEBUG(2), - "unsigned DLV record"); - return (DNS_R_NOVALIDSIG); - } else - result = ISC_R_SUCCESS; - } else if (result == ISC_R_NOTFOUND) { - result = create_fetch(val, name, dns_rdatatype_dlv, - dlv_fetched, - "dlv_validatezonekey"); - if (result != ISC_R_SUCCESS) - return (result); - return (DNS_R_WAIT); - } else if (result == DNS_R_NCACHENXDOMAIN || - result == DNS_R_NCACHENXRRSET || - result == DNS_R_NXDOMAIN || - result == DNS_R_NXRRSET) - { - /* - * The DS does not exist. - */ - if (dns_rdataset_isassociated(&val->frdataset)) - dns_rdataset_disassociate(&val->frdataset); - if (dns_rdataset_isassociated(&val->fsigrdataset)) - dns_rdataset_disassociate(&val->fsigrdataset); - validator_log(val, ISC_LOG_DEBUG(2), "no DLV record"); - return (DNS_R_NOVALIDSIG); - } - } - - /* - * We have a DLV set. - */ - INSIST(val->dlv != NULL); - - if (val->dlv->trust < dns_trust_secure) { - if (val->mustbesecure) { - validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); - return (DNS_R_MUSTBESECURE); - } - val->event->rdataset->trust = dns_trust_answer; - val->event->sigrdataset->trust = dns_trust_answer; - return (ISC_R_SUCCESS); - } + validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey"); /* * Look through the DLV record and find the keys that can sign the * key set and the matching signature. For each such key, attempt @@ -1553,15 +1381,16 @@ dlv_validatezonekey(dns_validator_t *val) { supported_algorithm = ISC_FALSE; - for (result = dns_rdataset_first(val->dlv); + for (result = dns_rdataset_first(&val->dlv); result == ISC_R_SUCCESS; - result = dns_rdataset_next(val->dlv)) + result = dns_rdataset_next(&val->dlv)) { dns_rdata_reset(&dlvrdata); - dns_rdataset_current(val->dlv, &dlvrdata); + dns_rdataset_current(&val->dlv, &dlvrdata); (void)dns_rdata_tostruct(&dlvrdata, &dlv, NULL); - if (!dns_resolver_algorithm_supported(val->view->resolver, + if (dlv.digest_type != DNS_DSDIGEST_SHA1 || + !dns_resolver_algorithm_supported(val->view->resolver, val->event->name, dlv.algorithm)) continue; @@ -1586,8 +1415,12 @@ dlv_validatezonekey(dns_validator_t *val) { result = dns_ds_buildrdata(val->event->name, &keyrdata, dlv.digest_type, dsbuf, &newdsrdata); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + validator_log(val, ISC_LOG_DEBUG(3), + "dns_ds_buildrdata() -> %s", + dns_result_totext(result)); continue; + } /* Covert to DLV */ newdsrdata.type = dns_rdatatype_dlv; if (dns_rdata_compare(&dlvrdata, &newdsrdata) == 0) @@ -1598,7 +1431,9 @@ dlv_validatezonekey(dns_validator_t *val) { "no DNSKEY matching DLV"); continue; } - + validator_log(val, ISC_LOG_DEBUG(3), + "Found matching DLV record: checking for signature"); + for (result = dns_rdataset_first(val->event->sigrdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(val->event->sigrdataset)) @@ -1610,7 +1445,6 @@ dlv_validatezonekey(dns_validator_t *val) { if (dlv.key_tag != sig.keyid && dlv.algorithm != sig.algorithm) continue; - dstkey = NULL; result = dns_dnssec_keyfromrdata(val->event->name, &keyrdata, @@ -1644,10 +1478,9 @@ dlv_validatezonekey(dns_validator_t *val) { "must be secure failure"); return (DNS_R_MUSTBESECURE); } - val->event->rdataset->trust = dns_trust_answer; - val->event->sigrdataset->trust = dns_trust_answer; validator_log(val, ISC_LOG_DEBUG(3), - "no supported algorithm (dlv)"); + "no supported algorithm/digest (dlv)"); + markanswer(val); return (ISC_R_SUCCESS); } else return (DNS_R_NOVALIDSIG); @@ -1685,6 +1518,10 @@ validatezonekey(dns_validator_t *val) { event = val->event; + if (val->havedlvsep && val->dlv.trust >= dns_trust_secure && + dns_name_equal(event->name, dns_fixedname_name(&val->dlvsep))) + return (dlv_validatezonekey(val)); + if (val->dsset == NULL) { /* * First, see if this key was signed by a trusted key. @@ -1783,22 +1620,6 @@ validatezonekey(dns_validator_t *val) { if (result != ISC_R_SUCCESS) return (result); return (DNS_R_WAIT); - } else if (val->view->dlv != NULL && !DLVTRIED(val) && - (result == DNS_R_NCACHENXRRSET || - result == DNS_R_NXRRSET) && - !dns_name_issubdomain(val->event->name, - val->view->dlv)) - { - - if (dns_rdataset_isassociated(&val->frdataset)) - dns_rdataset_disassociate(&val->frdataset); - if (dns_rdataset_isassociated(&val->fsigrdataset)) - dns_rdataset_disassociate(&val->fsigrdataset); - - validator_log(val, ISC_LOG_DEBUG(2), - "no DS record: looking for DLV"); - - return (dlv_validatezonekey(val)); } else if (result == DNS_R_NCACHENXDOMAIN || result == DNS_R_NCACHENXRRSET || result == DNS_R_NXDOMAIN || @@ -1827,8 +1648,7 @@ validatezonekey(dns_validator_t *val) { "must be secure failure"); return (DNS_R_MUSTBESECURE); } - val->event->rdataset->trust = dns_trust_answer; - val->event->sigrdataset->trust = dns_trust_answer; + markanswer(val); return (ISC_R_SUCCESS); } @@ -1848,6 +1668,8 @@ validatezonekey(dns_validator_t *val) { dns_rdataset_current(val->dsset, &dsrdata); (void)dns_rdata_tostruct(&dsrdata, &ds, NULL); + if (ds.digest_type != DNS_DSDIGEST_SHA1) + continue; if (!dns_resolver_algorithm_supported(val->view->resolver, val->event->name, ds.algorithm)) @@ -1923,24 +1745,15 @@ validatezonekey(dns_validator_t *val) { event->sigrdataset->trust = dns_trust_secure; validator_log(val, ISC_LOG_DEBUG(3), "marking as secure"); return (result); - } else if (result == ISC_R_NOMORE && val->view->dlv != NULL && - !DLVTRIED(val) && !dns_name_issubdomain(val->event->name, - val->view->dlv)) - { - validator_log(val, ISC_LOG_DEBUG(2), - "no DS/DNSKEY pair: looking for DLV"); - - return (dlv_validatezonekey(val)); } else if (result == ISC_R_NOMORE && !supported_algorithm) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, "must be secure failure"); return (DNS_R_MUSTBESECURE); } - val->event->rdataset->trust = dns_trust_answer; - val->event->sigrdataset->trust = dns_trust_answer; validator_log(val, ISC_LOG_DEBUG(3), - "no supported algorithm (ds)"); + "no supported algorithm/digest (DS)"); + markanswer(val); return (ISC_R_SUCCESS); } else return (DNS_R_NOVALIDSIG); @@ -2174,7 +1987,8 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) { if ((val->attributes & VALATTR_FOUNDNONEXISTENCE) == 0) { if (!val->seensig && val->soaset != NULL) { - result = create_validator(val, name, dns_rdatatype_soa, + result = create_validator(val, val->soaname, + dns_rdatatype_soa, val->soaset, NULL, negauthvalidated, "nsecvalidate"); @@ -2193,8 +2007,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) { } static isc_boolean_t -check_ds_algorithm(dns_validator_t *val, dns_name_t *name, - dns_rdataset_t *rdataset) { +check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) { dns_rdata_t dsrdata = DNS_RDATA_INIT; dns_rdata_ds_t ds; isc_result_t result; @@ -2205,16 +2018,20 @@ check_ds_algorithm(dns_validator_t *val, dns_name_t *name, dns_rdataset_current(rdataset, &dsrdata); (void)dns_rdata_tostruct(&dsrdata, &ds, NULL); - if (dns_resolver_algorithm_supported(val->view->resolver, - name, ds.algorithm)) + if (ds.digest_type == DNS_DSDIGEST_SHA1 && + dns_resolver_algorithm_supported(val->view->resolver, + name, ds.algorithm)) { + dns_rdata_reset(&dsrdata); return (ISC_TRUE); + } dns_rdata_reset(&dsrdata); } return (ISC_FALSE); } static void -dlv_fetched2(isc_task_t *task, isc_event_t *event) { +dlvfetched(isc_task_t *task, isc_event_t *event) { + char namebuf[DNS_NAME_FORMATSIZE]; dns_fetchevent_t *devent; dns_validator_t *val; isc_boolean_t want_destroy; @@ -2226,18 +2043,29 @@ dlv_fetched2(isc_task_t *task, isc_event_t *event) { devent = (dns_fetchevent_t *)event; val = devent->ev_arg; eresult = devent->result; - + + /* Free resources which are not of interest. */ + if (devent->node != NULL) + dns_db_detachnode(devent->db, &devent->node); + if (devent->db != NULL) + dns_db_detach(&devent->db); + if (dns_rdataset_isassociated(&val->fsigrdataset)) + dns_rdataset_disassociate(&val->fsigrdataset); isc_event_free(&event); dns_resolver_destroyfetch(&val->fetch); - + INSIST(val->event != NULL); - validator_log(val, ISC_LOG_DEBUG(3), "in dlv_fetched2: %s", + validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s", dns_result_totext(eresult)); LOCK(&val->lock); if (eresult == ISC_R_SUCCESS) { + dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf, + sizeof(namebuf)); + dns_rdataset_clone(&val->frdataset, &val->dlv); val->havedlvsep = ISC_TRUE; - result = proveunsecure(val, ISC_FALSE); + validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf); + result = dlv_validator_start(val); if (result != DNS_R_WAIT) validator_done(val, result); } else if (eresult == DNS_R_NXRRSET || @@ -2246,13 +2074,26 @@ dlv_fetched2(isc_task_t *task, isc_event_t *event) { eresult == DNS_R_NCACHENXDOMAIN) { result = finddlvsep(val, ISC_TRUE); if (result == ISC_R_SUCCESS) { - result = proveunsecure(val, ISC_FALSE); + dns_name_format(dns_fixedname_name(&val->dlvsep), + namebuf, sizeof(namebuf)); + validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", + namebuf); + result = dlv_validator_start(val); if (result != DNS_R_WAIT) validator_done(val, result); } else if (result == ISC_R_NOTFOUND) { + validator_log(val, ISC_LOG_DEBUG(3), "DLV not found"); + markanswer(val); validator_done(val, ISC_R_SUCCESS); - } else if (result != DNS_R_WAIT) - validator_done(val, result); + } else { + validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s", + dns_result_totext(result)); + if (result != DNS_R_WAIT) + validator_done(val, result); + } + } else { + validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s", + dns_result_totext(eresult)); } want_destroy = exit_check(val); UNLOCK(&val->lock); @@ -2261,19 +2102,72 @@ dlv_fetched2(isc_task_t *task, isc_event_t *event) { } static isc_result_t +startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) { + char namebuf[DNS_NAME_FORMATSIZE]; + isc_result_t result; + + INSIST(!DLVTRIED(val)); + + val->attributes |= VALATTR_DLVTRIED; + + dns_name_format(unsecure, namebuf, sizeof(namebuf)); + validator_log(val, ISC_LOG_DEBUG(3), + "plain DNSSEC returns unsecure (%s): looking for DLV", + namebuf); + + if (dns_name_issubdomain(val->event->name, val->view->dlv)) { + validator_log(val, ISC_LOG_WARNING, "must be secure failure"); + return (DNS_R_MUSTBESECURE); + } + + val->dlvlabels = dns_name_countlabels(unsecure) - 1; + result = finddlvsep(val, ISC_FALSE); + if (result == ISC_R_NOTFOUND) { + validator_log(val, ISC_LOG_DEBUG(3), "DLV not found"); + markanswer(val); + return (ISC_R_SUCCESS); + } + if (result != ISC_R_SUCCESS) { + validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s", + dns_result_totext(result)); + return (result); + } + dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf, + sizeof(namebuf)); + validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf); + return (dlv_validator_start(val)); +} + +static isc_result_t finddlvsep(dns_validator_t *val, isc_boolean_t resume) { + char namebuf[DNS_NAME_FORMATSIZE]; dns_fixedname_t dlvfixed; dns_name_t *dlvname; dns_name_t *dlvsep; dns_name_t noroot; isc_result_t result; unsigned int labels; + + INSIST(val->view->dlv != NULL); if (!resume) { + + if (dns_name_issubdomain(val->event->name, val->view->dlv)) { + validator_log(val, ISC_LOG_WARNING, + "must be secure failure"); + return (DNS_R_MUSTBESECURE); + } + dns_fixedname_init(&val->dlvsep); dlvsep = dns_fixedname_name(&val->dlvsep); dns_name_copy(val->event->name, dlvsep, NULL); - val->attributes |= VALATTR_DLVSEPTRIED; + if (val->event->type == dns_rdatatype_ds) { + labels = dns_name_countlabels(dlvsep); + if (labels == 0) + return (ISC_R_NOTFOUND); + dns_name_getlabelsequence(dlvsep, 1, labels - 1, + dlvsep); + } } else { dlvsep = dns_fixedname_name(&val->dlvsep); labels = dns_name_countlabels(dlvsep); @@ -2283,6 +2177,8 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) { dns_fixedname_init(&dlvfixed); dlvname = dns_fixedname_name(&dlvfixed); labels = dns_name_countlabels(dlvsep); + if (labels == 0) + return (ISC_R_NOTFOUND); dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot); result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL); while (result == ISC_R_NOSPACE) { @@ -2297,32 +2193,37 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) { return (DNS_R_NOVALIDSIG); } - while (dns_name_countlabels(dlvname) > - dns_name_countlabels(val->view->dlv)) - { + while (dns_name_countlabels(dlvname) >= + dns_name_countlabels(val->view->dlv) + val->dlvlabels) { + dns_name_format(dlvname, namebuf, sizeof(namebuf)); + validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s", + namebuf); result = view_find(val, dlvname, dns_rdatatype_dlv); if (result == ISC_R_SUCCESS) { if (val->frdataset.trust < dns_trust_secure) return (DNS_R_NOVALIDSIG); val->havedlvsep = ISC_TRUE; + dns_rdataset_clone(&val->frdataset, &val->dlv); return (ISC_R_SUCCESS); } if (result == ISC_R_NOTFOUND) { - result = create_fetch(val, dlvname, dns_rdatatype_dlv, - dlv_fetched2, "finddlvsep"); - if (result != ISC_R_SUCCESS) - return (result); - return (DNS_R_WAIT); + result = create_fetch(val, dlvname, dns_rdatatype_dlv, + dlvfetched, "finddlvsep"); + if (result != ISC_R_SUCCESS) + return (result); + return (DNS_R_WAIT); } if (result != DNS_R_NXRRSET && result != DNS_R_NXDOMAIN && result != DNS_R_NCACHENXRRSET && - result != DNS_R_NCACHENXDOMAIN) + result != DNS_R_NCACHENXDOMAIN) return (result); /* * Strip first labels from both dlvsep and dlvname. */ labels = dns_name_countlabels(dlvsep); + if (labels == 0) + break; dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep); labels = dns_name_countlabels(dlvname); dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname); @@ -2330,73 +2231,76 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) { return (ISC_R_NOTFOUND); } +/* + * proveunsecure walks down from the SEP looking for a break in the + * chain of trust. That occurs when we can prove the DS record does + * not exist at a delegation point or the DS exists at a delegation + * but we don't support the algorithm/digest. + */ static isc_result_t proveunsecure(dns_validator_t *val, isc_boolean_t resume) { isc_result_t result; - isc_result_t tresult; - dns_fixedname_t secroot; + dns_fixedname_t fixedsecroot; + dns_name_t *secroot; dns_name_t *tname; + char namebuf[DNS_NAME_FORMATSIZE]; - dns_fixedname_init(&secroot); - result = dns_keytable_finddeepestmatch(val->keytable, - val->event->name, - dns_fixedname_name(&secroot)); - /* - * If the name is not under a security root, it must be insecure. - */ - if (val->view->dlv != NULL && !DLVSEPTRIED(val) && - !dns_name_issubdomain(val->event->name, val->view->dlv)) { - tresult = finddlvsep(val, ISC_FALSE); - if (tresult != ISC_R_NOTFOUND && tresult != ISC_R_SUCCESS) { - validator_log(val, ISC_LOG_DEBUG(3), - "finddlvsep returned: %s", - dns_result_totext(tresult)); - return (tresult); - } - } + dns_fixedname_init(&fixedsecroot); + secroot = dns_fixedname_name(&fixedsecroot); + if (val->havedlvsep) + dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL); + else { + result = dns_keytable_finddeepestmatch(val->keytable, + val->event->name, + secroot); - if (result == ISC_R_NOTFOUND) { - if (!val->havedlvsep) { + if (result == ISC_R_NOTFOUND) { validator_log(val, ISC_LOG_DEBUG(3), - "not beneath secure root / DLV"); + "not beneath secure root"); if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, "must be secure failure"); result = DNS_R_MUSTBESECURE; goto out; } - val->event->rdataset->trust = dns_trust_answer; - return (ISC_R_SUCCESS); - } - dns_name_copy(dns_fixedname_name(&val->dlvsep), - dns_fixedname_name(&secroot), NULL); - } else if (result != ISC_R_SUCCESS) - return (result); - else if (val->havedlvsep && - dns_name_issubdomain(dns_fixedname_name(&val->dlvsep), - dns_fixedname_name(&secroot))) { - dns_name_copy(dns_fixedname_name(&val->dlvsep), - dns_fixedname_name(&secroot), NULL); + if (val->view->dlv == NULL || DLVTRIED(val)) { + markanswer(val); + return (ISC_R_SUCCESS); + } + return (startfinddlvsep(val, dns_rootname)); + } else if (result != ISC_R_SUCCESS) + return (result); } if (!resume) { - val->labels = - dns_name_countlabels(dns_fixedname_name(&secroot)) + 1; + /* + * We are looking for breaks below the SEP so add a label. + */ + val->labels = dns_name_countlabels(secroot) + 1; } else { validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure"); if (val->frdataset.trust >= dns_trust_secure && - !check_ds_algorithm(val, dns_fixedname_name(&val->fname), - &val->frdataset)) { + !check_ds(val, dns_fixedname_name(&val->fname), + &val->frdataset)) { + dns_name_format(dns_fixedname_name(&val->fname), + namebuf, sizeof(namebuf)); if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, - "must be secure failure"); + "must be secure failure at '%s'", + namebuf); result = DNS_R_MUSTBESECURE; goto out; } validator_log(val, ISC_LOG_DEBUG(3), - "no supported algorithm (ds)"); - val->event->rdataset->trust = dns_trust_answer; - result = ISC_R_SUCCESS; + "no supported algorithm/digest (%s/DS)", + namebuf); + if (val->view->dlv == NULL || DLVTRIED(val)) { + markanswer(val); + result = ISC_R_SUCCESS; + goto out; + } + result = startfinddlvsep(val, + dns_fixedname_name(&val->fname)); goto out; } val->labels++; @@ -2406,7 +2310,6 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) { val->labels <= dns_name_countlabels(val->event->name); val->labels++) { - char namebuf[DNS_NAME_FORMATSIZE]; dns_fixedname_init(&val->fname); tname = dns_fixedname_name(&val->fname); @@ -2425,7 +2328,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) { if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) { /* * There is no DS. If this is a delegation, - * we're done. + * we maybe done. */ if (val->frdataset.trust < dns_trust_secure) { /* @@ -2443,8 +2346,11 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) { "must be secure failure"); return (DNS_R_MUSTBESECURE); } - val->event->rdataset->trust = dns_trust_answer; - return (ISC_R_SUCCESS); + if (val->view->dlv == NULL || DLVTRIED(val)) { + markanswer(val); + return (ISC_R_SUCCESS); + } + return (startfinddlvsep(val, tname)); } continue; } else if (result == ISC_R_SUCCESS) { @@ -2453,10 +2359,10 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) { * continue. */ if (val->frdataset.trust >= dns_trust_secure) { - if (!check_ds_algorithm(val, tname, - &val->frdataset)) { + if (!check_ds(val, tname, &val->frdataset)) { validator_log(val, ISC_LOG_DEBUG(3), - "no supported algorithm (ds)"); + "no supported algorithm/" + "digest (%s/DS)", namebuf); if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, @@ -2464,9 +2370,13 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) { result = DNS_R_MUSTBESECURE; goto out; } - val->event->rdataset->trust = - dns_trust_answer; - result = ISC_R_SUCCESS; + if (val->view->dlv == NULL || + DLVTRIED(val)) { + markanswer(val); + result = ISC_R_SUCCESS; + goto out; + } + result = startfinddlvsep(val, tname); goto out; } continue; @@ -2531,6 +2441,23 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) { return (result); } +static isc_result_t +dlv_validator_start(dns_validator_t *val) { + isc_event_t *event; + + validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start"); + + /* + * Reset state and try again. + */ + val->attributes &= VALATTR_DLVTRIED; + val->options &= ~DNS_VALIDATOR_DLV; + + event = (isc_event_t *)val->event; + isc_task_send(val->task, &event); + return (DNS_R_WAIT); +} + static void validator_start(isc_task_t *task, isc_event_t *event) { dns_validator_t *val; @@ -2547,11 +2474,18 @@ validator_start(isc_task_t *task, isc_event_t *event) { if (val->event == NULL) return; - validator_log(val, ISC_LOG_DEBUG(3), "starting"); + if (DLVTRIED(val)) + validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV"); + else + validator_log(val, ISC_LOG_DEBUG(3), "starting"); LOCK(&val->lock); - if (val->event->rdataset != NULL && val->event->sigrdataset != NULL) { + if ((val->options & DNS_VALIDATOR_DLV) != 0) { + validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV"); + result = startfinddlvsep(val, dns_rootname); + } else if (val->event->rdataset != NULL && + val->event->sigrdataset != NULL) { isc_result_t saved_result; /* @@ -2635,7 +2569,6 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, REQUIRE(type != 0); REQUIRE(rdataset != NULL || (rdataset == NULL && sigrdataset == NULL && message != NULL)); - REQUIRE(options == 0); REQUIRE(validatorp != NULL && *validatorp == NULL); tclone = NULL; @@ -2685,12 +2618,13 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, val->currentset = NULL; val->keyset = NULL; val->dsset = NULL; - val->dlv = NULL; + dns_rdataset_init(&val->dlv); val->soaset = NULL; val->nsecset = NULL; val->soaname = NULL; val->seensig = ISC_FALSE; val->havedlvsep = ISC_FALSE; + val->depth = 0; val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name); dns_rdataset_init(&val->frdataset); dns_rdataset_init(&val->fsigrdataset); @@ -2749,6 +2683,12 @@ destroy(dns_validator_t *val) { dns_keytable_detach(&val->keytable); if (val->subvalidator != NULL) dns_validator_destroy(&val->subvalidator); + if (val->havedlvsep) + dns_rdataset_disassociate(&val->dlv); + if (dns_rdataset_isassociated(&val->frdataset)) + dns_rdataset_disassociate(&val->frdataset); + if (dns_rdataset_isassociated(&val->fsigrdataset)) + dns_rdataset_disassociate(&val->fsigrdataset); mctx = val->view->mctx; if (val->siginfo != NULL) isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo)); @@ -2787,9 +2727,14 @@ validator_logv(dns_validator_t *val, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *fmt, va_list ap) { char msgbuf[2048]; + static const char spaces[] = " *"; + int depth = val->depth * 2; vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); + if ((unsigned int) depth >= sizeof spaces) + depth = sizeof spaces - 1; + if (val->event != NULL && val->event->name != NULL) { char namebuf[DNS_NAME_FORMATSIZE]; char typebuf[DNS_RDATATYPE_FORMATSIZE]; @@ -2798,11 +2743,12 @@ validator_logv(dns_validator_t *val, isc_logcategory_t *category, dns_rdatatype_format(val->event->type, typebuf, sizeof(typebuf)); isc_log_write(dns_lctx, category, module, level, - "validating %s %s: %s", namebuf, typebuf, - msgbuf); + "%.*svalidating @%p: %s %s: %s", depth, spaces, + val, namebuf, typebuf, msgbuf); } else { isc_log_write(dns_lctx, category, module, level, - "validator @%p: %s", val, msgbuf); + "%.*svalidator @%p: %s", depth, spaces, + val, msgbuf); } } diff --git a/usr.sbin/bind/lib/dns/xfrin.c b/usr.sbin/bind/lib/dns/xfrin.c index 55b6e2a5749..a0bd284617f 100644 --- a/usr.sbin/bind/lib/dns/xfrin.c +++ b/usr.sbin/bind/lib/dns/xfrin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: xfrin.c,v 1.124.2.4.2.9 2004/10/13 22:28:42 marka Exp $ */ +/* $ISC: xfrin.c,v 1.124.2.4.2.12 2005/11/03 23:08:41 marka Exp $ */ #include <config.h> @@ -232,7 +232,7 @@ xfrin_log1(int level, dns_name_t *zonename, dns_rdataclass_t rdclass, ISC_FORMAT_PRINTF(5, 6); static void -xfrin_log(dns_xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...) +xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(3, 4); /**************************************************************************/ @@ -581,7 +581,7 @@ dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype, isc_task_t *task, dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp) { dns_name_t *zonename = dns_zone_getorigin(zone); - dns_xfrin_ctx_t *xfr; + dns_xfrin_ctx_t *xfr = NULL; isc_result_t result; dns_db_t *db = NULL; @@ -1391,7 +1391,7 @@ xfrin_log1(int level, dns_name_t *zonename, dns_rdataclass_t rdclass, */ static void -xfrin_log(dns_xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...) +xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...) { va_list ap; diff --git a/usr.sbin/bind/lib/dns/zone.c b/usr.sbin/bind/lib/dns/zone.c index 775c9c8079b..b8156cf9e81 100644 --- a/usr.sbin/bind/lib/dns/zone.c +++ b/usr.sbin/bind/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: zone.c,v 1.333.2.23.2.55 2005/02/03 23:50:45 marka Exp $ */ +/* $ISC: zone.c,v 1.333.2.23.2.59 2005/07/29 00:38:33 marka Exp $ */ #include <config.h> @@ -167,6 +167,7 @@ struct dns_zone { isc_sockaddr_t *masters; dns_name_t **masterkeynames; + isc_boolean_t *mastersok; unsigned int masterscnt; unsigned int curmaster; isc_sockaddr_t masteraddr; @@ -536,6 +537,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->minretry = DNS_ZONE_MINRETRY; zone->masters = NULL; zone->masterkeynames = NULL; + zone->mastersok = NULL; zone->masterscnt = 0; zone->curmaster = 0; zone->notify = NULL; @@ -590,7 +592,8 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { free_mutex: DESTROYLOCK(&zone->lock); - return (ISC_R_NOMEMORY); + isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone)); + return (result); } /* @@ -1250,6 +1253,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, isc_uint32_t serial, refresh, retry, expire, minimum; isc_time_t now; isc_boolean_t needdump = ISC_FALSE; + isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE); TIME_NOW(&now); @@ -1355,10 +1359,32 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, if (result != ISC_R_SUCCESS) goto cleanup; if (zone->db != NULL) { - if (!isc_serial_ge(serial, zone->serial)) { + /* + * This is checked in zone_replacedb() for slave zones + * as they don't reload from disk. + */ + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) && + !isc_serial_gt(serial, zone->serial)) { + isc_uint32_t serialmin, serialmax; + + INSIST(zone->type == dns_zone_master); + + serialmin = (zone->serial + 1) & 0xffffffffU; + serialmax = (zone->serial + 0x7fffffffU) & + 0xffffffffU; + dns_zone_log(zone, ISC_LOG_ERROR, + "ixfr-from-differences: " + "new serial (%u) out of range " + "[%u - %u]", serial, serialmin, + serialmax); + result = DNS_R_BADZONE; + goto cleanup; + } else if (!isc_serial_ge(serial, zone->serial)) dns_zone_log(zone, ISC_LOG_ERROR, "zone serial has gone backwards"); - } + else if (serial == zone->serial && !hasinclude) + dns_zone_log(zone, ISC_LOG_ERROR, + "zone serial unchanged"); } zone->serial = serial; zone->refresh = RANGE(refresh, @@ -1943,6 +1969,7 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone, isc_sockaddr_t *masters, isc_sockaddr_t *new; isc_result_t result = ISC_R_SUCCESS; dns_name_t **newname; + isc_boolean_t *newok; unsigned int i; REQUIRE(DNS_ZONE_VALID(zone)); @@ -1972,10 +1999,15 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone, isc_sockaddr_t *masters, zone->masterscnt * sizeof(dns_name_t *)); zone->masterkeynames = NULL; } + if (zone->mastersok != NULL) { + isc_mem_put(zone->mctx, zone->mastersok, + zone->masterscnt * sizeof(isc_boolean_t)); + zone->mastersok = NULL; + } zone->masterscnt = 0; /* - * If count == 0, don't allocate any space for masters or keynames - * so internally, those pointers are NULL if count == 0 + * If count == 0, don't allocate any space for masters, mastersok or + * keynames so internally, those pointers are NULL if count == 0 */ if (count == 0) goto unlock; @@ -1983,27 +2015,35 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone, isc_sockaddr_t *masters, /* * masters must countain count elements! */ - new = isc_mem_get(zone->mctx, - count * sizeof(isc_sockaddr_t)); + new = isc_mem_get(zone->mctx, count * sizeof(*new)); if (new == NULL) { result = ISC_R_NOMEMORY; goto unlock; } memcpy(new, masters, count * sizeof(*new)); - zone->masters = new; - zone->masterscnt = count; - DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS); + + /* + * Similarly for mastersok. + */ + newok = isc_mem_get(zone->mctx, count * sizeof(*newok)); + if (newok == NULL) { + result = ISC_R_NOMEMORY; + isc_mem_put(zone->mctx, new, count * sizeof(*new)); + goto unlock; + }; + for (i = 0; i < count; i++) + newok[i] = ISC_FALSE; /* * if keynames is non-NULL, it must contain count elements! */ + newname = NULL; if (keynames != NULL) { - newname = isc_mem_get(zone->mctx, - count * sizeof(dns_name_t *)); + newname = isc_mem_get(zone->mctx, count * sizeof(*newname)); if (newname == NULL) { result = ISC_R_NOMEMORY; - isc_mem_put(zone->mctx, zone->masters, - count * sizeof(*new)); + isc_mem_put(zone->mctx, new, count * sizeof(*new)); + isc_mem_put(zone->mctx, newok, count * sizeof(*newok)); goto unlock; } for (i = 0; i < count; i++) @@ -2024,16 +2064,27 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone, isc_sockaddr_t *masters, dns_name_free( newname[i], zone->mctx); - isc_mem_put(zone->mctx, zone->masters, + isc_mem_put(zone->mctx, new, count * sizeof(*new)); + isc_mem_put(zone->mctx, newok, + count * sizeof(*newok)); isc_mem_put(zone->mctx, newname, count * sizeof(*newname)); goto unlock; } } } - zone->masterkeynames = newname; } + + /* + * Everything is ok so attach to the zone. + */ + zone->masters = new; + zone->mastersok = newok; + zone->masterkeynames = newname; + zone->masterscnt = count; + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS); + unlock: UNLOCK_ZONE(zone); return (result); @@ -2222,6 +2273,7 @@ void dns_zone_refresh(dns_zone_t *zone) { isc_interval_t i; isc_uint32_t oldflags; + unsigned int j; REQUIRE(DNS_ZONE_VALID(zone)); @@ -2266,6 +2318,8 @@ dns_zone_refresh(dns_zone_t *zone) { zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600); zone->curmaster = 0; + for (j = 0; j < zone->masterscnt; j++) + zone->mastersok[j] = ISC_FALSE; /* initiate soa query */ queue_soa_query(zone); unlock: @@ -3186,6 +3240,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) { isc_time_t now; isc_boolean_t exiting = ISC_FALSE; isc_interval_t i; + unsigned int j; stub = revent->ev_arg; INSIST(DNS_STUB_VALID(stub)); @@ -3360,13 +3415,37 @@ stub_callback(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); LOCK_ZONE(zone); dns_request_destroy(&zone->request); - zone->curmaster++; + /* + * Skip to next failed / untried master. + */ + do { + zone->curmaster++; + } while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS); if (exiting || zone->curmaster >= zone->masterscnt) { + isc_boolean_t done = ISC_TRUE; if (!exiting && DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { + /* + * Did we get a good answer from all the masters? + */ + for (j = 0; j < zone->masterscnt; j++) + if (zone->mastersok[j] == ISC_FALSE) { + done = ISC_FALSE; + break; + } + } else + done = ISC_TRUE; + if (!done) { zone->curmaster = 0; + /* + * Find the next failed master. + */ + while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]) + zone->curmaster++; DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); } else { DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); @@ -3420,6 +3499,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { dns_rdata_soa_t soa; isc_result_t result; isc_uint32_t serial; + unsigned int j; zone = revent->ev_arg; INSIST(DNS_ZONE_VALID(zone)); @@ -3668,6 +3748,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { } DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime); DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime); + zone->mastersok[zone->curmaster] = ISC_TRUE; goto next_master; } else { if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) @@ -3676,6 +3757,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { soa.serial, master, zone->serial); else zone_debuglog(zone, me, 1, "ahead"); + zone->mastersok[zone->curmaster] = ISC_TRUE; goto next_master; } if (msg != NULL) @@ -3688,13 +3770,37 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); LOCK_ZONE(zone); dns_request_destroy(&zone->request); - zone->curmaster++; + /* + * Skip to next failed / untried master. + */ + do { + zone->curmaster++; + } while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS); if (zone->curmaster >= zone->masterscnt) { + isc_boolean_t done = ISC_TRUE; if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { + /* + * Did we get a good answer from all the masters? + */ + for (j = 0; j < zone->masterscnt; j++) + if (zone->mastersok[j] == ISC_FALSE) { + done = ISC_FALSE; + break; + } + } else + done = ISC_TRUE; + if (!done) { DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); zone->curmaster = 0; + /* + * Find the next failed master. + */ + while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]) + zone->curmaster++; goto requeue; } DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); @@ -4023,7 +4129,13 @@ soa_query(isc_task_t *task, isc_event_t *event) { skip_master: if (key != NULL) dns_tsigkey_detach(&key); - zone->curmaster++; + /* + * Skip to next failed / untried master. + */ + do { + zone->curmaster++; + } while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]); if (zone->curmaster < zone->masterscnt) goto again; zone->curmaster = 0; @@ -5275,40 +5387,58 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { * is enabled in the configuration. */ if (zone->db != NULL && zone->journal != NULL && - DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), - "generating diffs"); - result = dns_db_diff(zone->mctx, db, ver, - zone->db, NULL /* XXX */, + DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) && + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) { + isc_uint32_t serial; + + dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs"); + + result = dns_db_getsoaserial(db, ver, &serial); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "ixfr-from-differences: unable to get " + "new serial"); + goto fail; + } + + /* + * This is checked in zone_postload() for master zones. + */ + if (zone->type == dns_zone_slave && + !isc_serial_gt(serial, zone->serial)) { + isc_uint32_t serialmin, serialmax; + serialmin = (zone->serial + 1) & 0xffffffffU; + serialmax = (zone->serial + 0x7fffffffU) & 0xffffffffU; + dns_zone_log(zone, ISC_LOG_ERROR, + "ixfr-from-differences: failed: " + "new serial (%u) out of range [%u - %u]", + serial, serialmin, serialmax); + result = ISC_R_RANGE; + goto fail; + } + + result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL, zone->journal); if (result != ISC_R_SUCCESS) goto fail; if (dump) zone_needdump(zone, DNS_DUMP_DELAY); else if (zone->journalsize != -1) { - isc_uint32_t serial; - - result = dns_db_getsoaserial(db, ver, &serial); - if (result == ISC_R_SUCCESS) { - result = dns_journal_compact(zone->mctx, - zone->journal, - serial, - zone->journalsize); - switch (result) { - case ISC_R_SUCCESS: - case ISC_R_NOSPACE: - case ISC_R_NOTFOUND: - dns_zone_log(zone, ISC_LOG_DEBUG(3), - "dns_journal_compact: %s", - dns_result_totext(result)); - break; - default: - dns_zone_log(zone, ISC_LOG_ERROR, + result = dns_journal_compact(zone->mctx, zone->journal, + serial, zone->journalsize); + switch (result) { + case ISC_R_SUCCESS: + case ISC_R_NOSPACE: + case ISC_R_NOTFOUND: + dns_zone_log(zone, ISC_LOG_DEBUG(3), + "dns_journal_compact: %s", + dns_result_totext(result)); + break; + default: + dns_zone_log(zone, ISC_LOG_ERROR, "dns_journal_compact failed: %s", - dns_result_totext(result)); - break; - } + dns_result_totext(result)); + break; } } } else { @@ -5503,7 +5633,14 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) { default: next_master: - zone->curmaster++; + /* + * Skip to next failed / untried master. + */ + do { + zone->curmaster++; + } while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]); + /* FALLTHROUGH */ same_master: if (zone->curmaster >= zone->masterscnt) { zone->curmaster = 0; @@ -5511,6 +5648,9 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) { !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); + while (zone->curmaster < zone->masterscnt && + zone->mastersok[zone->curmaster]) + zone->curmaster++; again = ISC_TRUE; } else DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); @@ -5697,7 +5837,11 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) { "requesting AXFR of " "initial version from %s", mastertext); xfrtype = dns_rdatatype_axfr; - } else if (dns_zone_isforced(zone)) { + } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences " + "set, requesting AXFR from %s", mastertext); + xfrtype = dns_rdatatype_axfr; + } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) { dns_zone_log(zone, ISC_LOG_DEBUG(1), "forced reload, requesting AXFR of " "initial version from %s", mastertext); @@ -6663,6 +6807,9 @@ void dns_zone_forcereload(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); + if (zone->type == dns_zone_master) + return; + LOCK_ZONE(zone); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER); UNLOCK_ZONE(zone); |