diff options
author | Internet Software Consortium, Inc <@isc.org> | 2012-01-18 10:11:16 -0700 |
---|---|---|
committer | Internet Software Consortium, Inc <@isc.org> | 2012-01-18 10:11:16 -0700 |
commit | f8bb4eefd76094703b91acc987d8df0603639376 (patch) | |
tree | e2b41a79e5cee716e4c8b9c07c83910509e6ac2e /lib/dns | |
parent | 8b08ed79737eaec2fd64fbecce719fc5d91c0f48 (diff) | |
download | bind9-f8bb4eefd76094703b91acc987d8df0603639376.tar.gz |
9.9.0rc1
Diffstat (limited to 'lib/dns')
41 files changed, 1487 insertions, 828 deletions
diff --git a/lib/dns/adb.c b/lib/dns/adb.c index b6109ec7..5c5fe8b1 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: adb.c,v 1.262 2011-10-28 04:57:34 marka Exp $ */ +/* $Id: adb.c,v 1.264 2011-12-05 17:10:51 each Exp $ */ /*! \file * @@ -34,7 +34,6 @@ #include <isc/netaddr.h> #include <isc/random.h> #include <isc/stats.h> -#include <isc/stdio.h> /* temporary */ #include <isc/string.h> /* Required for HP/UX (and others?) */ #include <isc/task.h> #include <isc/util.h> @@ -66,24 +65,6 @@ #define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6') #define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC) -/*** - *** Constants for EDNS0 packets - *** DNS_ADB_EDNS0_MAX_LEN - max udpsize for edns0, should come from - *** named.conf - *** DNS_ADB_EDNS0_MIN_LEN - min udpsize for edns0 - *** DNS_ADB_EDNS_RESET_TIME - after this period of time, drop count - *** is set to 0 and EDNS may be tried at - *** bigger size - surface to user? - *** DNS_ADB_EDNS_MAX_DROP_COUNT - after this many times EDNS has been - *** reduced, edns->fetch_flag set - *** DNS_ADB_EDNS_MAX_DROP_TIME - after this time retry EDNS at larger size - ***/ -#define DNS_ADB_EDNS0_MAX_LEN 4096 -#define DNS_ADB_EDNS0_MIN_LEN 512 -#define DNS_ADB_EDNS_RESET_TIME 300 /*make this user configurable?*/ -#define DNS_ADB_EDNS_MAX_DROP_COUNT 5 /*make this user configurable?*/ -#define DNS_ADB_EDNS_MAX_DROP_TIME 3600 /*make this user configurable?*/ - /*! * For type 3 negative cache entries, we will remember that the address is * broken for this long. XXXMLG This is also used for actual addresses, too. @@ -271,31 +252,6 @@ struct dns_adbentry { * name. */ - - unsigned int edns_big_size; - unsigned int edns_last_size; - unsigned int edns_fetch_flag; - unsigned int edns_drop_count; - isc_stdtime_t edns_drop_timestamp; - isc_stdtime_t edns_expires_timestamp; - isc_boolean_t edns_timer_set; - /*%< - * The above fields beginning with edns_* determine - * past success with edns for this server. - * edns_big_size - biggest successful size received (e.g., 512) - * edns_last_size - last packet size received - * edns_fetch_flag - current EDNS state for this server (one of - * DNS_FETCHOPT_NOEDNS0, DNS_FETCHOPT_EDNS512 or - * 0 meaning use DNS_ADB_EDNS0_MAX_LEN) - * edns_drop_count - keeps count of the number of times EDNS udpsize - * was dropped - reset to 0 every - * DNS_ADB_EDNS_RESET_TIME - * edns_drop_timestamp - The time at which the first EDNS drop - * in packet size was recorded - * - * See also dns_adb_drop/setednssize() - */ - ISC_LIST(dns_adblameinfo_t) lameinfo; ISC_LINK(dns_adbentry_t) plink; @@ -1791,13 +1747,6 @@ new_adbentry(dns_adb_t *adb) { isc_random_get(&r); e->srtt = (r & 0x1f) + 1; e->expires = 0; - e->edns_big_size = 0; - e->edns_last_size = 0; - e->edns_fetch_flag = 0; - e->edns_drop_timestamp = 0; - e->edns_drop_count = 0; - e->edns_expires_timestamp = 0; - e->edns_timer_set = isc_boolean_false; ISC_LIST_INIT(e->lameinfo); ISC_LINK_INIT(e, plink); LOCK(&adb->entriescntlock); @@ -3961,169 +3910,6 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, UNLOCK(&adb->entrylocks[bucket]); } -unsigned int -dns_adb_getednsflag(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now) -{ - int bucket = 0; - int flag_to_use = 0; /* assume max by default */ - - REQUIRE(DNS_ADB_VALID(adb)); - REQUIRE(DNS_ADBADDRINFO_VALID(addr)); - - /* - * The purpose of this function is to return - * edns_fetch_flag, which effectively sets the udpsize for EDNS - * or turns off EDNS (if NOEDNS0 has been recorded). - * - * Also, this function checks to see if the timer needs resetting. - * ---> this part should really be done via a callback? - */ - - bucket = addr->entry->lock_bucket; - LOCK(&adb->entrylocks[bucket]); - - if((addr->entry->edns_timer_set) && - (now >= addr->entry->edns_expires_timestamp)) { - - /* Eventually, we may support more sizes */ - if((addr->entry->edns_big_size <= 512) && - (addr->entry->edns_big_size > 0)) - flag_to_use = DNS_FETCHOPT_EDNS512; - - addr->entry->edns_fetch_flag = flag_to_use; - addr->entry->edns_expires_timestamp = 0; - addr->entry->edns_timer_set = isc_boolean_false; - - } - - flag_to_use = addr->entry->edns_fetch_flag; - - UNLOCK(&adb->entrylocks[bucket]); - - return(flag_to_use); -} - -void -dns_adb_setednssize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, - unsigned int length) -{ - int bucket = 0; - unsigned int length_to_use; - - REQUIRE(DNS_ADB_VALID(adb)); - REQUIRE(DNS_ADBADDRINFO_VALID(addr)); - - bucket = addr->entry->lock_bucket; - LOCK(&adb->entrylocks[bucket]); - - /* - * The purpose of this function is to record - * the maximum sized udp response seen from the - * instant server. - */ - - length_to_use = addr->entry->edns_big_size; - - if (length > DNS_ADB_EDNS0_MAX_LEN) - length = DNS_ADB_EDNS0_MAX_LEN; - if (length < DNS_ADB_EDNS0_MIN_LEN) - length = DNS_ADB_EDNS0_MIN_LEN; - if (length > length_to_use) - length_to_use = length; - - addr->entry->edns_big_size = length_to_use; - - UNLOCK(&adb->entrylocks[bucket]); -} - -void -dns_adb_dropednssize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, - unsigned int length, isc_stdtime_t now) -{ - isc_stdtime_t expires_ts_to_use; - isc_boolean_t timer_setting_to_use; - unsigned int length_to_use; - unsigned int drop_counter_to_use; - unsigned int drop_ts_to_use; - unsigned int flag_to_use; - int bucket = 0; - - REQUIRE(DNS_ADB_VALID(adb)); - REQUIRE(DNS_ADBADDRINFO_VALID(addr)); - - if (length > DNS_ADB_EDNS0_MAX_LEN) - length = DNS_ADB_EDNS0_MAX_LEN; - if (length < DNS_ADB_EDNS0_MIN_LEN) - length = DNS_ADB_EDNS0_MIN_LEN; - - bucket = addr->entry->lock_bucket; - LOCK(&adb->entrylocks[bucket]); - - expires_ts_to_use = addr->entry->edns_expires_timestamp; - timer_setting_to_use = addr->entry->edns_timer_set; - length_to_use = addr->entry->edns_big_size; - drop_ts_to_use = addr->entry->edns_drop_timestamp; - flag_to_use = addr->entry->edns_fetch_flag; - - /* - * This function keeps a count of the number of times - * within DNS_ADB_EDNS_RESET_TIME that a particular server - * has dropped the udpsize in order to communicate with the - * server. If the number of times this occurs exceeds - * DNS_ADB_EDNS_MAX_DROP_COUNT, then the udpsize is reduced - * by way of edns_fetch_flag for DNS_ADB_EDNS_MAX_DROP_TIME, - * after which the largest size is retried again. - * NOTE: currently, only 4096 and 512 are supported sizes - */ - - if (length > length_to_use) - length_to_use = length; - - if ((now - addr->entry->edns_drop_timestamp) >= - DNS_ADB_EDNS_RESET_TIME) { - - drop_counter_to_use = 1; - drop_ts_to_use = now; - } else { - - drop_counter_to_use = addr->entry->edns_drop_count + 1; - - if (drop_counter_to_use >= DNS_ADB_EDNS_MAX_DROP_COUNT) { - /* - * At this point, we are dropping down the - * udpsize because we've had too many misses - * at larger sizes. - */ - if (timer_setting_to_use == isc_boolean_false) { - /* - * if we haven't already set a timer, - * do so now. After DNS_ADB_EDNS_MAX_DROP_TIME, - * we'll go back to the largest size - */ - expires_ts_to_use = - now + DNS_ADB_EDNS_MAX_DROP_TIME; - timer_setting_to_use = isc_boolean_true; - } - - if (length == 0) - flag_to_use = DNS_FETCHOPT_NOEDNS0; - else /* eventually, more edns sizes here */ - flag_to_use = DNS_FETCHOPT_EDNS512; - - drop_ts_to_use = 0; - drop_counter_to_use = 0; - } - } - - addr->entry->edns_drop_timestamp = drop_ts_to_use; - addr->entry->edns_drop_count = drop_counter_to_use; - addr->entry->edns_fetch_flag = flag_to_use; - addr->entry->edns_expires_timestamp = expires_ts_to_use; - addr->entry->edns_timer_set = timer_setting_to_use; - - UNLOCK(&adb->entrylocks[bucket]); -} - void dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int bits, unsigned int mask) diff --git a/lib/dns/api b/lib/dns/api index 580ddcfd..63ac0c79 100644 --- a/lib/dns/api +++ b/lib/dns/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 91 +LIBINTERFACE = 92 LIBREVISION = 0 -LIBAGE = 1 +LIBAGE = 0 diff --git a/lib/dns/callbacks.c b/lib/dns/callbacks.c index 474d4e2d..a4b46235 100644 --- a/lib/dns/callbacks.c +++ b/lib/dns/callbacks.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: callbacks.c,v 1.17 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: callbacks.c,v 1.19 2011-12-09 23:47:05 tbox Exp $ */ /*! \file */ @@ -88,6 +88,8 @@ dns_rdatacallbacks_initcommon(dns_rdatacallbacks_t *callbacks) { REQUIRE(callbacks != NULL); callbacks->add = NULL; + callbacks->rawdata = NULL; + callbacks->zone = NULL; callbacks->add_private = NULL; callbacks->error_private = NULL; callbacks->warn_private = NULL; diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index f9acc101..eea01b07 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.c,v 1.174 2011-07-28 23:47:58 tbox Exp $ */ +/* $Id: dispatch.c,v 1.175 2011-11-29 01:03:47 marka Exp $ */ /*! \file */ @@ -1810,6 +1810,10 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local, result = isc_socket_dup(dup_socket, &sock); if (result != ISC_R_SUCCESS) return (result); + + isc_socket_setname(sock, "dispatcher", NULL); + *sockp = sock; + return (ISC_R_SUCCESS); } else { result = isc_socket_create(mgr, isc_sockaddr_pf(local), isc_sockettype_udp, &sock); diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index 3c568c73..27b9e65e 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -16,7 +16,7 @@ */ /* - * $Id: dnssec.c,v 1.125 2011-08-26 05:29:48 marka Exp $ + * $Id: dnssec.c,v 1.126 2011-12-07 22:36:25 marka Exp $ */ /*! \file */ @@ -1142,17 +1142,15 @@ dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) { } static void -get_hints(dns_dnsseckey_t *key) { +get_hints(dns_dnsseckey_t *key, isc_stdtime_t now) { isc_result_t result; - isc_stdtime_t now, publish, active, revoke, inactive, delete; + isc_stdtime_t publish, active, revoke, inactive, delete; isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE; isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE; isc_boolean_t delset = ISC_FALSE; REQUIRE(key != NULL && key->key != NULL); - isc_stdtime_get(&now); - result = dst_key_gettime(key->key, DST_TIME_PUBLISH, &publish); if (result == ISC_R_SUCCESS) pubset = ISC_TRUE; @@ -1249,6 +1247,7 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, char namebuf[DNS_NAME_FORMATSIZE], *p; isc_buffer_t b; unsigned int len; + isc_stdtime_t now; REQUIRE(keylist != NULL); ISC_LIST_INIT(list); @@ -1264,6 +1263,8 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, RETERR(isc_dir_open(&dir, directory)); dir_open = ISC_TRUE; + isc_stdtime_get(&now); + while (isc_dir_read(&dir) == ISC_R_SUCCESS) { if (dir.entry.name[0] == 'K' && dir.entry.length > len + 1 && @@ -1294,7 +1295,7 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, RETERR(dns_dnsseckey_create(mctx, &dstkey, &key)); key->source = dns_keysource_repository; - get_hints(key); + get_hints(key, now); if (key->legacy) { dns_dnsseckey_destroy(mctx, &key); diff --git a/lib/dns/ecdb.c b/lib/dns/ecdb.c index 1ad03feb..eb2910f0 100644 --- a/lib/dns/ecdb.c +++ b/lib/dns/ecdb.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ecdb.c,v 1.9 2011-10-11 13:33:45 marka Exp $ */ +/* $Id: ecdb.c,v 1.10 2011-12-20 00:06:53 marka Exp $ */ #include "config.h" @@ -37,10 +37,6 @@ #define ECDBNODE_MAGIC ISC_MAGIC('E', 'C', 'D', 'N') #define VALID_ECDBNODE(ecdbn) ISC_MAGIC_VALID(ecdbn, ECDBNODE_MAGIC) -#if DNS_RDATASET_FIXED -#error "Fixed rdataset isn't supported in this implementation" -#endif - /*% * The 'ephemeral' cache DB (ecdb) implementation. An ecdb just provides * temporary storage for ongoing name resolution with the common DB interfaces. @@ -662,7 +658,11 @@ rdataset_first(dns_rdataset_t *rdataset) { rdataset->private5 = NULL; return (ISC_R_NOMORE); } +#if DNS_RDATASET_FIXED + raw += 2 + (4 * count); +#else raw += 2; +#endif /* * The privateuint4 field is the number of rdata beyond the cursor * position, so we decrement the total count by one before storing @@ -688,7 +688,11 @@ rdataset_next(dns_rdataset_t *rdataset) { rdataset->privateuint4 = count; raw = rdataset->private5; length = raw[0] * 256 + raw[1]; +#if DNS_RDATASET_FIXED + raw += length + 4; +#else raw += length + 2; +#endif rdataset->private5 = raw; return (ISC_R_SUCCESS); @@ -704,7 +708,11 @@ rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { REQUIRE(raw != NULL); length = raw[0] * 256 + raw[1]; +#if DNS_RDATASET_FIXED + raw += 4; +#else raw += 2; +#endif if (rdataset->type == dns_rdatatype_rrsig) { if (*raw & DNS_RDATASLAB_OFFLINE) flags |= DNS_RDATA_OFFLINE; diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h index 170fc846..9b15f102 100644 --- a/lib/dns/include/dns/adb.h +++ b/lib/dns/include/dns/adb.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: adb.h,v 1.87 2011-10-27 23:46:31 tbox Exp $ */ +/* $Id: adb.h,v 1.88 2011-12-05 17:10:51 each Exp $ */ #ifndef DNS_ADB_H #define DNS_ADB_H 1 @@ -548,64 +548,6 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, * srtt value. This may include changes made by others. */ -unsigned int -dns_adb_getednsflag(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now); -/*% - * Get the EDNS big size - * - *\brief - * Return the edns_fetchopt_flag from the instant dns_adbentry struct - * This value may be DNS_FETCHOPT_NOEDNS0, DNS_FETCHOPT_EDNS512, - * or 0. If 0, the default maximum EDNS udp size is assumed. - * - * Requires: - * - *\li adb be valid. - * - *\li addr be valid. - */ - -void -dns_adb_setednssize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, - unsigned int length); -/*% - * Set the EDNS size - * - *\brief - * Record the biggest length of received packet and maintain information - * about reductions in udp size. - * - *\li length - size of packet - *\li now - current time in seconds - * - * Requires: - * - *\li adb be valid. - * - *\li addr be valid. - */ - -void -dns_adb_dropednssize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, - unsigned int length, isc_stdtime_t now); -/*% - * Drop the EDNS size - * - *\brief - * Record a notification that the packetsize has been dropped because of - * communication failures. If enough of these occur, this server's EDNS size - * will be dropped for DNS_ADB_EDNS_MAX_DROP_TIME. - * - *\li length - size of packet - *\li now - current time in seconds - * - * Requires: - * - *\li adb be valid. - * - *\li addr be valid. - */ - void dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int bits, unsigned int mask); diff --git a/lib/dns/include/dns/callbacks.h b/lib/dns/include/dns/callbacks.h index 1b920080..7503f15c 100644 --- a/lib/dns/include/dns/callbacks.h +++ b/lib/dns/include/dns/callbacks.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2011 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: callbacks.h,v 1.24 2007-06-19 23:47:16 tbox Exp $ */ +/* $Id: callbacks.h,v 1.26 2011-12-09 23:47:05 tbox Exp $ */ #ifndef DNS_CALLBACKS_H #define DNS_CALLBACKS_H 1 @@ -41,6 +41,14 @@ struct dns_rdatacallbacks { * dns_load_master calls this when it has rdatasets to commit. */ dns_addrdatasetfunc_t add; + + /*% + * dns_master_load*() call this when loading a raw zonefile, + * to pass back information obtained from the file header + */ + dns_rawdatafunc_t rawdata; + dns_zone_t *zone; + /*% * dns_load_master / dns_rdata_fromtext call this to issue a error. */ diff --git a/lib/dns/include/dns/journal.h b/lib/dns/include/dns/journal.h index c5024a37..3141351f 100644 --- a/lib/dns/include/dns/journal.h +++ b/lib/dns/include/dns/journal.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: journal.h,v 1.39 2011-08-30 23:46:53 tbox Exp $ */ +/* $Id: journal.h,v 1.43 2011-12-22 07:32:41 each Exp $ */ #ifndef DNS_JOURNAL_H #define DNS_JOURNAL_H 1 @@ -76,7 +76,7 @@ ISC_LANG_BEGINDECLS isc_result_t dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx, - dns_diffop_t op, dns_difftuple_t **tp); + dns_diffop_t op, dns_difftuple_t **tp); /*!< brief * Create a diff tuple for the current database SOA. * XXX this probably belongs somewhere else. @@ -106,7 +106,7 @@ dns_journal_open(isc_mem_t *mctx, const char *filename, unsigned int mode, * * DNS_JOURNAL_CREATE open the journal for reading and writing and create * the journal if it does not exist. - * DNS_JOURNAL_WRITE open the journal for readinge and writing. + * DNS_JOURNAL_WRITE open the journal for reading and writing. * DNS_JOURNAL_READ open the journal for reading only. */ @@ -270,12 +270,18 @@ dns_db_diff(isc_mem_t *mctx, dns_db_t *dba, dns_dbversion_t *dbvera, dns_db_t *dbb, dns_dbversion_t *dbverb, const char *journal_filename); + +isc_result_t +dns_db_diffx(dns_diff_t *diff, dns_db_t *dba, dns_dbversion_t *dbvera, + dns_db_t *dbb, dns_dbversion_t *dbverb, + const char *journal_filename); /*%< - * Compare the databases 'dba' and 'dbb' and generate a journal + * Compare the databases 'dba' and 'dbb' and generate a diff/journal * entry containing the changes to make 'dba' from 'dbb' (note * the order). This journal entry will consist of a single, * possibly very large transaction. Append the journal - * entry to the journal file specified by 'journal_filename'. + * entry to the journal file specified by 'journal_filename' if + * non-NULL. */ isc_result_t @@ -287,12 +293,15 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial, * exists and is non-empty 'serial' must exist in the journal. */ -isc_uint32_t -dns_journal_get_bitws(dns_journal_t *j); +isc_boolean_t +dns_journal_get_sourceserial(dns_journal_t *j, isc_uint32_t *sourceserial); void -dns_journal_set_bitws(dns_journal_t *j, isc_uint32_t bitws); +dns_journal_set_sourceserial(dns_journal_t *j, isc_uint32_t sourceserial); /*%< - * Get and set bump in the wire serial. + * Get and set source serial. + * + * Returns: + * ISC_TRUE if sourceserial has previously been set. */ ISC_LANG_ENDDECLS diff --git a/lib/dns/include/dns/master.h b/lib/dns/include/dns/master.h index 2ee63748..3c217255 100644 --- a/lib/dns/include/dns/master.h +++ b/lib/dns/include/dns/master.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011 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: master.h,v 1.53 2009-07-01 23:47:36 tbox Exp $ */ +/* $Id: master.h,v 1.55 2011-12-09 23:47:05 tbox Exp $ */ #ifndef DNS_MASTER_H #define DNS_MASTER_H 1 @@ -66,18 +66,29 @@ ISC_LANG_BEGINDECLS * encoding, we directly read/write each field so that the encoded data * is always "packed", regardless of the hardware architecture. */ -#define DNS_RAWFORMAT_VERSION 0 +#define DNS_RAWFORMAT_VERSION 1 + +/* + * Flags to indicate the status of the data in the raw file header + */ +#define DNS_MASTERRAW_COMPAT 0x01 +#define DNS_MASTERRAW_SOURCESERIALSET 0x02 +#define DNS_MASTERRAW_LASTXFRINSET 0x04 /* Common header */ -typedef struct { +struct dns_masterrawheader { isc_uint32_t format; /* must be * dns_masterformat_raw */ isc_uint32_t version; /* compatibility for future * extensions */ isc_uint32_t dumptime; /* timestamp on creation - * (currently unused) - */ -} dns_masterrawheader_t; + * (currently unused) */ + isc_uint32_t flags; /* Flags */ + isc_uint32_t sourceserial; /* Source serial number (used + * by inline-signing zones) */ + isc_uint32_t lastxfrin; /* timestamp of last transfer + * (used by slave zones) */ +}; /* The structure for each RRset */ typedef struct { @@ -302,6 +313,12 @@ dns_loadctx_cancel(dns_loadctx_t *ctx); *\li 'ctx' to be valid */ +void +dns_master_initrawheader(dns_masterrawheader_t *header); +/*%< + * Initializes the header for a raw master file, setting all + * values to zero. + */ ISC_LANG_ENDDECLS #endif /* DNS_MASTER_H */ diff --git a/lib/dns/include/dns/masterdump.h b/lib/dns/include/dns/masterdump.h index be43875b..266877a1 100644 --- a/lib/dns/include/dns/masterdump.h +++ b/lib/dns/include/dns/masterdump.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: masterdump.h,v 1.45 2011-05-26 07:56:39 marka Exp $ */ +/* $Id: masterdump.h,v 1.47 2011-12-08 23:46:49 tbox Exp $ */ #ifndef DNS_MASTERDUMP_H #define DNS_MASTERDUMP_H 1 @@ -220,13 +220,25 @@ dns_master_dumptostream2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, dns_masterformat_t format, FILE *f); + +isc_result_t +dns_master_dumptostream3(isc_mem_t *mctx, dns_db_t *db, + dns_dbversion_t *version, + const dns_master_style_t *style, + dns_masterformat_t format, + dns_masterrawheader_t *header, FILE *f); /*%< * Dump the database 'db' to the steam 'f' in the specified format by * 'format'. If the format is dns_masterformat_text (the RFC1035 format), * 'style' specifies the file style (e.g., &dns_master_style_default). * - * dns_master_dumptostream() is an old form of dns_master_dumptostream2(), + * dns_master_dumptostream() is an old form of dns_master_dumptostream3(), * which always specifies the dns_masterformat_text format. + * dns_master_dumptostream2() is an old form which always specifies + * a NULL header. + * + * If 'format' is dns_masterformat_raw, then 'header' can contain + * information to be written to the file header. * * Temporary dynamic memory may be allocated from 'mctx'. * @@ -257,6 +269,13 @@ dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg, dns_dumpctx_t **dctxp, dns_masterformat_t format); isc_result_t +dns_master_dumpinc3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, + const dns_master_style_t *style, const char *filename, + isc_task_t *task, dns_dumpdonefunc_t done, void + *done_arg, dns_dumpctx_t **dctxp, + dns_masterformat_t format, dns_masterrawheader_t *header); + +isc_result_t dns_master_dump(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, const char *filename); @@ -267,14 +286,24 @@ dns_master_dump2(isc_mem_t *mctx, dns_db_t *db, const dns_master_style_t *style, const char *filename, dns_masterformat_t format); +isc_result_t +dns_master_dump3(isc_mem_t *mctx, dns_db_t *db, + dns_dbversion_t *version, + const dns_master_style_t *style, const char *filename, + dns_masterformat_t format, dns_masterrawheader_t *header); + /*%< * Dump the database 'db' to the file 'filename' in the specified format by * 'format'. If the format is dns_masterformat_text (the RFC1035 format), * 'style' specifies the file style (e.g., &dns_master_style_default). * - * dns_master_dumpinc() and dns_master_dump() are old forms of _dumpinc2() - * and _dump2(), respectively, which always specify the dns_masterformat_text - * format. + * dns_master_dumpinc() and dns_master_dump() are old forms of _dumpinc3() + * and _dump3(), respectively, which always specify the dns_masterformat_text + * format. dns_master_dumpinc2() and dns_master_dump2() are old forms which + * always specify a NULL header. + * + * If 'format' is dns_masterformat_raw, then 'header' can contain + * information to be written to the file header. * * Temporary dynamic memory may be allocated from 'mctx'. * diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index f6cd6325..043ede4a 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.h,v 1.71 2011-11-16 22:18:52 marka Exp $ */ +/* $Id: resolver.h,v 1.72 2011-12-05 17:10:51 each Exp $ */ #ifndef DNS_RESOLVER_H #define DNS_RESOLVER_H 1 @@ -96,9 +96,6 @@ typedef struct dns_fetchevent { #define DNS_FETCHOPT_EDNS512 0x40 /*%< Advertise a 512 byte UDP buffer. */ #define DNS_FETCHOPT_WANTNSID 0x80 /*%< Request NSID */ -#define DNS_FETCHOPT_CACHENOEDNS 0x100 /*%< This is a candidate - for setting NOEDNS - in adb. */ #define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000 #define DNS_FETCHOPT_EDNSVERSIONMASK 0xff000000 diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 3814aef4..716285b6 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: types.h,v 1.145 2011-07-01 23:47:44 tbox Exp $ */ +/* $Id: types.h,v 1.146 2011-12-08 16:07:21 each Exp $ */ #ifndef DNS_TYPES_H #define DNS_TYPES_H 1 @@ -85,6 +85,7 @@ typedef struct dns_keytable dns_keytable_t; typedef isc_uint16_t dns_keytag_t; typedef struct dns_loadctx dns_loadctx_t; typedef struct dns_loadmgr dns_loadmgr_t; +typedef struct dns_masterrawheader dns_masterrawheader_t; typedef struct dns_message dns_message_t; typedef isc_uint16_t dns_messageid_t; typedef isc_region_t dns_label_t; @@ -355,6 +356,9 @@ typedef void typedef void (*dns_loaddonefunc_t)(void *, isc_result_t); +typedef void +(*dns_rawdatafunc_t)(dns_zone_t *, dns_masterrawheader_t *); + typedef isc_result_t (*dns_addrdatasetfunc_t)(void *, dns_name_t *, dns_rdataset_t *); diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index f9e534b3..765f73fa 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.197 2011-11-04 05:51:01 each Exp $ */ +/* $Id: zone.h,v 1.199 2011-12-22 07:32:41 each Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -32,6 +32,7 @@ #include <isc/lang.h> #include <isc/rwlock.h> +#include <dns/master.h> #include <dns/masterdump.h> #include <dns/rdatastruct.h> #include <dns/types.h> @@ -510,6 +511,10 @@ dns_zone_dumptostream(dns_zone_t *zone, FILE *fd); isc_result_t dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format, const dns_master_style_t *style); +isc_result_t +dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format, + const dns_master_style_t *style, + const isc_uint32_t rawversion); /*%< * Write the zone to stream 'fd' in the specified 'format'. * If the 'format' is dns_masterformat_text (RFC1035), 'style' also @@ -519,7 +524,11 @@ dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format, * dns_zone_dumptostream2(), which always uses the dns_masterformat_text * format and the dns_master_style_default style. * - * Note that dns_zone_dumptostream2() is the most flexible form. It + * dns_zone_dumptostream2() is a backward-compatible form of + * dns_zone_dumptostream3(), which always uses the current + * default raw file format version. + * + * Note that dns_zone_dumptostream3() is the most flexible form. It * can also provide the functionality of dns_zone_fulldumptostream(). * * Require: @@ -2021,6 +2030,13 @@ dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags, * Requires: * \li 'zone' to be valid. */ + +void +dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header); +/*% + * Set the data to be included in the header when the zone is dumped in + * binary format. + */ ISC_LANG_ENDDECLS #endif /* DNS_ZONE_H */ diff --git a/lib/dns/journal.c b/lib/dns/journal.c index 16fe541b..4f2f5a03 100644 --- a/lib/dns/journal.c +++ b/lib/dns/journal.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: journal.c,v 1.116 2011-08-30 23:46:52 tbox Exp $ */ +/* $Id: journal.c,v 1.120 2011-12-22 07:32:41 each Exp $ */ #include <config.h> @@ -111,6 +111,8 @@ static isc_boolean_t bind8_compat = ISC_TRUE; /* XXX config */ if (result != ISC_R_SUCCESS) goto failure; \ } while (0) +#define JOURNAL_SERIALSET 0x01U + static isc_result_t index_to_disk(dns_journal_t *); static inline isc_uint32_t @@ -213,8 +215,9 @@ typedef union { journal_rawpos_t end; /*% Number of index entries following the header. */ unsigned char index_size[4]; - /*% Bump in the wire serial. */ - unsigned char bitws[4]; + /*% Source serial number. */ + unsigned char sourceserial[4]; + unsigned char flags; } h; /* Pad the header to a fixed size. */ unsigned char pad[JOURNAL_HEADER_SIZE]; @@ -254,7 +257,8 @@ typedef struct { journal_pos_t begin; journal_pos_t end; isc_uint32_t index_size; - isc_uint32_t bitws; + isc_uint32_t sourceserial; + isc_boolean_t serialset; } journal_header_t; /*% @@ -287,7 +291,7 @@ typedef struct { */ static journal_header_t -initial_journal_header = { ";BIND LOG V9\n", { 0, 0 }, { 0, 0 }, 0, 0 }; +initial_journal_header = { ";BIND LOG V9\n", { 0, 0 }, { 0, 0 }, 0, 0, 0 }; #define JOURNAL_EMPTY(h) ((h)->begin.offset == (h)->end.offset) @@ -296,7 +300,7 @@ typedef enum { JOURNAL_STATE_READ, JOURNAL_STATE_WRITE, JOURNAL_STATE_TRANSACTION, - JOURNAL_STATE_BITWS + JOURNAL_STATE_INLINE } journal_state_t; struct dns_journal { @@ -357,18 +361,24 @@ journal_header_decode(journal_rawheader_t *raw, journal_header_t *cooked) { journal_pos_decode(&raw->h.begin, &cooked->begin); journal_pos_decode(&raw->h.end, &cooked->end); cooked->index_size = decode_uint32(raw->h.index_size); - cooked->bitws = decode_uint32(raw->h.bitws); + cooked->sourceserial = decode_uint32(raw->h.sourceserial); + cooked->serialset = ISC_TF(raw->h.flags & JOURNAL_SERIALSET); } static void journal_header_encode(journal_header_t *cooked, journal_rawheader_t *raw) { + unsigned char flags = 0; + INSIST(sizeof(cooked->format) == sizeof(raw->h.format)); memset(raw->pad, 0, sizeof(raw->pad)); memcpy(raw->h.format, cooked->format, sizeof(raw->h.format)); journal_pos_encode(&raw->h.begin, &cooked->begin); journal_pos_encode(&raw->h.end, &cooked->end); encode_uint32(cooked->index_size, raw->h.index_size); - encode_uint32(cooked->bitws, raw->h.bitws); + encode_uint32(cooked->sourceserial, raw->h.sourceserial); + if (cooked->serialset) + flags |= JOURNAL_SERIALSET; + raw->h.flags = flags; } /* @@ -546,7 +556,8 @@ journal_file_create(isc_mem_t *mctx, const char *filename) { static isc_result_t journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write, - isc_boolean_t create, dns_journal_t **journalp) { + isc_boolean_t create, dns_journal_t **journalp) +{ FILE *fp = NULL; isc_result_t result; journal_rawheader_t rawheader; @@ -674,7 +685,8 @@ journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write, isc_result_t dns_journal_open(isc_mem_t *mctx, const char *filename, unsigned int mode, - dns_journal_t **journalp) { + dns_journal_t **journalp) +{ isc_result_t result; int namelen; char backup[1024]; @@ -955,7 +967,7 @@ dns_journal_begin_transaction(dns_journal_t *j) { REQUIRE(DNS_JOURNAL_VALID(j)); REQUIRE(j->state == JOURNAL_STATE_WRITE || - j->state == JOURNAL_STATE_BITWS); + j->state == JOURNAL_STATE_INLINE); /* * Find the file offset where the new transaction should @@ -1079,12 +1091,12 @@ dns_journal_commit(dns_journal_t *j) { REQUIRE(DNS_JOURNAL_VALID(j)); REQUIRE(j->state == JOURNAL_STATE_TRANSACTION || - j->state == JOURNAL_STATE_BITWS); + j->state == JOURNAL_STATE_INLINE); /* * Just write out a updated header. */ - if (j->state == JOURNAL_STATE_BITWS) { + if (j->state == JOURNAL_STATE_INLINE) { CHECK(journal_fsync(j)); journal_header_encode(&j->header, &rawheader); CHECK(journal_seek(j, 0)); @@ -1164,10 +1176,8 @@ dns_journal_commit(dns_journal_t *j) { /* * Update the journal header. */ - if (JOURNAL_EMPTY(&j->header)) { + if (JOURNAL_EMPTY(&j->header)) j->header.begin = j->x.pos[0]; - j->header.bitws = j->header.begin.serial; - } j->header.end = j->x.pos[1]; journal_header_encode(&j->header, &rawheader); CHECK(journal_seek(j, 0)); @@ -1399,7 +1409,7 @@ dns_journal_rollforward2(isc_mem_t *mctx, dns_db_t *db, unsigned int options, REQUIRE(filename != NULL); j = NULL; - result = dns_journal_open(mctx, filename, ISC_FALSE, &j); + result = dns_journal_open(mctx, filename, DNS_JOURNAL_READ, &j); if (result == ISC_R_NOTFOUND) { isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no journal file, but that's OK"); @@ -1432,7 +1442,7 @@ dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file) { REQUIRE(filename != NULL); j = NULL; - result = dns_journal_open(mctx, filename, ISC_FALSE, &j); + result = dns_journal_open(mctx, filename, DNS_JOURNAL_READ, &j); if (result == ISC_R_NOTFOUND) { isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no journal file"); return (DNS_R_NOJOURNAL); @@ -1445,7 +1455,8 @@ dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file) { return (result); } - fprintf(file, "BITWS = %u\n", j->header.bitws); + if (j->header.serialset) + fprintf(file, "Source serial = %u\n", j->header.sourceserial); dns_diff_init(j->mctx, &diff); /* @@ -1539,20 +1550,26 @@ dns_journal_last_serial(dns_journal_t *j) { } void -dns_journal_set_bitws(dns_journal_t *j, isc_uint32_t bitws) { +dns_journal_set_sourceserial(dns_journal_t *j, isc_uint32_t sourceserial) { REQUIRE(j->state == JOURNAL_STATE_WRITE || - j->state == JOURNAL_STATE_BITWS || + j->state == JOURNAL_STATE_INLINE || j->state == JOURNAL_STATE_TRANSACTION); - j->header.bitws = bitws; + j->header.sourceserial = sourceserial; + j->header.serialset = ISC_TRUE; if (j->state == JOURNAL_STATE_WRITE) - j->state = JOURNAL_STATE_BITWS; + j->state = JOURNAL_STATE_INLINE; } -isc_uint32_t -dns_journal_get_bitws(dns_journal_t *j) { - return (j->header.bitws); +isc_boolean_t +dns_journal_get_sourceserial(dns_journal_t *j, isc_uint32_t *sourceserial) { + REQUIRE(sourceserial != NULL); + + if (!j->header.serialset) + return (ISC_FALSE); + *sourceserial = j->header.sourceserial; + return (ISC_TRUE); } /**************************************************************************/ @@ -1910,8 +1927,7 @@ dns_diff_subtract(dns_diff_t diff[2], dns_diff_t *r) { } static isc_result_t -diff_namespace(isc_mem_t *mctx, - dns_db_t *dba, dns_dbversion_t *dbvera, +diff_namespace(dns_db_t *dba, dns_dbversion_t *dbvera, dns_db_t *dbb, dns_dbversion_t *dbverb, unsigned int options, dns_diff_t *resultdiff) { @@ -1927,8 +1943,8 @@ diff_namespace(isc_mem_t *mctx, db[0] = dba, db[1] = dbb; ver[0] = dbvera, ver[1] = dbverb; - dns_diff_init(mctx, &diff[0]); - dns_diff_init(mctx, &diff[1]); + dns_diff_init(resultdiff->mctx, &diff[0]); + dns_diff_init(resultdiff->mctx, &diff[1]); dns_fixedname_init(&fixname[0]); dns_fixedname_init(&fixname[1]); @@ -2006,8 +2022,11 @@ diff_namespace(isc_mem_t *mctx, failure: dns_dbiterator_destroy(&dbit[1]); + cleanup_iterator: dns_dbiterator_destroy(&dbit[0]); + dns_diff_clear(&diff[0]); + dns_diff_clear(&diff[1]); return (result); } @@ -2018,33 +2037,48 @@ diff_namespace(isc_mem_t *mctx, * possibly very large transaction. */ isc_result_t -dns_db_diff(isc_mem_t *mctx, - dns_db_t *dba, dns_dbversion_t *dbvera, - dns_db_t *dbb, dns_dbversion_t *dbverb, - const char *journal_filename) +dns_db_diff(isc_mem_t *mctx, dns_db_t *dba, dns_dbversion_t *dbvera, + dns_db_t *dbb, dns_dbversion_t *dbverb, const char *filename) +{ + isc_result_t result; + dns_diff_t diff; + + dns_diff_init(mctx, &diff); + + result = dns_db_diffx(&diff, dba, dbvera, dbb, dbverb, filename); + + dns_diff_clear(&diff); + + return (result); +} + +isc_result_t +dns_db_diffx(dns_diff_t *diff, dns_db_t *dba, dns_dbversion_t *dbvera, + dns_db_t *dbb, dns_dbversion_t *dbverb, const char *filename) { isc_result_t result; dns_journal_t *journal = NULL; - dns_diff_t resultdiff; - result = dns_journal_open(mctx, journal_filename, ISC_TRUE, &journal); - if (result != ISC_R_SUCCESS) - return (result); + if (filename != NULL) { + result = dns_journal_open(diff->mctx, filename, + DNS_JOURNAL_CREATE, &journal); + if (result != ISC_R_SUCCESS) + return (result); + } - dns_diff_init(mctx, &resultdiff); + CHECK(diff_namespace(dba, dbvera, dbb, dbverb, DNS_DB_NONSEC3, diff)); + CHECK(diff_namespace(dba, dbvera, dbb, dbverb, DNS_DB_NSEC3ONLY, diff)); - CHECK(diff_namespace(mctx, dba, dbvera, dbb, dbverb, - DNS_DB_NONSEC3, &resultdiff)); - CHECK(diff_namespace(mctx, dba, dbvera, dbb, dbverb, - DNS_DB_NSEC3ONLY, &resultdiff)); - if (ISC_LIST_EMPTY(resultdiff.tuples)) { - isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no changes"); - } else { - CHECK(dns_journal_write_transaction(journal, &resultdiff)); + if (journal != NULL) { + if (ISC_LIST_EMPTY(diff->tuples)) + isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no changes"); + else + CHECK(dns_journal_write_transaction(journal, diff)); } + failure: - dns_diff_clear(&resultdiff); - dns_journal_destroy(&journal); + if (journal != NULL) + dns_journal_destroy(&journal); return (result); } @@ -2195,7 +2229,8 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial, new->header.begin.offset = indexend; new->header.end.serial = j->header.end.serial; new->header.end.offset = indexend + copy_length; - new->header.bitws = j->header.bitws; + new->header.sourceserial = j->header.sourceserial; + new->header.serialset = j->header.serialset; /* * Update the journal header. diff --git a/lib/dns/master.c b/lib/dns/master.c index d6ac002a..4e1f274e 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: master.c,v 1.180 2011-03-12 04:59:48 tbox Exp $ */ +/* $Id: master.c,v 1.181 2011-12-08 16:07:20 each Exp $ */ /*! \file */ @@ -133,6 +133,7 @@ struct dns_loadctx { /* Members specific to the raw format: */ FILE *f; isc_boolean_t first; + dns_masterrawheader_t header; /* Which fixed buffers we are using? */ unsigned int loop_cnt; /*% records per quantum, @@ -595,6 +596,7 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx, lctx->f = NULL; lctx->first = ISC_TRUE; + dns_master_initrawheader(&lctx->header); lctx->loop_cnt = (done != NULL) ? 100 : 0; lctx->callbacks = callbacks; @@ -2086,48 +2088,72 @@ load_raw(dns_loadctx_t *lctx) { int target_size = TSIZ; isc_buffer_t target; unsigned char *target_mem = NULL; + dns_masterrawheader_t header; REQUIRE(DNS_LCTX_VALID(lctx)); callbacks = lctx->callbacks; + dns_master_initrawheader(&header); + if (lctx->first) { - dns_masterrawheader_t header; - isc_uint32_t format, version, dumptime; - size_t hdrlen = sizeof(format) + sizeof(version) + - sizeof(dumptime); + unsigned char data[sizeof(header)]; + size_t commonlen = + sizeof(header.format) + sizeof(header.version); + size_t remainder; - INSIST(hdrlen <= sizeof(header)); - isc_buffer_init(&target, &header, sizeof(header)); + INSIST(commonlen <= sizeof(header)); + isc_buffer_init(&target, data, sizeof(data)); - result = isc_stdio_read(&header, 1, hdrlen, lctx->f, NULL); + result = isc_stdio_read(data, 1, commonlen, lctx->f, NULL); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_stdio_read failed: %s", isc_result_totext(result)); return (result); } - isc_buffer_add(&target, hdrlen); - format = isc_buffer_getuint32(&target); - if (format != dns_masterformat_raw) { + isc_buffer_add(&target, commonlen); + header.format = isc_buffer_getuint32(&target); + if (header.format != dns_masterformat_raw) { (*callbacks->error)(callbacks, "dns_master_load: " "file format mismatch"); return (ISC_R_NOTIMPLEMENTED); } - version = isc_buffer_getuint32(&target); - if (version > DNS_RAWFORMAT_VERSION) { + header.version = isc_buffer_getuint32(&target); + switch (header.version) { + case 0: + remainder = sizeof(header.dumptime); + break; + case DNS_RAWFORMAT_VERSION: + remainder = sizeof(header) - commonlen; + break; + default: (*callbacks->error)(callbacks, "dns_master_load: " "unsupported file format version"); return (ISC_R_NOTIMPLEMENTED); } - /* Empty read: currently, we do not use dumptime */ - dumptime = isc_buffer_getuint32(&target); - POST(dumptime); + result = isc_stdio_read(data + commonlen, 1, remainder, + lctx->f, NULL); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_stdio_read failed: %s", + isc_result_totext(result)); + return (result); + } + + isc_buffer_add(&target, remainder); + header.dumptime = isc_buffer_getuint32(&target); + if (header.version == DNS_RAWFORMAT_VERSION) { + header.flags = isc_buffer_getuint32(&target); + header.sourceserial = isc_buffer_getuint32(&target); + header.lastxfrin = isc_buffer_getuint32(&target); + } lctx->first = ISC_FALSE; + lctx->header = header; } ISC_LIST_INIT(head); @@ -2353,6 +2379,9 @@ load_raw(dns_loadctx_t *lctx) { } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) result = lctx->result; + if (result == ISC_R_SUCCESS && callbacks->rawdata != NULL) + (*callbacks->rawdata)(callbacks->zone, &header); + cleanup: if (rdata != NULL) isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata)); @@ -2935,3 +2964,8 @@ dns_loadctx_cancel(dns_loadctx_t *lctx) { lctx->canceled = ISC_TRUE; UNLOCK(&lctx->lock); } + +void +dns_master_initrawheader(dns_masterrawheader_t *header) { + memset(header, 0, sizeof(dns_masterrawheader_t)); +} diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index 93e07054..7705026a 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: masterdump.c,v 1.110 2011-11-07 23:16:31 each Exp $ */ +/* $Id: masterdump.c,v 1.113 2011-12-20 00:06:53 marka Exp $ */ /*! \file */ @@ -188,6 +188,7 @@ struct dns_dumpctx { char *file; char *tmpfile; dns_masterformat_t format; + dns_masterrawheader_t header; isc_result_t (*dumpsets)(isc_mem_t *mctx, dns_name_t *name, dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx, @@ -931,6 +932,7 @@ dump_rdataset_raw(isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *rdataset, REQUIRE(buffer->length > 0); REQUIRE(DNS_RDATASET_VALID(rdataset)); + rdataset->attributes |= DNS_RDATASETATTR_LOADORDER; restart: totallen = 0; result = dns_rdataset_first(rdataset); @@ -1265,7 +1267,7 @@ task_send(dns_dumpctx_t *dctx) { static isc_result_t dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, FILE *f, dns_dumpctx_t **dctxp, - dns_masterformat_t format) + dns_masterformat_t format, dns_masterrawheader_t *header) { dns_dumpctx_t *dctx; isc_result_t result; @@ -1289,6 +1291,10 @@ dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, dctx->file = NULL; dctx->tmpfile = NULL; dctx->format = format; + if (header == NULL) + dns_master_initrawheader(&dctx->header); + else + dctx->header = *header; switch (format) { case dns_masterformat_text: @@ -1356,7 +1362,7 @@ dumptostreaminc(dns_dumpctx_t *dctx) { dns_fixedname_t fixname; unsigned int nodes; dns_masterrawheader_t rawheader; - isc_uint32_t now32; + isc_uint32_t rawversion, now32; isc_time_t start; bufmem = isc_mem_get(dctx->mctx, initial_buffer_length); @@ -1391,8 +1397,6 @@ dumptostreaminc(dns_dumpctx_t *dctx) { r.base = (unsigned char *)&rawheader; r.length = sizeof(rawheader); isc_buffer_region(&buffer, &r); - isc_buffer_putuint32(&buffer, dns_masterformat_raw); - isc_buffer_putuint32(&buffer, DNS_RAWFORMAT_VERSION); #if !defined(STDTIME_ON_32BITS) || (STDTIME_ON_32BITS + 0) != 1 /* * We assume isc_stdtime_t is a 32-bit integer, @@ -1411,7 +1415,22 @@ dumptostreaminc(dns_dumpctx_t *dctx) { #else now32 = dctx->now; #endif + rawversion = 1; + if ((dctx->header.flags & DNS_MASTERRAW_COMPAT) != 0) + rawversion = 0; + isc_buffer_putuint32(&buffer, dns_masterformat_raw); + isc_buffer_putuint32(&buffer, rawversion); isc_buffer_putuint32(&buffer, now32); + + if (rawversion == 1) { + isc_buffer_putuint32(&buffer, + dctx->header.flags); + isc_buffer_putuint32(&buffer, + dctx->header.sourceserial); + isc_buffer_putuint32(&buffer, + dctx->header.lastxfrin); + } + INSIST(isc_buffer_usedlength(&buffer) <= sizeof(rawheader)); result = isc_stdio_write(buffer.base, 1, @@ -1530,7 +1549,7 @@ dns_master_dumptostreaminc(isc_mem_t *mctx, dns_db_t *db, REQUIRE(done != NULL); result = dumpctx_create(mctx, db, version, style, f, &dctx, - dns_masterformat_text); + dns_masterformat_text, NULL); if (result != ISC_R_SUCCESS) return (result); isc_task_attach(task, &dctx->task); @@ -1557,8 +1576,8 @@ dns_master_dumptostream(isc_mem_t *mctx, dns_db_t *db, const dns_master_style_t *style, FILE *f) { - return (dns_master_dumptostream2(mctx, db, version, style, - dns_masterformat_text, f)); + return (dns_master_dumptostream3(mctx, db, version, style, + dns_masterformat_text, NULL, f)); } isc_result_t @@ -1567,10 +1586,22 @@ dns_master_dumptostream2(isc_mem_t *mctx, dns_db_t *db, const dns_master_style_t *style, dns_masterformat_t format, FILE *f) { + return (dns_master_dumptostream3(mctx, db, version, style, + format, NULL, f)); +} + +isc_result_t +dns_master_dumptostream3(isc_mem_t *mctx, dns_db_t *db, + dns_dbversion_t *version, + const dns_master_style_t *style, + dns_masterformat_t format, + dns_masterrawheader_t *header, FILE *f) +{ dns_dumpctx_t *dctx = NULL; isc_result_t result; - result = dumpctx_create(mctx, db, version, style, f, &dctx, format); + result = dumpctx_create(mctx, db, version, style, f, &dctx, + format, header); if (result != ISC_R_SUCCESS) return (result); @@ -1621,9 +1652,9 @@ dns_master_dumpinc(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg, dns_dumpctx_t **dctxp) { - return (dns_master_dumpinc2(mctx, db, version, style, filename, task, + return (dns_master_dumpinc3(mctx, db, version, style, filename, task, done, done_arg, dctxp, - dns_masterformat_text)); + dns_masterformat_text, NULL)); } isc_result_t @@ -1632,6 +1663,17 @@ dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg, dns_dumpctx_t **dctxp, dns_masterformat_t format) { + return (dns_master_dumpinc3(mctx, db, version, style, filename, task, + done, done_arg, dctxp, format, NULL)); +} + +isc_result_t +dns_master_dumpinc3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, + const dns_master_style_t *style, const char *filename, + isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg, + dns_dumpctx_t **dctxp, dns_masterformat_t format, + dns_masterrawheader_t *header) +{ FILE *f = NULL; isc_result_t result; char *tempname = NULL; @@ -1646,7 +1688,8 @@ dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, if (result != ISC_R_SUCCESS) goto cleanup; - result = dumpctx_create(mctx, db, version, style, f, &dctx, format); + result = dumpctx_create(mctx, db, version, style, f, &dctx, + format, header); if (result != ISC_R_SUCCESS) { (void)isc_stdio_close(f); (void)isc_file_remove(tempname); @@ -1682,8 +1725,8 @@ isc_result_t dns_master_dump(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, const char *filename) { - return (dns_master_dump2(mctx, db, version, style, filename, - dns_masterformat_text)); + return (dns_master_dump3(mctx, db, version, style, filename, + dns_masterformat_text, NULL)); } isc_result_t @@ -1691,6 +1734,15 @@ dns_master_dump2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, const char *filename, dns_masterformat_t format) { + return (dns_master_dump3(mctx, db, version, style, filename, + format, NULL)); +} + +isc_result_t +dns_master_dump3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, + const dns_master_style_t *style, const char *filename, + dns_masterformat_t format, dns_masterrawheader_t *header) +{ FILE *f = NULL; isc_result_t result; char *tempname; @@ -1700,7 +1752,8 @@ dns_master_dump2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, if (result != ISC_R_SUCCESS) return (result); - result = dumpctx_create(mctx, db, version, style, f, &dctx, format); + result = dumpctx_create(mctx, db, version, style, f, &dctx, + format, header); if (result != ISC_R_SUCCESS) goto cleanup; diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index fbbdcb93..7091a399 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.322 2011-11-18 18:40:31 each Exp $ */ +/* $Id: rbtdb.c,v 1.323 2011-12-07 22:21:05 marka Exp $ */ /*! \file */ @@ -2003,9 +2003,9 @@ iszonesecure(dns_db_t *db, rbtdb_version_t *version, dns_dbnode_t *origin) { result = dns_db_findrdataset(db, origin, version, dns_rdatatype_dnskey, 0, 0, &keyset, NULL); if (result == ISC_R_SUCCESS) { - dns_rdata_t keyrdata = DNS_RDATA_INIT; result = dns_rdataset_first(&keyset); while (result == ISC_R_SUCCESS) { + dns_rdata_t keyrdata = DNS_RDATA_INIT; dns_rdataset_current(&keyset, &keyrdata); if (dns_zonekey_iszonekey(&keyrdata)) { haszonekey = ISC_TRUE; diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index 08a12619..eb43935e 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdata.c,v 1.214 2011-11-02 01:01:52 marka Exp $ */ +/* $Id: rdata.c,v 1.215 2011-12-22 07:41:29 marka Exp $ */ /*! \file */ @@ -1138,7 +1138,8 @@ txt_fromtext(isc_textregion_t *source, isc_buffer_t *target) { } escape = ISC_FALSE; if (nrem == 0) - return (ISC_R_NOSPACE); + return ((tregion.length <= 256U) ? + ISC_R_NOSPACE : DNS_R_SYNTAX); *t++ = c; nrem--; } diff --git a/lib/dns/rdata/in_1/wks_11.c b/lib/dns/rdata/in_1/wks_11.c index 29983ec1..fff9da81 100644 --- a/lib/dns/rdata/in_1/wks_11.c +++ b/lib/dns/rdata/in_1/wks_11.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009, 2011 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: wks_11.c,v 1.57 2009-12-04 21:09:34 marka Exp $ */ +/* $Id: wks_11.c,v 1.59 2011-11-30 23:46:25 tbox Exp $ */ /* Reviewed: Fri Mar 17 15:01:49 PST 2000 by explorer */ @@ -27,16 +27,46 @@ #include <isc/net.h> #include <isc/netdb.h> +#include <isc/once.h> #define RRTYPE_WKS_ATTRIBUTES (0) +static isc_mutex_t wks_lock; + +static void init_lock(void) { + RUNTIME_CHECK(isc_mutex_init(&wks_lock) == ISC_R_SUCCESS); +} + +static isc_boolean_t +mygetprotobyname(const char *name, long *proto) { + struct protoent *pe; + + LOCK(&wks_lock); + pe = getprotobyname(name); + if (pe != NULL) + *proto = pe->p_proto; + UNLOCK(&wks_lock); + return (ISC_TF(pe != NULL)); +} + +static isc_boolean_t +mygetservbyname(const char *name, const char *proto, long *port) { + struct servent *se; + + LOCK(&wks_lock); + se = getservbyname(name, proto); + if (se != NULL) + *port = ntohs(se->s_port); + UNLOCK(&wks_lock); + return (ISC_TF(se != NULL)); +} + static inline isc_result_t fromtext_in_wks(ARGS_FROMTEXT) { + static isc_once_t once = ISC_ONCE_INIT; isc_token_t token; isc_region_t region; struct in_addr addr; - struct protoent *pe; - struct servent *se; char *e; long proto; unsigned char bm[8*1024]; /* 64k bits */ @@ -55,6 +85,8 @@ fromtext_in_wks(ARGS_FROMTEXT) { UNUSED(options); UNUSED(rdclass); + RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS); + /* * IPv4 dotted quad. */ @@ -78,10 +110,9 @@ fromtext_in_wks(ARGS_FROMTEXT) { proto = strtol(DNS_AS_STR(token), &e, 10); if (*e == 0) ; - else if ((pe = getprotobyname(DNS_AS_STR(token))) != NULL) - proto = pe->p_proto; - else + else if (!mygetprotobyname(DNS_AS_STR(token), &proto)) RETTOK(DNS_R_UNKNOWNPROTO); + if (proto < 0 || proto > 0xff) RETTOK(ISC_R_RANGE); @@ -112,12 +143,8 @@ fromtext_in_wks(ARGS_FROMTEXT) { port = strtol(DNS_AS_STR(token), &e, 10); if (*e == 0) ; - else if ((se = getservbyname(service, ps)) != NULL) - port = ntohs(se->s_port); - else if ((se = getservbyname(DNS_AS_STR(token), ps)) - != NULL) - port = ntohs(se->s_port); - else + else if (!mygetservbyname(service, ps, &port) && + !mygetservbyname(DNS_AS_STR(token), ps, &port)) RETTOK(DNS_R_UNKNOWNSERVICE); if (port < 0 || port > 0xffff) RETTOK(ISC_R_RANGE); diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c index 1b20bd52..d4fce614 100644 --- a/lib/dns/rdataslab.c +++ b/lib/dns/rdataslab.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdataslab.c,v 1.54 2011-02-03 12:18:11 tbox Exp $ */ +/* $Id: rdataslab.c,v 1.55 2011-12-20 00:55:01 marka Exp $ */ /*! \file */ @@ -53,6 +53,7 @@ * record count (2 bytes) * data records * data length (2 bytes) + * meta data (1 byte for RRSIG's) * data (data length bytes) * * Offsets are from the end of the header. diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 6b64461b..c97aa780 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.442 2011-11-16 22:18:52 marka Exp $ */ +/* $Id: resolver.c,v 1.446 2011-12-07 23:08:42 marka Exp $ */ /*! \file */ @@ -453,7 +453,7 @@ static isc_result_t ncache_adderesult(dns_message_t *message, dns_rdataset_t *ardataset, isc_result_t *eresultp); static void validated(isc_task_t *task, isc_event_t *event); -static void maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked); +static isc_boolean_t maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked); static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason, badnstype_t badtype); @@ -746,8 +746,11 @@ resquery_destroy(resquery_t **queryp) { INSIST(query->tcpsocket == NULL); query->fctx->nqueries--; - if (SHUTTINGDOWN(query->fctx)) - maybe_destroy(query->fctx, ISC_FALSE); /* Locks bucket. */ + if (SHUTTINGDOWN(query->fctx)) { + dns_resolver_t *res = query->fctx->res; + if (maybe_destroy(query->fctx, ISC_FALSE)) + empty_bucket(res); + } query->magic = 0; isc_mem_put(query->mctx, query, sizeof(*query)); *queryp = NULL; @@ -1324,9 +1327,7 @@ fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) { * We retry every .8 seconds the first two times through the address * list, and then we do exponential back-off. */ - if (fctx->restarts == 0) - us = 400000; - else if (fctx->restarts < 3) + if (fctx->restarts < 3) us = 800000; else us = (800000 << (fctx->restarts - 2)); @@ -1687,8 +1688,6 @@ resquery_send(resquery_t *query) { isc_boolean_t cleanup_cctx = ISC_FALSE; isc_boolean_t secure_domain; isc_boolean_t connecting = ISC_FALSE; - unsigned int edns_fetchopt_flag; - isc_stdtime_t now; fctx = query->fctx; QTRACE("send"); @@ -1799,16 +1798,6 @@ resquery_send(resquery_t *query) { (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer); /* - * Get the fetchopt flag for this server from the adb cache - * NOTE: if the NOEDNS flag has been set on addrinfo->flags, - * it will over write this below. - */ - isc_stdtime_get(&now); - edns_fetchopt_flag = dns_adb_getednsflag(fctx->adb, query->addrinfo, - now); - query->options |= edns_fetchopt_flag; - - /* * The ADB does not know about servers with "edns no". Check this, * and then inform the ADB for future use. */ @@ -1842,24 +1831,17 @@ resquery_send(resquery_t *query) { * * packet loss / link outage. */ if (fctx->timeout) { - if ((triededns512(fctx, &query->addrinfo->sockaddr) && - fctx->timeouts > MAX_EDNS0_TIMEOUTS) && + if ((triededns512(fctx, &query->addrinfo->sockaddr) || + fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) && (query->options & DNS_FETCHOPT_NOEDNS0) == 0) { query->options |= DNS_FETCHOPT_NOEDNS0; - query->options |= DNS_FETCHOPT_CACHENOEDNS; fctx->reason = "disabling EDNS"; } else if ((triededns(fctx, &query->addrinfo->sockaddr) || - fctx->timeouts >= 1) && + fctx->timeouts >= MAX_EDNS0_TIMEOUTS) && (query->options & DNS_FETCHOPT_NOEDNS0) == 0) { query->options |= DNS_FETCHOPT_EDNS512; - if (edns_fetchopt_flag != DNS_FETCHOPT_EDNS512) { - dns_adb_dropednssize(fctx->adb, query->addrinfo, - 512, now); - fctx->reason = "reducing the advertised EDNS " - "UDP packet size to 512 octets"; - } else - fctx->reason = "continuing to use lower EDNS " - "UDP packet size of 512 octets"; + fctx->reason = "reducing the advertised EDNS UDP " + "packet size to 512 octets"; } fctx->timeout = ISC_FALSE; } @@ -1918,12 +1900,11 @@ resquery_send(resquery_t *query) { goto cleanup_message; } - if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) { + if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) add_triededns(fctx, &query->addrinfo->sockaddr); - if ((query->options & DNS_FETCHOPT_EDNS512) != 0) - add_triededns512(fctx, &query->addrinfo->sockaddr); - } + if ((query->options & DNS_FETCHOPT_EDNS512) != 0) + add_triededns512(fctx, &query->addrinfo->sockaddr); /* * Clear CD if EDNS is not in use. @@ -2183,6 +2164,7 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) { isc_boolean_t want_try = ISC_FALSE; isc_boolean_t want_done = ISC_FALSE; isc_boolean_t bucket_empty = ISC_FALSE; + isc_boolean_t destroy = ISC_FALSE; unsigned int bucketnum; find = event->ev_sender; @@ -2194,6 +2176,9 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) { FCTXTRACE("finddone"); + bucketnum = fctx->bucketnum; + LOCK(&res->buckets[bucketnum].lock); + INSIST(fctx->pending > 0); fctx->pending--; @@ -2218,17 +2203,17 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) { } } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 && fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) { - bucketnum = fctx->bucketnum; - LOCK(&res->buckets[bucketnum].lock); /* * Note that we had to wait until we had the lock before * looking at fctx->references. */ if (fctx->references == 0) - bucket_empty = fctx_destroy(fctx); - UNLOCK(&res->buckets[bucketnum].lock); + destroy = ISC_TRUE; } + UNLOCK(&res->buckets[bucketnum].lock); + if (destroy) + bucket_empty = fctx_destroy(fctx); isc_event_free(&event); dns_adb_destroyfind(&find); @@ -3911,13 +3896,15 @@ clone_results(fetchctx_t *fctx) { /* * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has - * no references and is no longer waiting for any events). If this - * was the last fctx in the resolver, destroy the resolver. + * no references and is no longer waiting for any events). * * Requires: * '*fctx' is shutting down. + * + * Returns: + * true if the resolver is exiting and this is the last fctx in the bucket. */ -static void +static isc_boolean_t maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) { unsigned int bucketnum; isc_boolean_t bucket_empty = ISC_FALSE; @@ -3926,8 +3913,11 @@ maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) { REQUIRE(SHUTTINGDOWN(fctx)); + bucketnum = fctx->bucketnum; + if (!locked) + LOCK(&res->buckets[bucketnum].lock); if (fctx->pending != 0 || fctx->nqueries != 0) - return; + goto unlock; for (validator = ISC_LIST_HEAD(fctx->validators); validator != NULL; validator = next_validator) { @@ -3935,16 +3925,12 @@ maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) { dns_validator_cancel(validator); } - bucketnum = fctx->bucketnum; - if (!locked) - LOCK(&res->buckets[bucketnum].lock); if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators)) bucket_empty = fctx_destroy(fctx); + unlock: if (!locked) UNLOCK(&res->buckets[bucketnum].lock); - - if (bucket_empty) - empty_bucket(res); + return (bucket_empty); } /* @@ -3952,31 +3938,33 @@ maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) { */ static void validated(isc_task_t *task, isc_event_t *event) { - isc_result_t result = ISC_R_SUCCESS; - isc_result_t eresult = ISC_R_SUCCESS; - isc_stdtime_t now; - fetchctx_t *fctx; - dns_validatorevent_t *vevent; - dns_fetchevent_t *hevent; - dns_rdataset_t *ardataset = NULL; - dns_rdataset_t *asigrdataset = NULL; + dns_adbaddrinfo_t *addrinfo; dns_dbnode_t *node = NULL; - isc_boolean_t negative; - isc_boolean_t chaining; - isc_boolean_t sentresponse; - isc_uint32_t ttl; dns_dbnode_t *nsnode = NULL; + dns_fetchevent_t *hevent; dns_name_t *name; + dns_rdataset_t *ardataset = NULL; + dns_rdataset_t *asigrdataset = NULL; dns_rdataset_t *rdataset; dns_rdataset_t *sigrdataset; + dns_resolver_t *res; dns_valarg_t *valarg; - dns_adbaddrinfo_t *addrinfo; + dns_validatorevent_t *vevent; + fetchctx_t *fctx; + isc_boolean_t chaining; + isc_boolean_t negative; + isc_boolean_t sentresponse; + isc_result_t eresult = ISC_R_SUCCESS; + isc_result_t result = ISC_R_SUCCESS; + isc_stdtime_t now; + isc_uint32_t ttl; UNUSED(task); /* for now */ REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE); valarg = event->ev_arg; fctx = valarg->fctx; + res = fctx->res; addrinfo = valarg->addrinfo; REQUIRE(VALID_FCTX(fctx)); REQUIRE(!ISC_LIST_EMPTY(fctx->validators)); @@ -3986,7 +3974,7 @@ validated(isc_task_t *task, isc_event_t *event) { FCTXTRACE("received validation completion event"); - LOCK(&fctx->res->buckets[fctx->bucketnum].lock); + LOCK(&res->buckets[fctx->bucketnum].lock); ISC_LIST_UNLINK(fctx->validators, vevent->validator, link); fctx->validator = NULL; @@ -3996,7 +3984,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->buckets[fctx->bucketnum].mctx, + isc_mem_put(res->buckets[fctx->bucketnum].mctx, valarg, sizeof(*valarg)); negative = ISC_TF(vevent->rdataset == NULL); @@ -4009,8 +3997,12 @@ validated(isc_task_t *task, isc_event_t *event) { * so, destroy the fctx. */ if (SHUTTINGDOWN(fctx) && !sentresponse) { - maybe_destroy(fctx, ISC_TRUE); - UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); + isc_uint32_t bucketnum = fctx->bucketnum; + isc_boolean_t bucket_empty; + bucket_empty = maybe_destroy(fctx, ISC_TRUE); + UNLOCK(&res->buckets[bucketnum].lock); + if (bucket_empty) + empty_bucket(res); goto cleanup_event; } @@ -4059,7 +4051,7 @@ validated(isc_task_t *task, isc_event_t *event) { if (vevent->result != ISC_R_SUCCESS) { FCTXTRACE("validation failed"); - inc_stats(fctx->res, dns_resstatscounter_valfail); + inc_stats(res, dns_resstatscounter_valfail); fctx->valfail++; fctx->vresult = vevent->result; if (fctx->vresult != DNS_R_BROKENCHAIN) { @@ -4108,7 +4100,7 @@ validated(isc_task_t *task, isc_event_t *event) { result = fctx->vresult; add_bad(fctx, addrinfo, result, badns_validation); isc_event_free(&event); - UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); + UNLOCK(&res->buckets[fctx->bucketnum].lock); INSIST(fctx->validator == NULL); fctx->validator = ISC_LIST_HEAD(fctx->validators); if (fctx->validator != NULL) @@ -4127,8 +4119,7 @@ validated(isc_task_t *task, isc_event_t *event) { fctx->type == dns_rdatatype_dlv || fctx->type == dns_rdatatype_ds) && tresult == ISC_R_SUCCESS) - dns_resolver_addbadcache(fctx->res, - &fctx->name, + dns_resolver_addbadcache(res, &fctx->name, fctx->type, &expire); fctx_done(fctx, result, __LINE__); /* Locks bucket. */ } else @@ -4141,7 +4132,7 @@ validated(isc_task_t *task, isc_event_t *event) { dns_rdatatype_t covers; FCTXTRACE("nonexistence validation OK"); - inc_stats(fctx->res, dns_resstatscounter_valnegsuccess); + inc_stats(res, dns_resstatscounter_valnegsuccess); if (fctx->rmessage->rcode == dns_rcode_nxdomain) covers = dns_rdatatype_any; @@ -4158,10 +4149,9 @@ validated(isc_task_t *task, isc_event_t *event) { * to zero to facilitate locating the containing zone of * a arbitrary zone. */ - ttl = fctx->res->view->maxncachettl; + ttl = res->view->maxncachettl; if (fctx->type == dns_rdatatype_soa && - covers == dns_rdatatype_any && - fctx->res->zero_no_soa_ttl) + covers == dns_rdatatype_any && res->zero_no_soa_ttl) ttl = 0; result = ncache_adderesult(fctx->rmessage, fctx->cache, node, @@ -4171,7 +4161,7 @@ validated(isc_task_t *task, isc_event_t *event) { goto noanswer_response; goto answer_response; } else - inc_stats(fctx->res, dns_resstatscounter_valsuccess); + inc_stats(res, dns_resstatscounter_valsuccess); FCTXTRACE("validation OK"); @@ -4219,14 +4209,17 @@ validated(isc_task_t *task, isc_event_t *event) { } if (sentresponse) { + isc_boolean_t bucket_empty = ISC_FALSE; /* * If we only deferred the destroy because we wanted to cache * the data, destroy now. */ dns_db_detachnode(fctx->cache, &node); - UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); if (SHUTTINGDOWN(fctx)) - maybe_destroy(fctx, ISC_FALSE); /* Locks bucket. */ + bucket_empty = maybe_destroy(fctx, ISC_TRUE); + UNLOCK(&res->buckets[fctx->bucketnum].lock); + if (bucket_empty) + empty_bucket(res); goto cleanup_event; } @@ -4241,7 +4234,7 @@ validated(isc_task_t *task, isc_event_t *event) { * be validated. */ dns_db_detachnode(fctx->cache, &node); - UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); + UNLOCK(&res->buckets[fctx->bucketnum].lock); dns_validator_send(ISC_LIST_HEAD(fctx->validators)); goto cleanup_event; } @@ -4316,7 +4309,7 @@ validated(isc_task_t *task, isc_event_t *event) { if (node != NULL) dns_db_detachnode(fctx->cache, &node); - UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); + UNLOCK(&res->buckets[fctx->bucketnum].lock); fctx_done(fctx, result, __LINE__); /* Locks bucket. */ cleanup_event: @@ -6580,25 +6573,6 @@ resquery_response(isc_task_t *task, isc_event_t *event) { } } goto done; -#if 0 - } else if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0 && - (query->options & DNS_FETCHOPT_CACHENOEDNS) != 0 && - triededns512(fctx, &query->addrinfo->sockaddr)) { - char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf, - sizeof(addrbuf)); - /* - * We had a successful response to a DNS_FETCHOPT_NOEDNS0 - * query. - */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_EDNS_DISABLED, - DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, - "%s: setting NOEDNS flag in adb cache for '%s'", - fctx->info, addrbuf); - dns_adb_changeflags(fctx->adb, query->addrinfo, - DNS_FETCHOPT_NOEDNS0, - DNS_FETCHOPT_NOEDNS0); -#endif } message = fctx->rmessage; @@ -6742,10 +6716,6 @@ resquery_response(isc_task_t *task, isc_event_t *event) { char addrbuf[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf, sizeof(addrbuf)); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_EDNS_DISABLED, - DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, - "%s: changed rcode: setting NOEDNS flag in " - "adb cache for '%s'", fctx->info, addrbuf); dns_adb_changeflags(fctx->adb, query->addrinfo, DNS_FETCHOPT_NOEDNS0, DNS_FETCHOPT_NOEDNS0); @@ -6918,16 +6888,6 @@ resquery_response(isc_task_t *task, isc_event_t *event) { } /* - * Update the packet received sizes - */ - if (((query->options & DNS_FETCHOPT_NOEDNS0) == 0) && - ((devent->attributes & DNS_DISPATCHATTR_UDP) != 0)) - dns_adb_setednssize(fctx->adb, - query->addrinfo, - devent->buffer.length); - - - /* * Enforce delegations only zones like NET and COM. */ if (!ISFORWARDER(query->addrinfo) && diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index 107bf43f..35c88c9b 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdlz.c,v 1.34 2011-10-11 00:09:03 each Exp $ */ +/* $Id: sdlz.c,v 1.35 2011-12-22 07:15:05 marka Exp $ */ /*! \file */ @@ -1860,7 +1860,11 @@ dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl, &lookup->callbacks); if (result != ISC_R_SUCCESS) isc_buffer_free(&rdatabuf); + if (size >= 65535) + break; size *= 2; + if (size >= 65535) + size = 65535; } while (result == ISC_R_NOSPACE); if (result != ISC_R_SUCCESS) diff --git a/lib/dns/tests/Makefile.in b/lib/dns/tests/Makefile.in index 17d0ca5d..8e802d73 100644 --- a/lib/dns/tests/Makefile.in +++ b/lib/dns/tests/Makefile.in @@ -12,7 +12,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.10 2011-10-28 06:20:07 each Exp $ +# $Id: Makefile.in,v 1.12 2011-12-08 16:07:21 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -38,16 +38,23 @@ LIBS = @LIBS@ @ATFLIBS@ OBJS = dnstest.@O@ SRCS = dnstest.c master_test.c dbiterator_test.c time_test.c \ - private_test.c update_test.c zonemgr_test.c zt_test.c + private_test.c update_test.c zonemgr_test.c zt_test.c \ + dbdiff_test.c SUBDIRS = TARGETS = master_test@EXEEXT@ dbiterator_test@EXEEXT@ time_test@EXEEXT@ \ private_test@EXEEXT@ update_test@EXEEXT@ zonemgr_test@EXEEXT@ \ - zt_test@EXEEXT@ dbversion_test@EXEEXT@ + zt_test@EXEEXT@ dbversion_test@EXEEXT@ dbdiff_test@EXEEXT@ @BIND9_MAKE_RULES@ master_test@EXEEXT@: master_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${PERL} mkraw.pl < testdata/master/master12.data.in \ + > testdata/master/master12.data + ${PERL} mkraw.pl < testdata/master/master13.data.in \ + > testdata/master/master13.data + ${PERL} mkraw.pl < testdata/master/master14.data.in \ + > testdata/master/master14.data ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ master_test.@O@ dnstest.@O@ ${DNSLIBS} \ ${ISCLIBS} ${LIBS} @@ -77,6 +84,11 @@ dbiterator_test@EXEEXT@: dbiterator_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPL dbiterator_test.@O@ dnstest.@O@ ${DNSLIBS} \ ${ISCLIBS} ${LIBS} +dbdiff_test@EXEEXT@: dbdiff_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dbdiff_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + dbversion_test@EXEEXT@: dbversion_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ dbversion_test.@O@ dnstest.@O@ ${DNSLIBS} \ @@ -93,3 +105,5 @@ unit:: clean distclean:: rm -f ${TARGETS} rm -f atf.out + rm -f testdata/master/master12.data testdata/master/master13.data \ + testdata/master/master14.data diff --git a/lib/dns/tests/dbdiff_test.c b/lib/dns/tests/dbdiff_test.c new file mode 100644 index 00000000..d787f5c0 --- /dev/null +++ b/lib/dns/tests/dbdiff_test.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2011 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: dbdiff_test.c,v 1.2 2011-12-04 23:48:12 marka Exp $ */ + +/*! \file */ + +#include <config.h> + +#include <atf-c.h> + +#include <unistd.h> +#include <stdlib.h> + +#include <dns/db.h> +#include <dns/dbiterator.h> +#include <dns/name.h> +#include <dns/journal.h> + +#include "dnstest.h" + +/* + * Helper functions + */ + +#define BUFLEN 255 +#define BIGBUFLEN (64 * 1024) +#define TEST_ORIGIN "test" + +static void +test_create(const atf_tc_t *tc, dns_db_t **old, dns_db_t **new) { + isc_result_t result; + + result = dns_test_loaddb(old, dns_dbtype_zone, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-old")); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(new, dns_dbtype_zone, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-new")); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); +} + +/* + * Individual unit tests + */ + +ATF_TC(diffx_same); +ATF_TC_HEAD(diffx_same, tc) { + atf_tc_set_md_var(tc, "descr", "dns_db_diffx of identical content"); + atf_tc_set_md_var(tc, "X-old", "testdata/diff/zone1.data"); + atf_tc_set_md_var(tc, "X-new", "testdata/diff/zone1.data"); } +ATF_TC_BODY(diffx_same, tc) { + dns_db_t *new = NULL, *old = NULL; + isc_result_t result; + dns_diff_t diff; + + result = dns_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + test_create(tc, &old, &new); + + dns_diff_init(mctx, &diff); + + result = dns_db_diffx(&diff, new, NULL, old, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_REQUIRE_EQ(ISC_LIST_EMPTY(diff.tuples), ISC_TRUE); + + dns_diff_clear(&diff); + dns_db_detach(&new); + dns_db_detach(&old); + dns_test_end(); +} + +ATF_TC(diffx_add); +ATF_TC_HEAD(diffx_add, tc) { + atf_tc_set_md_var(tc, "descr", + "dns_db_diffx of zone with record added"); + atf_tc_set_md_var(tc, "X-old", "testdata/diff/zone1.data"); + atf_tc_set_md_var(tc, "X-new", "testdata/diff/zone2.data"); +} +ATF_TC_BODY(diffx_add, tc) { + dns_db_t *new = NULL, *old = NULL; + dns_difftuple_t *tuple; + isc_result_t result; + dns_diff_t diff; + int count = 0; + + result = dns_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + test_create(tc, &old, &new); + + dns_diff_init(mctx, &diff); + + result = dns_db_diffx(&diff, new, NULL, old, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_REQUIRE_EQ(ISC_LIST_EMPTY(diff.tuples), ISC_FALSE); + for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + ATF_REQUIRE_EQ(tuple->op, DNS_DIFFOP_ADD); + count++; + } + ATF_REQUIRE_EQ(count, 1); + + dns_diff_clear(&diff); + dns_db_detach(&new); + dns_db_detach(&old); + dns_test_end(); +} + +ATF_TC(diffx_remove); +ATF_TC_HEAD(diffx_remove, tc) { + atf_tc_set_md_var(tc, "descr", + "dns_db_diffx of zone with record removed"); + atf_tc_set_md_var(tc, "X-old", "testdata/diff/zone1.data"); + atf_tc_set_md_var(tc, "X-new", "testdata/diff/zone3.data"); +} +ATF_TC_BODY(diffx_remove, tc) { + dns_db_t *new = NULL, *old = NULL; + dns_difftuple_t *tuple; + isc_result_t result; + dns_diff_t diff; + int count = 0; + + result = dns_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + test_create(tc, &old, &new); + + dns_diff_init(mctx, &diff); + + result = dns_db_diffx(&diff, new, NULL, old, NULL, NULL); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + ATF_REQUIRE_EQ(ISC_LIST_EMPTY(diff.tuples), ISC_FALSE); + for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + ATF_REQUIRE_EQ(tuple->op, DNS_DIFFOP_DEL); + count++; + } + ATF_REQUIRE_EQ(count, 1); + + dns_diff_clear(&diff); + dns_db_detach(&new); + dns_db_detach(&old); + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, diffx_same); + ATF_TP_ADD_TC(tp, diffx_add); + ATF_TP_ADD_TC(tp, diffx_remove); + return (atf_no_error()); +} diff --git a/lib/dns/tests/dbiterator_test.c b/lib/dns/tests/dbiterator_test.c index 12af6908..00341d55 100644 --- a/lib/dns/tests/dbiterator_test.c +++ b/lib/dns/tests/dbiterator_test.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dbiterator_test.c,v 1.5 2011-08-29 23:44:07 marka Exp $ */ +/* $Id: dbiterator_test.c,v 1.6 2011-12-04 23:48:12 marka Exp $ */ /*! \file */ @@ -40,46 +40,6 @@ #define TEST_ORIGIN "test" static isc_result_t -setup_db(const char *testfile, dns_dbtype_t dbtype, dns_db_t **db) { - isc_result_t result; - int len; - char origin[sizeof(TEST_ORIGIN)]; - dns_name_t dns_origin; - isc_buffer_t source; - isc_buffer_t target; - unsigned char name_buf[BUFLEN]; - - strcpy(origin, TEST_ORIGIN); - len = strlen(origin); - isc_buffer_init(&source, origin, len); - isc_buffer_add(&source, len); - isc_buffer_setactive(&source, len); - isc_buffer_init(&target, name_buf, BUFLEN); - dns_name_init(&dns_origin, NULL); - - result = dns_name_fromtext(&dns_origin, &source, dns_rootname, - 0, &target); - if (result != ISC_R_SUCCESS) - return(result); - - result = dns_db_create(mctx, "rbt", &dns_origin, dbtype, - dns_rdataclass_in, 0, NULL, db); - if (result != ISC_R_SUCCESS) - return (result); - - /* - * atf-run changes us to a /tmp directory, so tests - * that access test data files must first chdir to the proper - * location. - */ - if (chdir(TESTS) == -1) - return (ISC_R_FAILURE); - - result = dns_db_load(*db, testfile); - return (result); -} - -static isc_result_t make_name(const char *src, dns_name_t *name) { isc_buffer_t b; isc_buffer_init(&b, src, strlen(src)); @@ -101,8 +61,8 @@ test_create(const atf_tc_t *tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = setup_db(atf_tc_get_md_var(tc, "X-filename"), - dns_dbtype_cache, &db); + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = dns_db_createiterator(db, 0, &iter); @@ -150,8 +110,8 @@ test_walk(const atf_tc_t *tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = setup_db(atf_tc_get_md_var(tc, "X-filename"), - dns_dbtype_cache, &db); + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = dns_db_createiterator(db, 0, &iter); @@ -213,8 +173,8 @@ static void test_reverse(const atf_tc_t *tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = setup_db(atf_tc_get_md_var(tc, "X-filename"), - dns_dbtype_cache, &db); + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = dns_db_createiterator(db, 0, &iter); @@ -276,8 +236,8 @@ static void test_seek(const atf_tc_t *tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = setup_db(atf_tc_get_md_var(tc, "X-filename"), - dns_dbtype_cache, &db); + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = dns_db_createiterator(db, 0, &iter); @@ -347,8 +307,8 @@ static void test_seek_empty(const atf_tc_t *tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = setup_db(atf_tc_get_md_var(tc, "X-filename"), - dns_dbtype_cache, &db); + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = dns_db_createiterator(db, 0, &iter); @@ -404,8 +364,8 @@ static void test_seek_nx(const atf_tc_t *tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = setup_db(atf_tc_get_md_var(tc, "X-filename"), - dns_dbtype_cache, &db); + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, + atf_tc_get_md_var(tc, "X-filename")); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = dns_db_createiterator(db, 0, &iter); diff --git a/lib/dns/tests/dnstest.c b/lib/dns/tests/dnstest.c index 9e9af61e..a5d15a04 100644 --- a/lib/dns/tests/dnstest.c +++ b/lib/dns/tests/dnstest.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnstest.c,v 1.8 2011-10-10 02:46:16 marka Exp $ */ +/* $Id: dnstest.c,v 1.11 2011-12-05 23:46:35 tbox Exp $ */ /*! \file */ @@ -35,6 +35,7 @@ #include <isc/timer.h> #include <isc/util.h> +#include <dns/db.h> #include <dns/fixedname.h> #include <dns/log.h> #include <dns/name.h> @@ -297,3 +298,27 @@ dns_test_nap(isc_uint32_t usec) { sleep((usec / 1000000) + 1); #endif } + +isc_result_t +dns_test_loaddb(dns_db_t **db, dns_dbtype_t dbtype, const char *origin, + const char *testfile) +{ + isc_result_t result; + dns_fixedname_t fixed; + dns_name_t *name; + + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); + + result = dns_name_fromstring(name, origin, 0, NULL); + if (result != ISC_R_SUCCESS) + return(result); + + result = dns_db_create(mctx, "rbt", name, dbtype, dns_rdataclass_in, + 0, NULL, db); + if (result != ISC_R_SUCCESS) + return (result); + + result = dns_db_load(*db, testfile); + return (result); +} diff --git a/lib/dns/tests/dnstest.h b/lib/dns/tests/dnstest.h index 8bddd410..bdd4b09d 100644 --- a/lib/dns/tests/dnstest.h +++ b/lib/dns/tests/dnstest.h @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnstest.h,v 1.4 2011-09-02 21:15:37 each Exp $ */ +/* $Id: dnstest.h,v 1.6 2011-12-05 23:46:35 tbox Exp $ */ /*! \file */ @@ -75,3 +75,7 @@ dns_test_closezonemgr(void); void dns_test_nap(isc_uint32_t usec); + +isc_result_t +dns_test_loaddb(dns_db_t **db, dns_dbtype_t dbtype, const char *origin, + const char *testfile); diff --git a/lib/dns/tests/master_test.c b/lib/dns/tests/master_test.c index afe6eaa4..db93b203 100644 --- a/lib/dns/tests/master_test.c +++ b/lib/dns/tests/master_test.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: master_test.c,v 1.6 2011-09-07 19:11:14 each Exp $ */ +/* $Id: master_test.c,v 1.7 2011-12-08 16:07:22 each Exp $ */ /*! \file */ @@ -26,6 +26,7 @@ #include <dns/cache.h> #include <dns/callbacks.h> +#include <dns/db.h> #include <dns/master.h> #include <dns/masterdump.h> #include <dns/name.h> @@ -43,9 +44,15 @@ #define BIGBUFLEN (64 * 1024) #define TEST_ORIGIN "test" +static dns_masterrawheader_t header; +static isc_boolean_t headerset; + static isc_result_t add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset); +static void +rawdata_callback(dns_zone_t *zone, dns_masterrawheader_t *header); + static isc_result_t add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset) { char buf[BIGBUFLEN]; @@ -60,8 +67,15 @@ add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset) { return(result); } +static void +rawdata_callback(dns_zone_t *zone, dns_masterrawheader_t *h) { + UNUSED(zone); + header = *h; + headerset = ISC_TRUE; +} + static int -test_master(const char *testfile) { +test_master(const char *testfile, dns_masterformat_t format) { isc_result_t result; int len; char origin[sizeof(TEST_ORIGIN)]; @@ -78,6 +92,7 @@ test_master(const char *testfile) { isc_buffer_setactive(&source, len); isc_buffer_init(&target, name_buf, BUFLEN); dns_name_init(&dns_origin, NULL); + dns_master_initrawheader(&header); result = dns_name_fromtext(&dns_origin, &source, dns_rootname, 0, &target); @@ -86,10 +101,12 @@ test_master(const char *testfile) { dns_rdatacallbacks_init_stdio(&callbacks); callbacks.add = add_callback; - - result = dns_master_loadfile(testfile, &dns_origin, &dns_origin, - dns_rdataclass_in, ISC_TRUE, - &callbacks, mctx); + callbacks.rawdata = rawdata_callback; + callbacks.zone = NULL; + headerset = ISC_FALSE; + result = dns_master_loadfile2(testfile, &dns_origin, &dns_origin, + dns_rdataclass_in, ISC_TRUE, + &callbacks, mctx, format); return (result); } @@ -98,12 +115,12 @@ test_master(const char *testfile) { */ /* Successful load test */ -ATF_TC(master_load); -ATF_TC_HEAD(master_load, tc) { +ATF_TC(load); +ATF_TC_HEAD(load, tc) { atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() loads a " "valid master file and returns success"); } -ATF_TC_BODY(master_load, tc) { +ATF_TC_BODY(load, tc) { isc_result_t result; UNUSED(tc); @@ -111,7 +128,8 @@ ATF_TC_BODY(master_load, tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = test_master("testdata/master/master1.data"); + result = test_master("testdata/master/master1.data", + dns_masterformat_text); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); dns_test_end(); @@ -119,13 +137,13 @@ ATF_TC_BODY(master_load, tc) { /* Unepxected end of file test */ -ATF_TC(master_unexpected); -ATF_TC_HEAD(master_unexpected, tc) { +ATF_TC(unexpected); +ATF_TC_HEAD(unexpected, tc) { atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns " "DNS_R_UNEXPECTED when file ends " "too soon"); } -ATF_TC_BODY(master_unexpected, tc) { +ATF_TC_BODY(unexpected, tc) { isc_result_t result; UNUSED(tc); @@ -133,7 +151,8 @@ ATF_TC_BODY(master_unexpected, tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = test_master("testdata/master/master2.data"); + result = test_master("testdata/master/master2.data", + dns_masterformat_text); ATF_REQUIRE_EQ(result, ISC_R_UNEXPECTEDEND); dns_test_end(); @@ -141,13 +160,13 @@ ATF_TC_BODY(master_unexpected, tc) { /* No owner test */ -ATF_TC(master_noowner); -ATF_TC_HEAD(master_noowner, tc) { +ATF_TC(noowner); +ATF_TC_HEAD(noowner, tc) { atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() accepts broken " "zones with no TTL for first record " "if it is an SOA"); } -ATF_TC_BODY(master_noowner, tc) { +ATF_TC_BODY(noowner, tc) { isc_result_t result; UNUSED(tc); @@ -155,7 +174,8 @@ ATF_TC_BODY(master_noowner, tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = test_master("testdata/master/master3.data"); + result = test_master("testdata/master/master3.data", + dns_masterformat_text); ATF_REQUIRE_EQ(result, DNS_R_NOOWNER); dns_test_end(); @@ -163,14 +183,14 @@ ATF_TC_BODY(master_noowner, tc) { /* No TTL test */ -ATF_TC(master_nottl); -ATF_TC_HEAD(master_nottl, tc) { +ATF_TC(nottl); +ATF_TC_HEAD(nottl, tc) { atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns " "DNS_R_NOOWNER when no owner name " "is specified"); } -ATF_TC_BODY(master_nottl, tc) { +ATF_TC_BODY(nottl, tc) { isc_result_t result; UNUSED(tc); @@ -178,7 +198,8 @@ ATF_TC_BODY(master_nottl, tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = test_master("testdata/master/master4.data"); + result = test_master("testdata/master/master4.data", + dns_masterformat_text); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); dns_test_end(); @@ -186,13 +207,13 @@ ATF_TC_BODY(master_nottl, tc) { /* Bad class test */ -ATF_TC(master_badclass); -ATF_TC_HEAD(master_badclass, tc) { +ATF_TC(badclass); +ATF_TC_HEAD(badclass, tc) { atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() returns " "DNS_R_BADCLASS when record class " "doesn't match zone class"); } -ATF_TC_BODY(master_badclass, tc) { +ATF_TC_BODY(badclass, tc) { isc_result_t result; UNUSED(tc); @@ -200,19 +221,20 @@ ATF_TC_BODY(master_badclass, tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = test_master("testdata/master/master5.data"); + result = test_master("testdata/master/master5.data", + dns_masterformat_text); ATF_REQUIRE_EQ(result, DNS_R_BADCLASS); dns_test_end(); } /* DNSKEY test */ -ATF_TC(master_dnskey); -ATF_TC_HEAD(master_dnskey, tc) { +ATF_TC(dnskey); +ATF_TC_HEAD(dnskey, tc) { atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " "DNSKEY with key material"); } -ATF_TC_BODY(master_dnskey, tc) { +ATF_TC_BODY(dnskey, tc) { isc_result_t result; UNUSED(tc); @@ -220,7 +242,8 @@ ATF_TC_BODY(master_dnskey, tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = test_master("testdata/master/master6.data"); + result = test_master("testdata/master/master6.data", + dns_masterformat_text); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); dns_test_end(); @@ -228,12 +251,12 @@ ATF_TC_BODY(master_dnskey, tc) { /* DNSKEY with no key material test */ -ATF_TC(master_dnsnokey); -ATF_TC_HEAD(master_dnsnokey, tc) { +ATF_TC(dnsnokey); +ATF_TC_HEAD(dnsnokey, tc) { atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " "DNSKEY with no key material"); } -ATF_TC_BODY(master_dnsnokey, tc) { +ATF_TC_BODY(dnsnokey, tc) { isc_result_t result; UNUSED(tc); @@ -241,19 +264,20 @@ ATF_TC_BODY(master_dnsnokey, tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = test_master("testdata/master/master7.data"); + result = test_master("testdata/master/master7.data", + dns_masterformat_text); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); dns_test_end(); } /* Include test */ -ATF_TC(master_include); -ATF_TC_HEAD(master_include, tc) { +ATF_TC(include); +ATF_TC_HEAD(include, tc) { atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " "$INCLUDE"); } -ATF_TC_BODY(master_include, tc) { +ATF_TC_BODY(include, tc) { isc_result_t result; UNUSED(tc); @@ -261,19 +285,20 @@ ATF_TC_BODY(master_include, tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = test_master("testdata/master/master8.data"); + result = test_master("testdata/master/master8.data", + dns_masterformat_text); ATF_REQUIRE_EQ(result, DNS_R_SEENINCLUDE); dns_test_end(); } /* Include failure test */ -ATF_TC(master_includefail); -ATF_TC_HEAD(master_includefail, tc) { +ATF_TC(includefail); +ATF_TC_HEAD(includefail, tc) { atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() understands " "$INCLUDE failures"); } -ATF_TC_BODY(master_includefail, tc) { +ATF_TC_BODY(includefail, tc) { isc_result_t result; UNUSED(tc); @@ -281,7 +306,8 @@ ATF_TC_BODY(master_includefail, tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = test_master("testdata/master/master9.data"); + result = test_master("testdata/master/master9.data", + dns_masterformat_text); ATF_REQUIRE_EQ(result, DNS_R_BADCLASS); dns_test_end(); @@ -289,12 +315,12 @@ ATF_TC_BODY(master_includefail, tc) { /* Non-empty blank lines test */ -ATF_TC(master_blanklines); -ATF_TC_HEAD(master_blanklines, tc) { +ATF_TC(blanklines); +ATF_TC_HEAD(blanklines, tc) { atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() handles " "non-empty blank lines"); } -ATF_TC_BODY(master_blanklines, tc) { +ATF_TC_BODY(blanklines, tc) { isc_result_t result; UNUSED(tc); @@ -302,19 +328,20 @@ ATF_TC_BODY(master_blanklines, tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = test_master("testdata/master/master10.data"); + result = test_master("testdata/master/master10.data", + dns_masterformat_text); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); dns_test_end(); } /* SOA leading zeroes test */ -ATF_TC(master_leadingzero); -ATF_TC_HEAD(master_leadingzero, tc) { +ATF_TC(leadingzero); +ATF_TC_HEAD(leadingzero, tc) { atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() allows " "leading zeroes in SOA"); } -ATF_TC_BODY(master_leadingzero, tc) { +ATF_TC_BODY(leadingzero, tc) { isc_result_t result; UNUSED(tc); @@ -322,17 +349,18 @@ ATF_TC_BODY(master_leadingzero, tc) { result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); - result = test_master("testdata/master/master11.data"); + result = test_master("testdata/master/master11.data", + dns_masterformat_text); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); dns_test_end(); } -ATF_TC(master_totext); -ATF_TC_HEAD(master_totext, tc) { +ATF_TC(totext); +ATF_TC_HEAD(totext, tc) { atf_tc_set_md_var(tc, "descr", "masterfile totext tests"); } -ATF_TC_BODY(master_totext, tc) { +ATF_TC_BODY(totext, tc) { isc_result_t result; dns_rdataset_t rdataset; dns_rdatalist_t rdatalist; @@ -372,22 +400,136 @@ ATF_TC_BODY(master_totext, tc) { dns_test_end(); } +/* Raw load */ +ATF_TC(loadraw); +ATF_TC_HEAD(loadraw, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() loads a " + "valid raw file and returns success"); +} +ATF_TC_BODY(loadraw, tc) { + isc_result_t result; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* Raw format version 0 */ + result = test_master("testdata/master/master12.data", + dns_masterformat_raw); + ATF_CHECK_STREQ(isc_result_totext(result), "success"); + ATF_CHECK(headerset); + ATF_CHECK_EQ(header.flags, 0); + + /* Raw format version 1, no source serial */ + result = test_master("testdata/master/master13.data", + dns_masterformat_raw); + ATF_CHECK_STREQ(isc_result_totext(result), "success"); + ATF_CHECK(headerset); + ATF_CHECK_EQ(header.flags, 0); + + /* Raw format version 1, source serial == 2011120101 */ + result = test_master("testdata/master/master14.data", + dns_masterformat_raw); + ATF_CHECK_STREQ(isc_result_totext(result), "success"); + ATF_CHECK(headerset); + ATF_CHECK((header.flags & DNS_MASTERRAW_SOURCESERIALSET) != 0); + ATF_CHECK_EQ(header.sourceserial, 2011120101); + + dns_test_end(); +} + +/* Raw dump*/ +ATF_TC(dumpraw); +ATF_TC_HEAD(dumpraw, tc) { + atf_tc_set_md_var(tc, "descr", "dns_master_dump*() functions " + "dump valid raw files"); +} +ATF_TC_BODY(dumpraw, tc) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbversion_t *version = NULL; + char origin[sizeof(TEST_ORIGIN)]; + dns_name_t dns_origin; + isc_buffer_t source, target; + unsigned char name_buf[BUFLEN]; + int len; + + UNUSED(tc); + + strcpy(origin, TEST_ORIGIN); + len = strlen(origin); + isc_buffer_init(&source, origin, len); + isc_buffer_add(&source, len); + isc_buffer_setactive(&source, len); + isc_buffer_init(&target, name_buf, BUFLEN); + dns_name_init(&dns_origin, NULL); + result = dns_name_fromtext(&dns_origin, &source, dns_rootname, + 0, &target); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_test_begin(NULL, ISC_FALSE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_create(mctx, "rbt", &dns_origin, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_db_load(db, "testdata/master/master1.data"); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + dns_db_currentversion(db, &version); + + result = dns_master_dump2(mctx, db, version, + &dns_master_style_default, "test.dump", + dns_masterformat_raw); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("test.dump", dns_masterformat_raw); + ATF_CHECK_STREQ(isc_result_totext(result), "success"); + ATF_CHECK(headerset); + ATF_CHECK_EQ(header.flags, 0); + + dns_master_initrawheader(&header); + header.sourceserial = 12345; + header.flags |= DNS_MASTERRAW_SOURCESERIALSET; + + unlink("test.dump"); + result = dns_master_dump3(mctx, db, version, + &dns_master_style_default, "test.dump", + dns_masterformat_raw, &header); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = test_master("test.dump", dns_masterformat_raw); + ATF_CHECK_STREQ(isc_result_totext(result), "success"); + ATF_CHECK(headerset); + ATF_CHECK((header.flags & DNS_MASTERRAW_SOURCESERIALSET) != 0); + ATF_CHECK_EQ(header.sourceserial, 12345); + + unlink("test.dump"); + dns_db_closeversion(db, &version, ISC_FALSE); + dns_db_detach(&db); + dns_test_end(); +} + /* * Main */ ATF_TP_ADD_TCS(tp) { - ATF_TP_ADD_TC(tp, master_load); - ATF_TP_ADD_TC(tp, master_unexpected); - ATF_TP_ADD_TC(tp, master_noowner); - ATF_TP_ADD_TC(tp, master_nottl); - ATF_TP_ADD_TC(tp, master_badclass); - ATF_TP_ADD_TC(tp, master_dnskey); - ATF_TP_ADD_TC(tp, master_dnsnokey); - ATF_TP_ADD_TC(tp, master_include); - ATF_TP_ADD_TC(tp, master_includefail); - ATF_TP_ADD_TC(tp, master_blanklines); - ATF_TP_ADD_TC(tp, master_leadingzero); - ATF_TP_ADD_TC(tp, master_totext); + ATF_TP_ADD_TC(tp, load); + ATF_TP_ADD_TC(tp, unexpected); + ATF_TP_ADD_TC(tp, noowner); + ATF_TP_ADD_TC(tp, nottl); + ATF_TP_ADD_TC(tp, badclass); + ATF_TP_ADD_TC(tp, dnskey); + ATF_TP_ADD_TC(tp, dnsnokey); + ATF_TP_ADD_TC(tp, include); + ATF_TP_ADD_TC(tp, includefail); + ATF_TP_ADD_TC(tp, blanklines); + ATF_TP_ADD_TC(tp, leadingzero); + ATF_TP_ADD_TC(tp, totext); + ATF_TP_ADD_TC(tp, loadraw); + ATF_TP_ADD_TC(tp, dumpraw); return (atf_no_error()); } diff --git a/lib/dns/tests/mkraw.pl b/lib/dns/tests/mkraw.pl new file mode 100644 index 00000000..31fa1b0d --- /dev/null +++ b/lib/dns/tests/mkraw.pl @@ -0,0 +1,31 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2011 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 +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: mkraw.pl,v 1.2 2011-12-08 16:07:22 each Exp $ + +# Convert a hexdump to binary format. +# +# To convert binary data to the input format for this command, +# use the following: +# +# perl -e 'while (read(STDIN, my $byte, 1)) { +# print unpack("H2", $byte); +# } +# print "\n";' < file > file.in + +use strict; +chomp(my $line = <STDIN>); +print pack("H*", $line); diff --git a/lib/dns/tests/testdata/diff/zone1.data b/lib/dns/tests/testdata/diff/zone1.data new file mode 100644 index 00000000..a3e0a1db --- /dev/null +++ b/lib/dns/tests/testdata/diff/zone1.data @@ -0,0 +1,20 @@ +; Copyright (C) 2011 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 +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +; $Id: zone1.data,v 1.3 2011-12-06 23:46:31 tbox Exp $ + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS @ +@ 0 A 1.2.3.4 +remove 0 A 5.6.7.8 diff --git a/lib/dns/tests/testdata/diff/zone2.data b/lib/dns/tests/testdata/diff/zone2.data new file mode 100644 index 00000000..2de15a0a --- /dev/null +++ b/lib/dns/tests/testdata/diff/zone2.data @@ -0,0 +1,21 @@ +; Copyright (C) 2011 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 +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +; $Id: zone2.data,v 1.3 2011-12-06 23:46:32 tbox Exp $ + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS @ +@ 0 A 1.2.3.4 +remove 0 A 5.6.7.8 +added 0 A 5.6.7.8 diff --git a/lib/dns/tests/testdata/diff/zone3.data b/lib/dns/tests/testdata/diff/zone3.data new file mode 100644 index 00000000..f31960b3 --- /dev/null +++ b/lib/dns/tests/testdata/diff/zone3.data @@ -0,0 +1,19 @@ +; Copyright (C) 2011 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 +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +; $Id: zone3.data,v 1.3 2011-12-06 23:46:32 tbox Exp $ + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS @ +@ 0 A 1.2.3.4 diff --git a/lib/dns/tests/testdata/master/master1.data b/lib/dns/tests/testdata/master/master1.data index 9b814740..030bc689 100644 --- a/lib/dns/tests/testdata/master/master1.data +++ b/lib/dns/tests/testdata/master/master1.data @@ -5,7 +5,7 @@ $TTL 1000 1800 ;retry 604800 ;expiration 3600 ) ;minimum -a in ns ns.vix.com. -a in ns ns2vix.com. -a in ns ns3vix.com. + in ns ns.vix.com. + in ns ns2.vix.com. + in ns ns3.vix.com. b in a 1.2.3.4 diff --git a/lib/dns/tests/testdata/master/master12.data.in b/lib/dns/tests/testdata/master/master12.data.in new file mode 100644 index 00000000..36343882 --- /dev/null +++ b/lib/dns/tests/testdata/master/master12.data.in @@ -0,0 +1 @@ +00000002000000004ed7306600000051000100060000000003e80000000100060474657374000035096c6f63616c686f7374000a706f73746d6173746572096c6f63616c686f73740076cb8ab100000e100000070800093a8000000e1000000046000100020000000003e8000000030006047465737400000c026e730376697803636f6d00000d036e73320376697803636f6d00000d036e73330376697803636f6d0000000022000100010000000003e80000000100080162047465737400000401020304 diff --git a/lib/dns/tests/testdata/master/master13.data.in b/lib/dns/tests/testdata/master/master13.data.in new file mode 100644 index 00000000..d1c262f0 --- /dev/null +++ b/lib/dns/tests/testdata/master/master13.data.in @@ -0,0 +1 @@ +00000002000000014ed7337f00000000000000000000000000000051000100060000000003e80000000100060474657374000035096c6f63616c686f7374000a706f73746d6173746572096c6f63616c686f73740076cb8ab100000e100000070800093a8000000e1000000046000100020000000003e8000000030006047465737400000c026e730376697803636f6d00000d036e73320376697803636f6d00000d036e73330376697803636f6d0000000022000100010000000003e80000000100080162047465737400000401020304 diff --git a/lib/dns/tests/testdata/master/master14.data.in b/lib/dns/tests/testdata/master/master14.data.in new file mode 100644 index 00000000..149a25f3 --- /dev/null +++ b/lib/dns/tests/testdata/master/master14.data.in @@ -0,0 +1 @@ +00000002000000014ed7337f0000000277df41e50000000000000051000100060000000003e80000000100060474657374000035096c6f63616c686f7374000a706f73746d6173746572096c6f63616c686f73740076cb8ab100000e100000070800093a8000000e1000000046000100020000000003e8000000030006047465737400000c026e730376697803636f6d00000d036e73320376697803636f6d00000d036e73330376697803636f6d0000000022000100010000000003e80000000100080162047465737400000401020304 diff --git a/lib/dns/win32/libdns.def b/lib/dns/win32/libdns.def index 7ddceb0b..615d068f 100644 --- a/lib/dns/win32/libdns.def +++ b/lib/dns/win32/libdns.def @@ -99,6 +99,7 @@ dns_db_deleterdataset dns_db_detach dns_db_detachnode dns_db_diff +dns_db_diffx dns_db_dump dns_db_endload dns_db_expirenode @@ -242,6 +243,7 @@ dns_journal_current_rr dns_journal_destroy dns_journal_first_rr dns_journal_first_serial +dns_journal_get_sourceserial dns_journal_iter_init dns_journal_last_serial dns_journal_next_rr @@ -249,6 +251,7 @@ dns_journal_open dns_journal_print dns_journal_rollforward dns_journal_rollforward2 +dns_journal_set_sourceserial dns_journal_write_transaction dns_journal_writediff dns_keydata_fromdnskey @@ -286,11 +289,18 @@ dns_lookup_cancel dns_lookup_create dns_lookup_destroy dns_master_dump +dns_master_dump2 +dns_master_dump3 +dns_master_dumpinc +dns_master_dumpinc2 +dns_master_dumpinc3 dns_master_dumpnode dns_master_dumpnodetostream dns_master_dumptostream dns_master_dumptostream2 +dns_master_dumptostream3 dns_master_dumptostreaminc +dns_master_initrawheader dns_master_loadbuffer dns_master_loadbufferinc dns_master_loadfile @@ -779,6 +789,7 @@ dns_zone_dlzpostload dns_zone_dump dns_zone_dumptostream dns_zone_dumptostream2 +dns_zone_dumptostream3 dns_zone_expire dns_zone_first dns_zone_flush @@ -892,6 +903,7 @@ dns_zone_setorigin dns_zone_setprivatetype dns_zone_setqueryacl dns_zone_setqueryonacl +dns_zone_setrawdata dns_zone_setrefreshkeyinterval dns_zone_setrequestixfr dns_zone_setrequeststats diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index e0a23ecc..b433d39e 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: xfrin.c,v 1.171 2011-08-30 05:16:14 marka Exp $ */ +/* $Id: xfrin.c,v 1.172 2011-12-22 07:32:41 each Exp $ */ /*! \file */ @@ -360,7 +360,7 @@ ixfr_init(dns_xfrin_ctx_t *xfr) { journalfile = dns_zone_getjournal(xfr->zone); if (journalfile != NULL) CHECK(dns_journal_open(xfr->mctx, journalfile, - ISC_TRUE, &xfr->ixfr.journal)); + DNS_JOURNAL_CREATE, &xfr->ixfr.journal)); result = ISC_R_SUCCESS; failure: diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 541d5e9e..30e35227 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.647 2011-11-04 05:51:01 each Exp $ */ +/* $Id: zone.c,v 1.658 2011-12-22 07:32:41 each Exp $ */ /*! \file */ @@ -363,6 +363,9 @@ struct dns_zone { dns_zone_t *raw; dns_zone_t *secure; + + isc_boolean_t sourceserialset; + isc_uint32_t sourceserial; }; #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0)) @@ -652,6 +655,7 @@ static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length); static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length); static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length); static isc_result_t zone_send_secureserial(dns_zone_t *zone, + isc_boolean_t locked, isc_uint32_t serial); #if 0 @@ -709,7 +713,8 @@ static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver, static void zone_rekey(dns_zone_t *zone); static isc_boolean_t delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys); -static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db); +static isc_result_t zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked, + dns_db_t *db); #define ENTER zone_debuglog(zone, me, 1, "enter") @@ -896,6 +901,8 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { ISC_LIST_INIT(zone->forwards); zone->raw = NULL; zone->secure = NULL; + zone->sourceserial = 0; + zone->sourceserialset = ISC_FALSE; zone->magic = ZONE_MAGIC; @@ -1034,6 +1041,28 @@ zone_free(dns_zone_t *zone) { } /* + * Returns ISC_TRUE iff this the signed side of an inline-signing zone + */ +static inline isc_boolean_t +inline_secure(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + if (zone->raw != NULL) + return (ISC_TRUE); + return (ISC_FALSE); +} + +/* + * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone + */ +static inline isc_boolean_t +inline_raw(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + if (zone->secure != NULL) + return (ISC_TRUE); + return (ISC_FALSE); +} + +/* * Single shot. */ void @@ -1061,7 +1090,7 @@ dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) { zone_rdclass_tostr(zone, namebuf, sizeof namebuf); zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf); - if (zone->raw != NULL) + if (inline_secure(zone)) dns_zone_setclass(zone->raw, rdclass); UNLOCK_ZONE(zone); } @@ -1254,7 +1283,7 @@ dns_zone_setview(dns_zone_t *zone, dns_view_t *view) { zone_viewname_tostr(zone, namebuf, sizeof namebuf); zone->strviewname = isc_mem_strdup(zone->mctx, namebuf); - if (zone->raw != NULL) + if (inline_secure(zone)) dns_zone_setview(zone->raw, view); UNLOCK_ZONE(zone); @@ -1293,7 +1322,7 @@ dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) { zone_name_tostr(zone, namebuf, sizeof namebuf); zone->strname = isc_mem_strdup(zone->mctx, namebuf); - if (result == ISC_R_SUCCESS && zone->raw != NULL) + if (result == ISC_R_SUCCESS && inline_secure(zone)) result = dns_zone_setorigin(zone->raw, origin); UNLOCK_ZONE(zone); return (result); @@ -1465,7 +1494,7 @@ zone_load(dns_zone_t *zone, unsigned int flags) { LOCK_ZONE(zone); TIME_NOW(&now); - if (zone->raw != NULL) { + if (inline_secure(zone)) { result = zone_load(zone->raw, flags); if (result != ISC_R_SUCCESS) goto cleanup; @@ -1718,7 +1747,11 @@ isc_result_t dns_zone_loadandthaw(dns_zone_t *zone) { isc_result_t result; - result = zone_load(zone, DNS_ZONELOADFLAG_THAW); + if (inline_raw(zone)) + result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW); + else + result = zone_load(zone, DNS_ZONELOADFLAG_THAW); + switch (result) { case DNS_R_CONTINUE: /* Deferred thaw. */ @@ -1788,8 +1821,7 @@ zone_gotreadhandle(isc_task_t *task, isc_event_t *event) { result = dns_master_loadfileinc3(load->zone->masterfile, dns_db_origin(load->db), dns_db_origin(load->db), - load->zone->rdclass, - options, + load->zone->rdclass, options, load->zone->sigresigninginterval, &load->callbacks, task, zone_loaddone, load, @@ -1805,11 +1837,28 @@ zone_gotreadhandle(isc_task_t *task, isc_event_t *event) { } static void +get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) { + isc_result_t result; + + LOCK(&raw->lock); + if (raw->db != NULL) { + result = zone_get_from_db(raw, raw->db, NULL, NULL, + &rawdata->sourceserial, + NULL, NULL, NULL, NULL, + NULL); + if (result == ISC_R_SUCCESS) + rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET; + } + UNLOCK(&raw->lock); +} + +static void zone_gotwritehandle(isc_task_t *task, isc_event_t *event) { const char me[] = "zone_gotwritehandle"; dns_zone_t *zone = event->ev_arg; isc_result_t result = ISC_R_SUCCESS; dns_dbversion_t *version = NULL; + dns_masterrawheader_t rawdata; REQUIRE(DNS_ZONE_VALID(zone)); INSIST(task == zone->task); @@ -1824,10 +1873,14 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) { LOCK_ZONE(zone); ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); dns_db_currentversion(zone->db, &version); - result = dns_master_dumpinc2(zone->mctx, zone->db, version, + dns_master_initrawheader(&rawdata); + if (inline_secure(zone)) + get_raw_serial(zone->raw, &rawdata); + result = dns_master_dumpinc3(zone->mctx, zone->db, version, &dns_master_style_default, zone->masterfile, zone->task, dump_done, - zone, &zone->dctx, zone->masterformat); + zone, &zone->dctx, zone->masterformat, + &rawdata); dns_db_closeversion(zone->db, &version, ISC_FALSE); ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); UNLOCK_ZONE(zone); @@ -1839,6 +1892,31 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) { dump_done(zone, result); } +/* + * Save the raw serial number for inline-signing zones. + * (XXX: Other information from the header will be used + * for other purposes in the future, but for now this is + * all we're interested in.) + */ +static void +zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) { + if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) + return; + + zone->sourceserial = header->sourceserial; + zone->sourceserialset = ISC_TRUE; +} + +void +dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) { + if (zone == NULL) + return; + + LOCK_ZONE(zone); + zone_setrawdata(zone, header); + UNLOCK_ZONE(zone); +} + static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { dns_load_t *load; @@ -1866,6 +1944,8 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { zone_iattach(zone, &load->zone); dns_db_attach(db, &load->db); dns_rdatacallbacks_init(&load->callbacks); + load->callbacks.rawdata = zone_setrawdata; + zone_iattach(zone, &load->callbacks.zone); result = dns_db_beginload(db, &load->callbacks.add, &load->callbacks.add_private); if (result != ISC_R_SUCCESS) @@ -1887,18 +1967,24 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { dns_rdatacallbacks_t callbacks; dns_rdatacallbacks_init(&callbacks); + callbacks.rawdata = zone_setrawdata; + zone_iattach(zone, &callbacks.zone); result = dns_db_beginload(db, &callbacks.add, &callbacks.add_private); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + zone_idetach(&callbacks.zone); return (result); - result = dns_master_loadfile3(zone->masterfile, &zone->origin, - &zone->origin, zone->rdclass, - options, zone->sigresigninginterval, + } + result = dns_master_loadfile3(zone->masterfile, + &zone->origin, &zone->origin, + zone->rdclass, options, + zone->sigresigninginterval, &callbacks, zone->mctx, zone->masterformat); tresult = dns_db_endload(db, &callbacks.add_private); if (result == ISC_R_SUCCESS) result = tresult; + zone_idetach(&callbacks.zone); } return (result); @@ -1907,6 +1993,7 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { load->magic = 0; dns_db_detach(&load->db); zone_idetach(&load->zone); + zone_idetach(&load->callbacks.zone); isc_mem_detach(&load->mctx); isc_mem_put(zone->mctx, load, sizeof(*load)); return (result); @@ -3227,37 +3314,39 @@ update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, * Write all transactions in 'diff' to the zone journal file. */ static isc_result_t -zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *bitws, +zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial, const char *caller) { const char me[] = "zone_journal"; const char *journalfile; isc_result_t result = ISC_R_SUCCESS; dns_journal_t *journal = NULL; + unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE; ENTER; journalfile = dns_zone_getjournal(zone); if (journalfile != NULL) { - result = dns_journal_open(zone->mctx, journalfile, - DNS_JOURNAL_CREATE, &journal); + result = dns_journal_open(zone->mctx, journalfile, mode, + &journal); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "%s:dns_journal_open -> %s\n", caller, dns_result_totext(result)); return (result); } - if (bitws != NULL) - dns_journal_set_bitws(journal, *bitws); + + if (sourceserial != NULL) + dns_journal_set_sourceserial(journal, *sourceserial); result = dns_journal_write_transaction(journal, diff); - dns_journal_destroy(&journal); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "%s:dns_journal_write_transaction -> %s\n", caller, dns_result_totext(result)); - return (result); } + dns_journal_destroy(&journal); } + return (result); } @@ -3460,15 +3549,54 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) { } static void -maybe_send_securedb(dns_zone_t *zone) { +maybe_send_secure(dns_zone_t *zone) { + isc_result_t result; + + /* + * We've finished loading, or else failed to load, an inline-signing + * 'secure' zone. We now need information about the status of the + * 'raw' zone. If we failed to load, then we need it to send a + * copy of its database; if we succeeded, we need it to send its + * serial number so that we can sync with it. If it has not yet + * loaded, we set a flag so that it will send the necessary + * information when it has finished loading. + */ LOCK_ZONE(zone->raw); - if (zone->raw->db != NULL) - zone_send_securedb(zone->raw, zone->raw->db); - else + if (zone->raw->db != NULL) { + if (zone->db != NULL) { + isc_uint32_t serial; + result = zone_get_from_db(zone->raw, zone->raw->db, + NULL, NULL, &serial, NULL, + NULL, NULL, NULL, NULL); + if (result == ISC_R_SUCCESS) + zone_send_secureserial(zone->raw, ISC_TRUE, + serial); + } else + zone_send_securedb(zone->raw, ISC_TRUE, zone->raw->db); + + } else DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE); + UNLOCK_ZONE(zone->raw); } +static isc_boolean_t +zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) { + isc_result_t result; + isc_boolean_t answer = ISC_FALSE; + dns_diff_t diff; + + dns_diff_init(mctx, &diff); + result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL); + if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) + answer = ISC_TRUE; + dns_diff_clear(&diff); + return (answer); +} + +/* + * The zone is presumed to be locked. + */ static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, isc_result_t result) @@ -3505,10 +3633,11 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, zone->masterfile, dns_result_totext(result)); } else if (zone->type == dns_zone_master && - zone->raw != NULL && result == ISC_R_FILENOTFOUND) { + inline_secure(zone) && result == ISC_R_FILENOTFOUND) + { dns_zone_log(zone, ISC_LOG_DEBUG(1), "no master file, requesting db"); - maybe_send_securedb(zone); + maybe_send_secure(zone); } else { int level = ISC_LOG_ERROR; if (zone->type == dns_zone_key && @@ -3608,7 +3737,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, dns_journal_t *journal = NULL; result = dns_journal_open(zone->mctx, zone->journal, - ISC_FALSE, &journal); + DNS_JOURNAL_READ, &journal); if (result == ISC_R_SUCCESS) { jserial = dns_journal_last_serial(journal); dns_journal_destroy(&journal); @@ -3700,6 +3829,14 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, INSIST(zone->type == dns_zone_master); + if (serial == oldserial && + zone_unchanged(zone->db, db, zone->mctx)) { + dns_zone_log(zone, ISC_LOG_INFO, + "ixfr-from-differences: " + "unchanged"); + return(ISC_R_SUCCESS); + } + serialmin = (oldserial + 1) & 0xffffffffU; serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU; @@ -3766,6 +3903,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, &zone->expiretime) >= 0) zone->refreshtime = now; } + break; case dns_zone_key: @@ -3818,10 +3956,23 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY); if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) && - zone->secure != NULL) - zone_send_securedb(zone, db); + inline_raw(zone)) + { + if (zone->secure->db == NULL) + zone_send_securedb(zone, ISC_FALSE, db); + else + zone_send_secureserial(zone, ISC_FALSE, serial); + } } + /* + * Finished loading inline-signing zone; need to get status + * from the raw side now. + */ + if (zone->type == dns_zone_master && inline_secure(zone)) + maybe_send_secure(zone); + + result = ISC_R_SUCCESS; if (needdump) { @@ -4732,6 +4883,7 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone, /* * Everything is ok so attach to the zone. */ + zone->curmaster = 0; zone->mastersok = newok; zone->masters = newaddrs; zone->masterkeynames = newnames; @@ -8413,7 +8565,7 @@ dns_zone_markdirty(dns_zone_t *zone) { LOCK_ZONE(zone); if (zone->type == dns_zone_master) { - if (zone->secure != NULL) { + if (inline_raw(zone)) { ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); if (zone->db != NULL) { result = zone_get_from_db(zone, zone->db, NULL, @@ -8424,7 +8576,7 @@ dns_zone_markdirty(dns_zone_t *zone) { result = DNS_R_NOTLOADED; ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); if (result == ISC_R_SUCCESS) - zone_send_secureserial(zone, serial); + zone_send_secureserial(zone, ISC_FALSE, serial); } set_resigntime(zone); /* XXXMPA make separate call back */ } @@ -8616,8 +8768,9 @@ dump_done(void *arg, isc_result_t result) { * If there is a secure version of this zone * use its serial if it is less than ours. */ - if (tresult == ISC_R_SUCCESS && - zone->secure != NULL && zone->secure->db != NULL) { + if (tresult == ISC_R_SUCCESS && inline_raw(zone) && + zone->secure->db != NULL) + { isc_uint32_t sserial; isc_result_t mresult; @@ -8735,10 +8888,15 @@ zone_dump(dns_zone_t *zone, isc_boolean_t compact) { result = DNS_R_CONTINUE; UNLOCK_ZONE(zone); } else { + dns_masterrawheader_t rawdata; dns_db_currentversion(db, &version); - result = dns_master_dump2(zone->mctx, db, version, + dns_master_initrawheader(&rawdata); + if (inline_secure(zone)) + get_raw_serial(zone->raw, &rawdata); + result = dns_master_dump3(zone->mctx, db, version, &dns_master_style_default, - masterfile, masterformat); + masterfile, masterformat, + &rawdata); dns_db_closeversion(db, &version, ISC_FALSE); } fail: @@ -8777,11 +8935,12 @@ zone_dump(dns_zone_t *zone, isc_boolean_t compact) { static isc_result_t dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style, - dns_masterformat_t format) + dns_masterformat_t format, const isc_uint32_t rawversion) { isc_result_t result; dns_dbversion_t *version = NULL; dns_db_t *db = NULL; + dns_masterrawheader_t rawdata; REQUIRE(DNS_ZONE_VALID(zone)); @@ -8793,29 +8952,46 @@ dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style, return (DNS_R_NOTLOADED); dns_db_currentversion(db, &version); - result = dns_master_dumptostream2(zone->mctx, db, version, style, - format, fd); + dns_master_initrawheader(&rawdata); + if (rawversion == 0) + rawdata.flags |= DNS_MASTERRAW_COMPAT; + else if (inline_secure(zone)) + get_raw_serial(zone->raw, &rawdata); + else if (zone->sourceserialset) { + rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET; + rawdata.sourceserial = zone->sourceserial; + } + result = dns_master_dumptostream3(zone->mctx, db, version, style, + format, &rawdata, fd); dns_db_closeversion(db, &version, ISC_FALSE); dns_db_detach(&db); return (result); } isc_result_t +dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format, + const dns_master_style_t *style, + const isc_uint32_t rawversion) +{ + return (dumptostream(zone, fd, style, format, rawversion)); +} + +isc_result_t dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format, const dns_master_style_t *style) { - return dumptostream(zone, fd, style, format); + return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION)); } isc_result_t dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) { - return dumptostream(zone, fd, &dns_master_style_default, - dns_masterformat_text); + return (dumptostream(zone, fd, &dns_master_style_default, + dns_masterformat_text, 0)); } isc_result_t dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) { - return dumptostream(zone, fd, &dns_master_style_full, - dns_masterformat_text); + return (dumptostream(zone, fd, &dns_master_style_full, + dns_masterformat_text, 0)); } void @@ -10887,11 +11063,11 @@ zone_shutdown(isc_task_t *task, isc_event_t *event) { */ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN); free_needed = exit_check(zone); - if (zone->raw != NULL) { + if (inline_secure(zone)) { raw = zone->raw; zone->raw = NULL; } - if (zone->secure != NULL) { + if (inline_raw(zone)) { secure = zone->secure; zone->secure = NULL; } @@ -11263,7 +11439,7 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, * Notify messages are processed by the raw zone. */ LOCK_ZONE(zone); - if (zone->raw != NULL) { + if (inline_secure(zone)) { result = dns_zone_notifyreceive(zone->raw, from, msg); UNLOCK_ZONE(zone); return (result); @@ -11674,9 +11850,9 @@ zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) { isc_buffer_putstr(&buffer, "/"); isc_buffer_putstr(&buffer, zone->view->name); } - if (zone->raw != NULL && 9U < isc_buffer_availablelength(&buffer)) + if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) isc_buffer_putstr(&buffer, " (signed)"); - if (zone->secure != NULL && 11U < isc_buffer_availablelength(&buffer)) + if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) isc_buffer_putstr(&buffer, " (unsigned)"); buf[isc_buffer_usedlength(&buffer)] = '\0'; @@ -11995,8 +12171,9 @@ notify_done(isc_task_t *task, isc_event_t *event) { dns_message_destroy(&message); } -struct secure_serial { +struct secure_event { isc_event_t e; + dns_db_t *db; isc_uint32_t serial; }; @@ -12006,89 +12183,55 @@ update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) { dns_zone_log(zone, level, "%s", message); } -static void -receive_secure_serial(isc_task_t *task, isc_event_t *event) { - isc_result_t result; - dns_journal_t *rjournal = NULL, *sjournal = NULL; - isc_uint32_t start, end; - dns_zone_t *zone; - int n_soa = 0; - dns_db_t *db = NULL; - dns_dbnode_t *node = NULL; - dns_dbversion_t *newver = NULL, *oldver = NULL; - isc_uint32_t oldserial, newserial; +static isc_result_t +sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal, + isc_uint32_t start, isc_uint32_t end, + dns_difftuple_t **soatuplep, dns_diff_t *diff) +{ + isc_result_t result; + dns_difftuple_t *tuple = NULL; dns_diffop_t op = DNS_DIFFOP_ADD; - dns_diff_t diff; - dns_difftuple_t *tuple = NULL, *soatuple = NULL; - dns_update_log_t log = { update_log_cb, NULL }; - isc_time_t timenow; - - zone = event->ev_arg; - end = ((struct secure_serial *)event)->serial; - - dns_diff_init(zone->mctx, &diff); - - UNUSED(task); - CHECK(dns_journal_open(zone->raw->mctx, zone->raw->journal, - DNS_JOURNAL_WRITE, &rjournal)); - result = dns_journal_open(zone->raw->mctx, zone->journal, - DNS_JOURNAL_READ, &sjournal); - if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) - goto failure; - - start = dns_journal_get_bitws(rjournal); - if (sjournal != NULL) { - isc_uint32_t serial = dns_journal_get_bitws(sjournal); - /* - * We write the secure journal first so if that exists - * use its value provided it is greater that from the - * raw journal. - */ - if (isc_serial_gt(serial, start)) - start = serial; - dns_journal_destroy(&sjournal); - } + int n_soa = 0; - if (start == end) - goto failure; - CHECK(dns_journal_iter_init(rjournal, start, end)); + REQUIRE(soatuplep != NULL); - dns_db_attach(zone->db, &db); - dns_db_currentversion(db, &oldver); - CHECK(dns_db_newversion(db, &newver)); + if (start == end) + return (DNS_R_UNCHANGED); - for (result = dns_journal_first_rr(rjournal); - result == ISC_R_SUCCESS; - result = dns_journal_next_rr(rjournal)) { - dns_name_t *name = NULL; - isc_uint32_t ttl; - dns_rdata_t *rdata = NULL; - dns_journal_current_rr(rjournal, &name, &ttl, &rdata); - - if (rdata->type == dns_rdatatype_soa) { - n_soa++; - if (n_soa == 2) { - /* - * Save the lastest raw SOA record. - */ - if (soatuple != NULL) - dns_difftuple_free(&soatuple); - CHECK(dns_difftuple_create(diff.mctx, - DNS_DIFFOP_ADD, - name, ttl, rdata, - &soatuple)); - } - if (n_soa == 3) - n_soa = 1; + CHECK(dns_journal_iter_init(journal, start, end)); + for (result = dns_journal_first_rr(journal); + result == ISC_R_SUCCESS; + result = dns_journal_next_rr(journal)) + { + dns_name_t *name = NULL; + isc_uint32_t ttl; + dns_rdata_t *rdata = NULL; + dns_journal_current_rr(journal, &name, &ttl, &rdata); + + if (rdata->type == dns_rdatatype_soa) { + n_soa++; + if (n_soa == 2) { + /* + * Save the latest raw SOA record. + */ + if (*soatuplep != NULL) + dns_difftuple_free(soatuplep); + CHECK(dns_difftuple_create(diff->mctx, + DNS_DIFFOP_ADD, + name, ttl, rdata, + soatuplep)); + } + if (n_soa == 3) + n_soa = 1; continue; } - /* Sanity. */ + /* Sanity. */ if (n_soa == 0) { dns_zone_log(zone->raw, ISC_LOG_ERROR, "corrupt journal file: '%s'\n", zone->raw->journal); - goto failure; + return (ISC_R_FAILURE); } if (zone->privatetype != 0 && @@ -12104,18 +12247,149 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD; - CHECK(dns_difftuple_create(diff.mctx, op, name, ttl, rdata, + CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple)); - dns_diff_appendminimal(&diff, &tuple); + dns_diff_appendminimal(diff, &tuple); + } + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + + failure: + return(result); +} + +static isc_result_t +sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb, + dns_dbversion_t *secver, dns_diff_t *diff) +{ + isc_result_t result; + dns_db_t *rawdb = NULL; + dns_dbversion_t *rawver = NULL; + dns_difftuple_t *tuple = NULL, *next; + + REQUIRE(DNS_ZONE_VALID(seczone)); + REQUIRE(inline_secure(seczone)); + + if (!seczone->sourceserialset) + return (DNS_R_UNCHANGED); + + dns_db_attach(seczone->raw->db, &rawdb); + dns_db_currentversion(rawdb, &rawver); + result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL); + dns_db_closeversion(rawdb, &rawver, ISC_FALSE); + dns_db_detach(&rawdb); + + if (result != ISC_R_SUCCESS) + return (result); + + for (tuple = ISC_LIST_HEAD(diff->tuples); + tuple != NULL; + tuple = next) + { + next = ISC_LIST_NEXT(tuple, link); + if (tuple->rdata.type == dns_rdatatype_nsec || + tuple->rdata.type == dns_rdatatype_rrsig || + tuple->rdata.type == dns_rdatatype_dnskey || + tuple->rdata.type == dns_rdatatype_nsec3 || + tuple->rdata.type == dns_rdatatype_soa || + tuple->rdata.type == dns_rdatatype_nsec3param) + { + ISC_LIST_UNLINK(diff->tuples, tuple, link); + dns_difftuple_free(&tuple); + } + } + + if (ISC_LIST_EMPTY(diff->tuples)) + return (DNS_R_UNCHANGED); + + return (ISC_R_SUCCESS); +} + +static void +receive_secure_serial(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + dns_journal_t *rjournal = NULL; + isc_uint32_t start, end; + dns_zone_t *zone; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + dns_dbversion_t *newver = NULL, *oldver = NULL; + dns_diff_t diff; + dns_difftuple_t *tuple = NULL, *soatuple = NULL; + dns_update_log_t log = { update_log_cb, NULL }; + isc_time_t timenow; + + zone = event->ev_arg; + end = ((struct secure_event *)event)->serial; + isc_event_free(&event); + + REQUIRE(inline_secure(zone)); + + dns_diff_init(zone->mctx, &diff); + + UNUSED(task); + + /* + * We first attempt to sync the raw zone to the secure zone + * by using the raw zone's journal, applying all the deltas + * from the latest source-serial of the secure zone up to + * the current serial number of the raw zone. + * + * If that fails, then we'll fall back to a direct comparison + * between raw and secure zones. + */ + result = dns_journal_open(zone->raw->mctx, zone->raw->journal, + DNS_JOURNAL_WRITE, &rjournal); + if (result != ISC_R_SUCCESS) + goto failure; + else { + dns_journal_t *sjournal = NULL; + + result = dns_journal_open(zone->raw->mctx, zone->journal, + DNS_JOURNAL_READ, &sjournal); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) + goto failure; + + if (!dns_journal_get_sourceserial(rjournal, &start)) { + start = dns_journal_first_serial(rjournal); + dns_journal_set_sourceserial(rjournal, start); + } + if (sjournal != NULL) { + isc_uint32_t serial; + /* + * We read the secure journal first, if that exists + * use its value provided it is greater that from the + * raw journal. + */ + if (dns_journal_get_sourceserial(sjournal, &serial)) { + if (isc_serial_gt(serial, start)) + start = serial; + } + dns_journal_destroy(&sjournal); + } + } + + dns_db_attach(zone->db, &db); + dns_db_currentversion(db, &oldver); + CHECK(dns_db_newversion(db, &newver)); + + /* + * Try to apply diffs from the raw zone's journal to the secure + * zone. If that fails, we recover by syncing up the databases + * directly. + */ + result = sync_secure_journal(zone, rjournal, start, end, + &soatuple, &diff); + if (result == DNS_R_UNCHANGED) + goto failure; + else if (result != ISC_R_SUCCESS) { + CHECK(sync_secure_db(zone, db, oldver, &diff)); } - if (result == ISC_R_NOMORE) - result = ISC_R_SUCCESS; - CHECK(result); CHECK(dns_diff_apply(&diff, db, newver)); if (soatuple != NULL) { - isc_uint32_t desired; + isc_uint32_t oldserial, newserial, desired; CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, DNS_DIFFOP_DEL, &tuple)); @@ -12140,12 +12414,14 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { CHECK(zone_journal(zone, &diff, &end, "receive_secure_serial")); - dns_journal_set_bitws(rjournal, end); + dns_journal_set_sourceserial(rjournal, end); dns_journal_commit(rjournal); LOCK_ZONE(zone); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); + zone->sourceserial = end; + zone->sourceserialset = ISC_TRUE; zone_needdump(zone, DNS_DUMP_DELAY); TIME_NOW(&timenow); @@ -12157,6 +12433,9 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { dns_db_closeversion(db, &newver, ISC_TRUE); failure: + if (result != ISC_R_SUCCESS) + dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s", + dns_result_totext(result)); if (tuple != NULL) dns_difftuple_free(&tuple); if (soatuple != NULL) @@ -12172,33 +12451,33 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { } if (rjournal != NULL) dns_journal_destroy(&rjournal); - if (sjournal != NULL) - dns_journal_destroy(&sjournal); dns_diff_clear(&diff); - isc_event_free(&event); + dns_zone_idetach(&zone); } static isc_result_t -zone_send_secureserial(dns_zone_t *zone, isc_uint32_t serial) { +zone_send_secureserial(dns_zone_t *zone, isc_boolean_t locked, + isc_uint32_t serial) +{ isc_event_t *e; + dns_zone_t *dummy = NULL; e = isc_event_allocate(zone->secure->mctx, zone, DNS_EVENT_ZONESECURESERIAL, receive_secure_serial, zone->secure, - sizeof(struct secure_serial)); + sizeof(struct secure_event)); if (e == NULL) return (ISC_R_NOMEMORY); - ((struct secure_serial *)e)->serial = serial; - + ((struct secure_event *)e)->serial = serial; + if (locked) + zone_iattach(zone->secure, &dummy); + else + dns_zone_iattach(zone->secure, &dummy); isc_task_send(zone->secure->task, &e); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE); return (ISC_R_SUCCESS); } -struct secure_db { - isc_event_t e; - dns_db_t *db; -}; - static void receive_secure_db(isc_task_t *task, isc_event_t *event) { isc_result_t result; @@ -12216,7 +12495,11 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) { UNUSED(task); zone = event->ev_arg; - rawdb = ((struct secure_db *)event)->db; + rawdb = ((struct secure_event *)event)->db; + isc_event_free(&event); + + REQUIRE(inline_secure(zone)); + dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_rdataset_init(&rdataset); @@ -12301,22 +12584,27 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) { dns_db_detach(&rawdb); if (dbiterator != NULL) dns_dbiterator_destroy(&dbiterator); - isc_event_free(&event); + dns_zone_idetach(&zone); } static isc_result_t -zone_send_securedb(dns_zone_t *zone, dns_db_t *db) { +zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked, dns_db_t *db) { isc_event_t *e; dns_db_t *dummy = NULL; + dns_zone_t *secure = NULL; e = isc_event_allocate(zone->secure->mctx, zone, DNS_EVENT_ZONESECUREDB, receive_secure_db, zone->secure, - sizeof(struct secure_db)); + sizeof(struct secure_event)); if (e == NULL) return (ISC_R_NOMEMORY); dns_db_attach(db, &dummy); - ((struct secure_db *)e)->db = dummy; + ((struct secure_event *)e)->db = dummy; + if (locked) + zone_iattach(zone->secure, &secure); + else + dns_zone_iattach(zone->secure, &secure); isc_task_send(zone->secure->task, &e); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE); @@ -12384,7 +12672,8 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { */ if (zone->db != NULL && zone->journal != NULL && DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) { + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) + { isc_uint32_t serial, oldserial; dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs"); @@ -12443,8 +12732,8 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { break; } } - if (zone->type == dns_zone_master && zone->secure != NULL) - zone_send_secureserial(zone, serial); + if (zone->type == dns_zone_master && inline_raw(zone)) + zone_send_secureserial(zone, ISC_FALSE, serial); } else { if (dump && zone->masterfile != NULL) { /* @@ -12495,8 +12784,9 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { zone->journal, strbuf); } } - if (zone->secure != NULL) - zone_send_securedb(zone, db); + + if (inline_raw(zone)) + zone_send_securedb(zone, ISC_FALSE, db); } dns_db_closeversion(db, &ver, ISC_FALSE); @@ -12648,8 +12938,8 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) { dns_zone_log(zone, ISC_LOG_INFO, "transferred serial %u%s", serial, buf); - if (zone->secure != NULL) - zone_send_secureserial(zone, serial); + if (inline_raw(zone)) + zone_send_secureserial(zone, ISC_FALSE, serial); } /* @@ -12802,6 +13092,7 @@ zone_loaddone(void *arg, isc_result_t result) { (void)zone_postload(load->zone, load->db, load->loadtime, result); zonemgr_putio(&load->zone->readio); DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING); + zone_idetach(&load->callbacks.zone); /* * Leave the zone frozen if the reload fails. */ @@ -13949,8 +14240,9 @@ zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) { if (result != ISC_R_SUCCESS) goto cleanup; - dns_zone_log(zone, ISC_LOG_WARNING, "saved '%s' as '%s'", - path, buf); + dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; " + "renaming file to '%s' for failure analysis and " + "retransferring.", path, buf); cleanup: isc_mem_put(zone->mctx, buf, buflen); @@ -14985,6 +15277,9 @@ zone_rekey(dns_zone_t *zone) { CHECK(dns_db_newversion(db, &ver)); CHECK(dns_db_getoriginnode(db, &node)); + TIME_NOW(&timenow); + now = isc_time_seconds(&timenow); + dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys"); /* Get the SOA record's TTL */ @@ -15084,7 +15379,6 @@ zone_rekey(dns_zone_t *zone) { dns_db_closeversion(db, &ver, commit); if (commit) { - isc_time_t timenow; dns_difftuple_t *tuple; LOCK_ZONE(zone); @@ -15092,7 +15386,6 @@ zone_rekey(dns_zone_t *zone) { zone_needdump(zone, DNS_DUMP_DELAY); - TIME_NOW(&timenow); zone_settimer(zone, &timenow); /* Remove any signatures from removed keys. */ @@ -15209,13 +15502,6 @@ zone_rekey(dns_zone_t *zone) { UNLOCK_ZONE(zone); } - /* - * If we are doing automatic key maintenance and the key metadata - * indicates there is a key change event scheduled in the future, - * set the key refresh timer. - */ - isc_stdtime_get(&now); - TIME_NOW(&timenow); isc_time_settoepoch(&zone->refreshkeytime); /* diff --git a/lib/dns/zt.c b/lib/dns/zt.c index 0995377a..3751b4c4 100644 --- a/lib/dns/zt.c +++ b/lib/dns/zt.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zt.c,v 1.56 2011-09-07 00:50:06 marka Exp $ */ +/* $Id: zt.c,v 1.59 2011-12-10 22:09:41 marka Exp $ */ /*! \file */ @@ -357,15 +357,25 @@ freezezones(dns_zone_t *zone, void *uap) { isc_result_t result = ISC_R_SUCCESS; char classstr[DNS_RDATACLASS_FORMATSIZE]; char zonename[DNS_NAME_FORMATSIZE]; + dns_zone_t *raw = NULL; dns_view_t *view; const char *vname; const char *sep; int level; - if (dns_zone_gettype(zone) != dns_zone_master) + dns_zone_getraw(zone, &raw); + if (raw != NULL) + zone = raw; + if (dns_zone_gettype(zone) != dns_zone_master) { + if (raw != NULL) + dns_zone_detach(&raw); return (ISC_R_SUCCESS); - if (!dns_zone_isdynamic(zone, ISC_TRUE)) + } + if (!dns_zone_isdynamic(zone, ISC_TRUE)) { + if (raw != NULL) + dns_zone_detach(&raw); return (ISC_R_SUCCESS); + } frozen = dns_zone_getupdatedisabled(zone); if (freeze) { @@ -402,6 +412,8 @@ freezezones(dns_zone_t *zone, void *uap) { freeze ? "freezing" : "thawing", zonename, classstr, sep, vname, isc_result_totext(result)); + if (raw != NULL) + dns_zone_detach(&raw); return (result); } |