summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES59
-rw-r--r--README4
-rw-r--r--bin/named/builtin.c210
-rw-r--r--bin/named/query.c5
-rw-r--r--bin/named/server.c2
-rw-r--r--bin/named/unix/dlz_dlopen_driver.c2
-rw-r--r--lib/bind9/api2
-rw-r--r--lib/bind9/check.c2
-rw-r--r--lib/dns/api2
-rw-r--r--lib/dns/dnssec.c2
-rw-r--r--lib/dns/include/dns/ecdb.h4
-rw-r--r--lib/dns/include/dns/rpz.h2
-rw-r--r--lib/dns/include/dns/sdb.h5
-rw-r--r--lib/dns/include/dns/stats.h2
-rw-r--r--lib/dns/include/dns/tsec.h4
-rw-r--r--lib/dns/include/dns/view.h2
-rw-r--r--lib/dns/rbtdb.c2
-rw-r--r--lib/dns/rdata/generic/tlsa_52.c290
-rw-r--r--lib/dns/rdata/generic/tlsa_52.h35
-rw-r--r--lib/dns/resolver.c228
-rw-r--r--lib/dns/sdb.c91
-rw-r--r--lib/dns/tkey.c4
-rw-r--r--lib/dns/zone.c124
-rw-r--r--lib/isc/pthreads/mutex.c16
-rw-r--r--lib/isccfg/api2
-rw-r--r--lib/isccfg/parser.c24
-rw-r--r--version2
27 files changed, 835 insertions, 292 deletions
diff --git a/CHANGES b/CHANGES
index 19f8e51..e8cfbfe3 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,56 @@
+ --- 9.8.3 released ---
+
+3318. [tuning] Reduce the amount of work performed while holding a
+ bucket lock when finshed with a fetch context.
+ [RT #29239]
+
+3314. [bug] The masters list could be updated while refesh_callback
+ and stub_callback were using it. [RT #26732]
+
+3313. [protocol] Add TLSA record type. [RT #28989]
+
+3312. [bug] named-checkconf didn't detect a bad dns64 clients acl.
+ [RT #27631]
+
+3311. [bug] Abort the zone dump if zone->db is NULL in
+ zone.c:zone_gotwritehandle. [RT #29028]
+
+3310. [test] Increase table size for mutex profiling. [RT #28809]
+
+3309. [bug] resolver.c:fctx_finddone() was not threadsafe.
+ [RT #27995]
+
+3307. [bug] Add missing ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS.
+ [RT #28956]
+
+3306. [bug] Improve DNS64 reverse zone performance. [RT #28563]
+
+3305. [func] Add wire format lookup method to sdb. [RT #28563]
+
+3304. [bug] Use hmctx, not mctx when freeing rbtdb->heaps.
+ [RT #28571]
+
+3302. [bug] dns_dnssec_findmatchingkeys could fail to find
+ keys if the zone name contained character that
+ required special mappings. [RT #28600]
+
+3301. [contrib] Update queryperf to build on darwin. Add -R flag
+ for non-recursive queries. [RT #28565]
+
+3300. [bug] Named could die if gssapi was enabled in named.conf
+ but was not compiled in. [RT #28338]
+
+3299. [bug] Make SDB handle errors from database drivers better.
+ [RT #28534]
+
+3232. [bug] Zero zone->curmaster before return in
+ dns_zone_setmasterswithkeys(). [RT #26732]
+
+3183. [bug] Added RTLD_GLOBAL flag to dlopen call. [RT #26301]
+
+3197. [bug] Don't try to log the filename and line number when
+ the config parser can't open a file. [RT #22263]
+
--- 9.8.2 released ---
3298. [bug] Named could dereference a NULL pointer in
@@ -58,9 +111,9 @@
3274. [bug] Log when a zone is not reusable. Only set loadtime
on successful loads. [RT #27650]
-3273. [bug] AAAA responses could be returned in the additional
- section even when filter-aaaa-on-v4 was in use.
- [RT #27292]
+3273. [bug] AAAA responses could be returned in the additional
+ section even when filter-aaaa-on-v4 was in use.
+ [RT #27292]
3271. [port] darwin: mksymtbl is not always stable, loop several
times before giving up. mksymtbl was using non
diff --git a/README b/README
index d78fb85..ee56344 100644
--- a/README
+++ b/README
@@ -51,6 +51,10 @@ BIND 9
For up-to-date release notes and errata, see
http://www.isc.org/software/bind9/releasenotes
+BIND 9.8.3
+
+ BIND 9.8.3 is a maintenance release.
+
BIND 9.8.2
BIND 9.8.2 includes a number of bug fixes and prevents a security
diff --git a/bin/named/builtin.c b/bin/named/builtin.c
index 86afa5a..754e73d 100644
--- a/bin/named/builtin.c
+++ b/bin/named/builtin.c
@@ -69,35 +69,79 @@ static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL };
static builtin_t dns64_builtin = { do_dns64_lookup, NULL, NULL };
static dns_sdbimplementation_t *builtin_impl;
+static dns_sdbimplementation_t *dns64_impl;
-static const char hex[] = "0123456789abcdef";
-static const char HEX[] = "0123456789ABCDEF";
+/*
+ * Pre computed HEX * 16 or 1 table.
+ */
+static const unsigned char hex16[256] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*00*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*20*/
+ 0, 16, 32, 48, 64, 80, 96,112,128,144, 1, 1, 1, 1, 1, 1, /*30*/
+ 1,160,176,192,208,224,240, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*50*/
+ 1,160,176,192,208,224,240, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*60*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*70*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*A0*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*B0*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*C0*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*D0*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*E0*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /*F0*/
+};
+
+const unsigned char decimal[] = "0123456789";
+
+static size_t
+dns64_rdata(unsigned char *v, size_t start, unsigned char *rdata) {
+ size_t i, j = 0;
+
+ for (i = 0; i < 4; i++) {
+ unsigned char c = v[start++];
+ if (start == 7)
+ start++;
+ if (c > 99) {
+ rdata[j++] = 3;
+ rdata[j++] = decimal[c/100]; c = c % 100;
+ rdata[j++] = decimal[c/10]; c = c % 10;
+ rdata[j++] = decimal[c];
+ } else if (c > 9) {
+ rdata[j++] = 2;
+ rdata[j++] = decimal[c/10]; c = c % 10;
+ rdata[j++] = decimal[c];
+ } else {
+ rdata[j++] = 1;
+ rdata[j++] = decimal[c];
+ }
+ }
+ memcpy(&rdata[j], "\07in-addr\04arpa", 14);
+ return (j + 14);
+}
static isc_result_t
-dns64_cname(const char *zone, const char *name, dns_sdblookup_t *lookup) {
- size_t zlen, nlen, j;
- const char *s;
- unsigned char v[16];
+dns64_cname(const dns_name_t *zone, const dns_name_t *name,
+ dns_sdblookup_t *lookup)
+{
+ size_t zlen, nlen, j, len;
+ unsigned char v[16], n;
unsigned int i;
- char reverse[sizeof("123.123.123.123.in-addr.arpa.")];
+ unsigned char rdata[sizeof("123.123.123.123.in-addr.arpa.")];
+ unsigned char *ndata;
/*
- * The sum the length of the relative name and the length of the zone
- * name for a IPv6 reverse lookup comes to 71.
+ * The combined length of the zone and name is 74.
*
- * The reverse of 2001::10.0.0.1 (dns64 2001::/96) has a zone of
- * "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.2.ip6.arpa"
- * and a name of "1.0.0.0.0.0.a.0". The sum of the lengths of these
- * two strings is 71.
+ * The minimum zone length is 10 ((3)ip6(4)arpa(0)).
*
- * The minimum length for a ip6.arpa zone name is 8.
- *
- * The length of name should always be odd as we are expecting
+ * The length of name should always be even as we are expecting
* a series of nibbles.
*/
- zlen = strlen(zone);
- nlen = strlen(name);
- if ((zlen + nlen) > 71U || zlen < 8U || (nlen % 2) != 1U)
+ zlen = zone->length;
+ nlen = name->length;
+ if ((zlen + nlen) > 74U || zlen < 10U || (nlen % 2) != 0U)
return (ISC_R_NOTFOUND);
/*
@@ -116,25 +160,20 @@ dns64_cname(const char *zone, const char *name, dns_sdblookup_t *lookup) {
* are byte aligned and we correctly return ISC_R_NOTFOUND or
* ISC_R_SUCCESS. We will not generate a CNAME in this case.
*/
- i = (nlen % 4) == 1U ? 1 : 0;
+ ndata = name->ndata;
+ i = (nlen % 4) == 2U ? 1 : 0;
j = nlen;
memset(v, 0, sizeof(v));
- while (j >= 1U) {
+ while (j != 0) {
INSIST((i/2) < sizeof(v));
- if (j > 1U && name[1] != '.')
+ if (ndata[0] != 1)
return (ISC_R_NOTFOUND);
- v[i/2] >>= 4;
- if ((s = strchr(hex, name[0])) != NULL)
- v[i/2] |= (s - hex) << 4;
- else if ((s = strchr(HEX, name[0])) != NULL)
- v[i/2] |= (s - HEX) << 4;
- else
+ n = hex16[ndata[1]&0xff];
+ if (n == 1)
return (ISC_R_NOTFOUND);
- if (j > 1U)
- j -= 2;
- else
- j -= 1;
- name += 2;
+ v[i/2] = n | (v[i/2]>>4);
+ j -= 2;
+ ndata += 2;
i++;
}
@@ -144,90 +183,91 @@ dns64_cname(const char *zone, const char *name, dns_sdblookup_t *lookup) {
* it corresponds to a empty node in the zone or there should be
* a CNAME.
*/
+#define ZLEN(x) (10 + (x)/2)
switch (zlen) {
- case 24: /* prefix len 32 */
+ case ZLEN(32): /* prefix len 32 */
/*
- * If the total length is not 71 then this is a empty node
+ * The nibbles that map to this byte must be zero for 'name'
+ * to exist in the zone.
+ */
+ if (nlen > 16U && v[(nlen-1)/4 - 4] != 0)
+ return (ISC_R_NOTFOUND);
+ /*
+ * If the total length is not 74 then this is a empty node
* so return success.
*/
- if (nlen + zlen != 71U)
+ if (nlen + zlen != 74U)
return (ISC_R_SUCCESS);
- snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
- v[8], v[9], v[10], v[11]);
+ len = dns64_rdata(v, 8, rdata);
break;
- case 28: /* prefix len 40 */
+ case ZLEN(40): /* prefix len 40 */
/*
* The nibbles that map to this byte must be zero for 'name'
* to exist in the zone.
*/
- if (nlen > 11U && v[nlen/4 - 3] != 0)
+ if (nlen > 12U && v[(nlen-1)/4 - 3] != 0)
return (ISC_R_NOTFOUND);
/*
- * If the total length is not 71 then this is a empty node
+ * If the total length is not 74 then this is a empty node
* so return success.
*/
- if (nlen + zlen != 71U)
+ if (nlen + zlen != 74U)
return (ISC_R_SUCCESS);
- snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
- v[6], v[8], v[9], v[10]);
+ len = dns64_rdata(v, 6, rdata);
break;
- case 32: /* prefix len 48 */
+ case ZLEN(48): /* prefix len 48 */
/*
* The nibbles that map to this byte must be zero for 'name'
* to exist in the zone.
*/
- if (nlen > 7U && v[nlen/4 - 2] != 0)
+ if (nlen > 8U && v[(nlen-1)/4 - 2] != 0)
return (ISC_R_NOTFOUND);
/*
- * If the total length is not 71 then this is a empty node
+ * If the total length is not 74 then this is a empty node
* so return success.
*/
- if (nlen + zlen != 71U)
+ if (nlen + zlen != 74U)
return (ISC_R_SUCCESS);
- snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
- v[5], v[6], v[8], v[9]);
+ len = dns64_rdata(v, 5, rdata);
break;
- case 36: /* prefix len 56 */
+ case ZLEN(56): /* prefix len 56 */
/*
* The nibbles that map to this byte must be zero for 'name'
* to exist in the zone.
*/
- if (nlen > 3U && v[nlen/4 - 1] != 0)
+ if (nlen > 4U && v[(nlen-1)/4 - 1] != 0)
return (ISC_R_NOTFOUND);
/*
- * If the total length is not 71 then this is a empty node
+ * If the total length is not 74 then this is a empty node
* so return success.
*/
- if (nlen + zlen != 71U)
+ if (nlen + zlen != 74U)
return (ISC_R_SUCCESS);
- snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
- v[4], v[5], v[6], v[8]);
+ len = dns64_rdata(v, 4, rdata);
break;
- case 40: /* prefix len 64 */
+ case ZLEN(64): /* prefix len 64 */
/*
* The nibbles that map to this byte must be zero for 'name'
* to exist in the zone.
*/
- if (v[nlen/4] != 0)
+ if (v[(nlen-1)/4] != 0)
return (ISC_R_NOTFOUND);
/*
- * If the total length is not 71 then this is a empty node
+ * If the total length is not 74 then this is a empty node
* so return success.
*/
- if (nlen + zlen != 71U)
+ if (nlen + zlen != 74U)
return (ISC_R_SUCCESS);
- snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
- v[3], v[4], v[5], v[6]);
+ len = dns64_rdata(v, 3, rdata);
break;
- case 56: /* prefix len 96 */
+ case ZLEN(96): /* prefix len 96 */
/*
- * If the total length is not 71 then this is a empty node
+ * If the total length is not 74 then this is a empty node
* so return success.
*/
- if (nlen + zlen != 71U)
+ if (nlen + zlen != 74U)
return (ISC_R_SUCCESS);
- snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
- v[0], v[1], v[2], v[3]);
+ len = dns64_rdata(v, 0, rdata);
break;
default:
/*
@@ -236,7 +276,7 @@ dns64_cname(const char *zone, const char *name, dns_sdblookup_t *lookup) {
*/
return (ISC_R_NOTFOUND);
}
- return (dns_sdb_putrr(lookup, "CNAME", 600, reverse));
+ return (dns_sdb_putrdata(lookup, dns_rdatatype_cname, 600, rdata, len));
}
static isc_result_t
@@ -249,13 +289,23 @@ builtin_lookup(const char *zone, const char *name, void *dbdata,
if (strcmp(name, "@") == 0)
return (b->do_lookup(lookup));
- else if (b->do_lookup == do_dns64_lookup)
- return (dns64_cname(zone, name, lookup));
else
return (ISC_R_NOTFOUND);
}
static isc_result_t
+dns64_lookup(const dns_name_t *zone, const dns_name_t *name, void *dbdata,
+ dns_sdblookup_t *lookup)
+{
+ builtin_t *b = (builtin_t *) dbdata;
+
+ if (name->labels == 0 && name->length == 0)
+ return (b->do_lookup(lookup));
+ else
+ return (dns64_cname(zone, name, lookup));
+}
+
+static isc_result_t
put_txt(dns_sdblookup_t *lookup, const char *text) {
unsigned char buf[256];
unsigned int len = strlen(text);
@@ -481,7 +531,17 @@ static dns_sdbmethods_t builtin_methods = {
builtin_authority,
NULL, /* allnodes */
builtin_create,
- builtin_destroy
+ builtin_destroy,
+ NULL
+};
+
+static dns_sdbmethods_t dns64_methods = {
+ NULL,
+ builtin_authority,
+ NULL, /* allnodes */
+ builtin_create,
+ builtin_destroy,
+ dns64_lookup,
};
isc_result_t
@@ -491,11 +551,17 @@ ns_builtin_init(void) {
DNS_SDBFLAG_RELATIVERDATA,
ns_g_mctx, &builtin_impl)
== ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_sdb_register("_dns64", &dns64_methods, NULL,
+ DNS_SDBFLAG_RELATIVEOWNER |
+ DNS_SDBFLAG_RELATIVERDATA |
+ DNS_SDBFLAG_DNS64,
+ ns_g_mctx, &dns64_impl)
+ == ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
}
void
ns_builtin_deinit(void) {
dns_sdb_unregister(&builtin_impl);
+ dns_sdb_unregister(&dns64_impl);
}
-
diff --git a/bin/named/query.c b/bin/named/query.c
index 6d2ee44..9464a82 100644
--- a/bin/named/query.c
+++ b/bin/named/query.c
@@ -3354,6 +3354,11 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db,
dns_name_copy(name, cname, NULL);
while (result == DNS_R_NXDOMAIN) {
labels = dns_name_countlabels(cname) - 1;
+ /*
+ * Sanity check.
+ */
+ if (labels == 0U)
+ goto cleanup;
dns_name_split(cname, labels, NULL, cname);
result = dns_db_find(db, cname, version,
dns_rdatatype_nsec,
diff --git a/bin/named/server.c b/bin/named/server.c
index 46f26c4..666d854 100644
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -1358,7 +1358,7 @@ dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na,
{
char *cp;
char reverse[48+sizeof("ip6.arpa.")];
- const char *dns64_dbtype[4] = { "_builtin", "dns64", ".", "." };
+ const char *dns64_dbtype[4] = { "_dns64", "dns64", ".", "." };
const char *sep = ": view ";
const char *viewname = view->name;
const unsigned char *s6;
diff --git a/bin/named/unix/dlz_dlopen_driver.c b/bin/named/unix/dlz_dlopen_driver.c
index ca4b1fd..edd3946 100644
--- a/bin/named/unix/dlz_dlopen_driver.c
+++ b/bin/named/unix/dlz_dlopen_driver.c
@@ -250,7 +250,7 @@ dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
isc_mutex_init(&cd->lock);
/* Open the library */
- dlopen_flags = RTLD_NOW;
+ dlopen_flags = RTLD_NOW|RTLD_GLOBAL;
#ifdef RTLD_DEEPBIND
/*
diff --git a/lib/bind9/api b/lib/bind9/api
index 74bc338..089e782 100644
--- a/lib/bind9/api
+++ b/lib/bind9/api
@@ -4,5 +4,5 @@
# 9.8: 80-89
# 9.9: 90-109
LIBINTERFACE = 80
-LIBREVISION = 4
+LIBREVISION = 5
LIBAGE = 0
diff --git a/lib/bind9/check.c b/lib/bind9/check.c
index 695a230..26eaa1a 100644
--- a/lib/bind9/check.c
+++ b/lib/bind9/check.c
@@ -434,7 +434,7 @@ check_dns64(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
int nbytes;
int i;
- static const char *acls[] = { "client", "exclude", "mapped", NULL};
+ static const char *acls[] = { "clients", "exclude", "mapped", NULL};
if (voptions != NULL)
cfg_map_get(voptions, "dns64", &dns64);
diff --git a/lib/dns/api b/lib/dns/api
index 69ec5c4..9e783a5 100644
--- a/lib/dns/api
+++ b/lib/dns/api
@@ -4,5 +4,5 @@
# 9.8: 80-89
# 9.9: 90-109
LIBINTERFACE = 87
-LIBREVISION = 0
+LIBREVISION = 1
LIBAGE = 6
diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c
index 34dd464..b72e82d 100644
--- a/lib/dns/dnssec.c
+++ b/lib/dns/dnssec.c
@@ -1246,7 +1246,7 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory,
isc_dir_init(&dir);
isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1);
- RETERR(dns_name_totext(origin, ISC_FALSE, &b));
+ RETERR(dns_name_tofilenametext(origin, ISC_FALSE, &b));
len = isc_buffer_usedlength(&b);
namebuf[len] = '\0';
diff --git a/lib/dns/include/dns/ecdb.h b/lib/dns/include/dns/ecdb.h
index 5c735b5..246cc30 100644
--- a/lib/dns/include/dns/ecdb.h
+++ b/lib/dns/include/dns/ecdb.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009, 2012 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
@@ -39,6 +39,8 @@
*** Functions
***/
+ISC_LANG_BEGINDECLS
+
/* TBD: describe those */
isc_result_t
diff --git a/lib/dns/include/dns/rpz.h b/lib/dns/include/dns/rpz.h
index fbbe539..59d4f87 100644
--- a/lib/dns/include/dns/rpz.h
+++ b/lib/dns/include/dns/rpz.h
@@ -194,5 +194,7 @@ dns_rpz_cidr_find(dns_rpz_cidr_t *cidr, const isc_netaddr_t *netaddr,
dns_rpz_policy_t
dns_rpz_decode_cname(dns_rdataset_t *, dns_name_t *selfname);
+ISC_LANG_ENDDECLS
+
#endif /* DNS_RPZ_H */
diff --git a/lib/dns/include/dns/sdb.h b/lib/dns/include/dns/sdb.h
index 4b3ab48..c57c4a1 100644
--- a/lib/dns/include/dns/sdb.h
+++ b/lib/dns/include/dns/sdb.h
@@ -59,6 +59,9 @@ typedef struct dns_sdballnodes dns_sdballnodes_t;
typedef isc_result_t
(*dns_sdblookupfunc_t)(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *);
+typedef isc_result_t
+(*dns_sdblookup2func_t)(const dns_name_t *zone, const dns_name_t *name,
+ void *dbdata, dns_sdblookup_t *lookup);
typedef isc_result_t
(*dns_sdbauthorityfunc_t)(const char *zone, void *dbdata, dns_sdblookup_t *);
@@ -81,6 +84,7 @@ typedef struct dns_sdbmethods {
dns_sdballnodesfunc_t allnodes;
dns_sdbcreatefunc_t create;
dns_sdbdestroyfunc_t destroy;
+ dns_sdblookup2func_t lookup2;
} dns_sdbmethods_t;
/***
@@ -92,6 +96,7 @@ ISC_LANG_BEGINDECLS
#define DNS_SDBFLAG_RELATIVEOWNER 0x00000001U
#define DNS_SDBFLAG_RELATIVERDATA 0x00000002U
#define DNS_SDBFLAG_THREADSAFE 0x00000004U
+#define DNS_SDBFLAG_DNS64 0x00000008U
isc_result_t
dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
diff --git a/lib/dns/include/dns/stats.h b/lib/dns/include/dns/stats.h
index b8dc17e..bc77d1e 100644
--- a/lib/dns/include/dns/stats.h
+++ b/lib/dns/include/dns/stats.h
@@ -147,6 +147,8 @@ typedef void (*dns_rdatatypestats_dumper_t)(dns_rdatastatstype_t, isc_uint64_t,
void *);
typedef void (*dns_opcodestats_dumper_t)(dns_opcode_t, isc_uint64_t, void *);
+ISC_LANG_BEGINDECLS
+
isc_result_t
dns_generalstats_create(isc_mem_t *mctx, dns_stats_t **statsp, int ncounters);
/*%<
diff --git a/lib/dns/include/dns/tsec.h b/lib/dns/include/dns/tsec.h
index a9d60c2..4f31c3e 100644
--- a/lib/dns/include/dns/tsec.h
+++ b/lib/dns/include/dns/tsec.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009, 2010, 2012 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
@@ -132,4 +132,6 @@ dns_tsec_getkey(dns_tsec_t *tsec, void *keyp);
*\li *tsecp points to a valid key structure depending on the TSEC type.
*/
+ISC_LANG_ENDDECLS
+
#endif /* DNS_TSEC_H */
diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h
index 6f7140c..7db600b 100644
--- a/lib/dns/include/dns/view.h
+++ b/lib/dns/include/dns/view.h
@@ -1075,4 +1075,6 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
void
dns_view_restorekeyring(dns_view_t *view);
+ISC_LANG_ENDDECLS
+
#endif /* DNS_VIEW_H */
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index 1550221..a2523ba 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -7814,7 +7814,7 @@ dns_rbtdb_create
for (i = 0 ; i < (int)rbtdb->node_lock_count ; i++)
if (rbtdb->heaps[i] != NULL)
isc_heap_destroy(&rbtdb->heaps[i]);
- isc_mem_put(mctx, rbtdb->heaps,
+ isc_mem_put(hmctx, rbtdb->heaps,
rbtdb->node_lock_count * sizeof(isc_heap_t *));
}
diff --git a/lib/dns/rdata/generic/tlsa_52.c b/lib/dns/rdata/generic/tlsa_52.c
new file mode 100644
index 0000000..11c6d75
--- /dev/null
+++ b/lib/dns/rdata/generic/tlsa_52.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2012 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$ */
+
+/* draft-ietf-dane-protocol-19.txt */
+
+#ifndef RDATA_GENERIC_TLSA_52_C
+#define RDATA_GENERIC_TLSA_52_C
+
+#define RRTYPE_TLSA_ATTRIBUTES 0
+
+static inline isc_result_t
+fromtext_tlsa(ARGS_FROMTEXT) {
+ isc_token_t token;
+
+ REQUIRE(type == 52);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * Certificate Usage.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Selector.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Matching type.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Certificate Association Data.
+ */
+ return (isc_hex_tobuffer(lexer, target, -1));
+}
+
+static inline isc_result_t
+totext_tlsa(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000 ")];
+ unsigned int n;
+
+ REQUIRE(rdata->type == 52);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Certificate Usage.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Selector.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Matching type.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Certificate Association Data.
+ */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" (", target));
+ RETERR(str_totext(tctx->linebreak, target));
+ if (tctx->width == 0) /* No splitting */
+ RETERR(isc_hex_totext(&sr, 0, "", target));
+ else
+ RETERR(isc_hex_totext(&sr, tctx->width - 2,
+ tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_tlsa(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 52);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+
+ if (sr.length < 3)
+ return (ISC_R_UNEXPECTEDEND);
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_tlsa(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 52);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_tlsa(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 52);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_tlsa(ARGS_FROMSTRUCT) {
+ dns_rdata_tlsa_t *tlsa = source;
+
+ REQUIRE(type == 52);
+ REQUIRE(source != NULL);
+ REQUIRE(tlsa->common.rdtype == type);
+ REQUIRE(tlsa->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(tlsa->usage, target));
+ RETERR(uint8_tobuffer(tlsa->selector, target));
+ RETERR(uint8_tobuffer(tlsa->match, target));
+
+ return (mem_tobuffer(target, tlsa->data, tlsa->length));
+}
+
+static inline isc_result_t
+tostruct_tlsa(ARGS_TOSTRUCT) {
+ dns_rdata_tlsa_t *tlsa = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 52);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ tlsa->common.rdclass = rdata->rdclass;
+ tlsa->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&tlsa->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ tlsa->usage = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ tlsa->selector = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ tlsa->match = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ tlsa->length = region.length;
+
+ tlsa->data = mem_maybedup(mctx, region.base, region.length);
+ if (tlsa->data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ tlsa->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_tlsa(ARGS_FREESTRUCT) {
+ dns_rdata_tlsa_t *tlsa = source;
+
+ REQUIRE(tlsa != NULL);
+ REQUIRE(tlsa->common.rdtype == 52);
+
+ if (tlsa->mctx == NULL)
+ return;
+
+ if (tlsa->data != NULL)
+ isc_mem_free(tlsa->mctx, tlsa->data);
+ tlsa->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_tlsa(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 52);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_tlsa(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 52);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_tlsa(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 52);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_tlsa(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 52);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+static inline int
+casecompare_tlsa(ARGS_COMPARE) {
+ return (compare_tlsa(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_TLSA_52_C */
diff --git a/lib/dns/rdata/generic/tlsa_52.h b/lib/dns/rdata/generic/tlsa_52.h
new file mode 100644
index 0000000..83ce952
--- /dev/null
+++ b/lib/dns/rdata/generic/tlsa_52.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 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$ */
+
+#ifndef GENERIC_TLSA_52_H
+#define GENERIC_TLSA_52_H 1
+
+/*!
+ * \brief per draft-ietf-dane-protocol-19.txt
+ */
+typedef struct dns_rdata_tlsa {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint8_t usage;
+ isc_uint8_t selector;
+ isc_uint8_t match;
+ isc_uint16_t length;
+ unsigned char *data;
+} dns_rdata_tlsa_t;
+
+#endif /* GENERIC_TLSA_52_H */
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index 3084dd8..1ae2f16 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -180,7 +180,9 @@ struct fetchctx {
dns_rdatatype_t type;
unsigned int options;
unsigned int bucketnum;
- char * info;
+ char * info;
+ isc_mem_t * mctx;
+
/*% Locked by appropriate bucket lock. */
fetchstate state;
isc_boolean_t want_shutdown;
@@ -446,7 +448,8 @@ static void resquery_response(isc_task_t *task, isc_event_t *event);
static void resquery_connected(isc_task_t *task, isc_event_t *event);
static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying,
isc_boolean_t badcache);
-static isc_boolean_t fctx_destroy(fetchctx_t *fctx);
+static void fctx_destroy(fetchctx_t *fctx);
+static isc_boolean_t fctx_unlink(fetchctx_t *fctx);
static isc_result_t ncache_adderesult(dns_message_t *message,
dns_db_t *cache, dns_dbnode_t *node,
dns_rdatatype_t covers,
@@ -478,8 +481,7 @@ valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
dns_valarg_t *valarg;
isc_result_t result;
- valarg = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
- sizeof(*valarg));
+ valarg = isc_mem_get(fctx->mctx, sizeof(*valarg));
if (valarg == NULL)
return (ISC_R_NOMEMORY);
@@ -501,8 +503,7 @@ valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
}
ISC_LIST_APPEND(fctx->validators, validator, link);
} else
- isc_mem_put(fctx->res->buckets[fctx->bucketnum].mctx,
- valarg, sizeof(*valarg));
+ isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
return (result);
}
@@ -1386,13 +1387,12 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
- query = isc_mem_get(res->buckets[fctx->bucketnum].mctx,
- sizeof(*query));
+ query = isc_mem_get(fctx->mctx, sizeof(*query));
if (query == NULL) {
result = ISC_R_NOMEMORY;
goto stop_idle_timer;
}
- query->mctx = res->buckets[fctx->bucketnum].mctx;
+ query->mctx = fctx->mctx;
query->options = options;
query->attributes = 0;
query->sends = 0;
@@ -1569,8 +1569,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
cleanup_query:
if (query->connects == 0) {
query->magic = 0;
- isc_mem_put(res->buckets[fctx->bucketnum].mctx,
- query, sizeof(*query));
+ isc_mem_put(fctx->mctx, query, sizeof(*query));
}
stop_idle_timer:
@@ -1600,8 +1599,7 @@ add_bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
if (bad_edns(fctx, address))
return;
- sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
- sizeof(*sa));
+ sa = isc_mem_get(fctx->mctx, sizeof(*sa));
if (sa == NULL)
return;
@@ -1630,8 +1628,7 @@ add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
if (triededns(fctx, address))
return;
- sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
- sizeof(*sa));
+ sa = isc_mem_get(fctx->mctx, sizeof(*sa));
if (sa == NULL)
return;
@@ -1660,8 +1657,7 @@ add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
if (triededns512(fctx, address))
return;
- sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
- sizeof(*sa));
+ sa = isc_mem_get(fctx->mctx, sizeof(*sa));
if (sa == NULL)
return;
@@ -2166,8 +2162,8 @@ 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;
+ isc_boolean_t destroy = ISC_FALSE;
find = event->ev_sender;
fctx = event->ev_arg;
@@ -2205,17 +2201,14 @@ 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)) {
- /*
- * Note that we had to wait until we had the lock before
- * looking at fctx->references.
- */
- if (fctx->references == 0)
+
+ if (fctx->references == 0) {
+ bucket_empty = fctx_unlink(fctx);
destroy = ISC_TRUE;
+ }
}
UNLOCK(&res->buckets[bucketnum].lock);
- if (destroy)
- bucket_empty = fctx_destroy(fctx);
isc_event_free(&event);
dns_adb_destroyfind(&find);
@@ -2223,8 +2216,11 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
fctx_try(fctx, ISC_TRUE, ISC_FALSE);
else if (want_done)
fctx_done(fctx, ISC_R_FAILURE, __LINE__);
- else if (bucket_empty)
- empty_bucket(res);
+ else if (destroy) {
+ fctx_destroy(fctx);
+ if (bucket_empty)
+ empty_bucket(res);
+ }
}
@@ -2347,8 +2343,7 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
FCTXTRACE("add_bad");
- sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
- sizeof(*sa));
+ sa = isc_mem_get(fctx->mctx, sizeof(*sa));
if (sa == NULL)
return;
*sa = *address;
@@ -2631,12 +2626,9 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
fctx->fwdpolicy = forwarders->fwdpolicy;
if (fctx->fwdpolicy == dns_fwdpolicy_only &&
isstrictsubdomain(domain, &fctx->domain)) {
- isc_mem_t *mctx;
-
- mctx = res->buckets[fctx->bucketnum].mctx;
- dns_name_free(&fctx->domain, mctx);
+ dns_name_free(&fctx->domain, fctx->mctx);
dns_name_init(&fctx->domain, NULL);
- result = dns_name_dup(domain, mctx,
+ result = dns_name_dup(domain, fctx->mctx,
&fctx->domain);
if (result != ISC_R_SUCCESS)
return (result);
@@ -3075,10 +3067,9 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
}
static isc_boolean_t
-fctx_destroy(fetchctx_t *fctx) {
+fctx_unlink(fetchctx_t *fctx) {
dns_resolver_t *res;
unsigned int bucketnum;
- isc_sockaddr_t *sa, *next_sa;
/*
* Caller must be holding the bucket lock.
@@ -3095,13 +3086,42 @@ fctx_destroy(fetchctx_t *fctx) {
REQUIRE(fctx->references == 0);
REQUIRE(ISC_LIST_EMPTY(fctx->validators));
- FCTXTRACE("destroy");
+ FCTXTRACE("unlink");
res = fctx->res;
bucketnum = fctx->bucketnum;
ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
+ LOCK(&res->nlock);
+ res->nfctx--;
+ UNLOCK(&res->nlock);
+
+ if (res->buckets[bucketnum].exiting &&
+ ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+static void
+fctx_destroy(fetchctx_t *fctx) {
+ isc_sockaddr_t *sa, *next_sa;
+
+ REQUIRE(VALID_FCTX(fctx));
+ REQUIRE(fctx->state == fetchstate_done ||
+ fctx->state == fetchstate_init);
+ REQUIRE(ISC_LIST_EMPTY(fctx->events));
+ REQUIRE(ISC_LIST_EMPTY(fctx->queries));
+ REQUIRE(ISC_LIST_EMPTY(fctx->finds));
+ REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
+ REQUIRE(fctx->pending == 0);
+ REQUIRE(fctx->references == 0);
+ REQUIRE(ISC_LIST_EMPTY(fctx->validators));
+ REQUIRE(!ISC_LINK_LINKED(fctx, link));
+
+ FCTXTRACE("destroy");
+
/*
* Free bad.
*/
@@ -3110,7 +3130,7 @@ fctx_destroy(fetchctx_t *fctx) {
sa = next_sa) {
next_sa = ISC_LIST_NEXT(sa, link);
ISC_LIST_UNLINK(fctx->bad, sa, link);
- isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
+ isc_mem_put(fctx->mctx, sa, sizeof(*sa));
}
for (sa = ISC_LIST_HEAD(fctx->edns);
@@ -3118,7 +3138,7 @@ fctx_destroy(fetchctx_t *fctx) {
sa = next_sa) {
next_sa = ISC_LIST_NEXT(sa, link);
ISC_LIST_UNLINK(fctx->edns, sa, link);
- isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
+ isc_mem_put(fctx->mctx, sa, sizeof(*sa));
}
for (sa = ISC_LIST_HEAD(fctx->edns512);
@@ -3126,7 +3146,7 @@ fctx_destroy(fetchctx_t *fctx) {
sa = next_sa) {
next_sa = ISC_LIST_NEXT(sa, link);
ISC_LIST_UNLINK(fctx->edns512, sa, link);
- isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
+ isc_mem_put(fctx->mctx, sa, sizeof(*sa));
}
for (sa = ISC_LIST_HEAD(fctx->bad_edns);
@@ -3134,31 +3154,21 @@ fctx_destroy(fetchctx_t *fctx) {
sa = next_sa) {
next_sa = ISC_LIST_NEXT(sa, link);
ISC_LIST_UNLINK(fctx->bad_edns, sa, link);
- isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
+ isc_mem_put(fctx->mctx, sa, sizeof(*sa));
}
isc_timer_detach(&fctx->timer);
dns_message_destroy(&fctx->rmessage);
dns_message_destroy(&fctx->qmessage);
if (dns_name_countlabels(&fctx->domain) > 0)
- dns_name_free(&fctx->domain, res->buckets[bucketnum].mctx);
+ dns_name_free(&fctx->domain, fctx->mctx);
if (dns_rdataset_isassociated(&fctx->nameservers))
dns_rdataset_disassociate(&fctx->nameservers);
- dns_name_free(&fctx->name, res->buckets[bucketnum].mctx);
+ dns_name_free(&fctx->name, fctx->mctx);
dns_db_detach(&fctx->cache);
dns_adb_detach(&fctx->adb);
- isc_mem_free(res->buckets[bucketnum].mctx, fctx->info);
- isc_mem_put(res->buckets[bucketnum].mctx, fctx, sizeof(*fctx));
-
- LOCK(&res->nlock);
- res->nfctx--;
- UNLOCK(&res->nlock);
-
- if (res->buckets[bucketnum].exiting &&
- ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
- return (ISC_TRUE);
-
- return (ISC_FALSE);
+ isc_mem_free(fctx->mctx, fctx->info);
+ isc_mem_putanddetach(&fctx->mctx, fctx, sizeof(*fctx));
}
/*
@@ -3258,6 +3268,7 @@ fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
dns_resolver_t *res;
unsigned int bucketnum;
dns_validator_t *validator;
+ isc_boolean_t destroy = ISC_FALSE;
REQUIRE(VALID_FCTX(fctx));
@@ -3307,13 +3318,18 @@ fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
}
if (fctx->references == 0 && fctx->pending == 0 &&
- fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators))
- bucket_empty = fctx_destroy(fctx);
+ fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
+ bucket_empty = fctx_unlink(fctx);
+ destroy = ISC_TRUE;
+ }
UNLOCK(&res->buckets[bucketnum].lock);
- if (bucket_empty)
- empty_bucket(res);
+ if (destroy) {
+ fctx_destroy(fctx);
+ if (bucket_empty)
+ empty_bucket(res);
+ }
}
static void
@@ -3322,6 +3338,7 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;
dns_resolver_t *res;
unsigned int bucketnum;
+ isc_boolean_t destroy = ISC_FALSE;
REQUIRE(VALID_FCTX(fctx));
@@ -3354,7 +3371,8 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
/*
* It's now safe to destroy this fctx.
*/
- bucket_empty = fctx_destroy(fctx);
+ bucket_empty = fctx_unlink(fctx);
+ destroy = ISC_TRUE;
}
done = ISC_TRUE;
} else {
@@ -3376,6 +3394,8 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
if (!done) {
isc_result_t result;
+ INSIST(!destroy);
+
/*
* All is well. Start working on the fetch.
*/
@@ -3384,8 +3404,11 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
fctx_done(fctx, result, __LINE__);
else
fctx_try(fctx, ISC_FALSE, ISC_FALSE);
- } else if (bucket_empty)
- empty_bucket(res);
+ } else if (destroy) {
+ fctx_destroy(fctx);
+ if (bucket_empty)
+ empty_bucket(res);
+ }
}
/*
@@ -3473,27 +3496,29 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
char typebuf[DNS_RDATATYPE_FORMATSIZE];
dns_name_t suffix;
+ isc_mem_t *mctx;
/*
* Caller must be holding the lock for bucket number 'bucketnum'.
*/
REQUIRE(fctxp != NULL && *fctxp == NULL);
- fctx = isc_mem_get(res->buckets[bucketnum].mctx, sizeof(*fctx));
+ mctx = res->buckets[bucketnum].mctx;
+ fctx = isc_mem_get(mctx, sizeof(*fctx));
if (fctx == NULL)
return (ISC_R_NOMEMORY);
dns_name_format(name, buf, sizeof(buf));
dns_rdatatype_format(type, typebuf, sizeof(typebuf));
strcat(buf, "/"); /* checked */
strcat(buf, typebuf); /* checked */
- fctx->info = isc_mem_strdup(res->buckets[bucketnum].mctx, buf);
+ fctx->info = isc_mem_strdup(mctx, buf);
if (fctx->info == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup_fetch;
}
FCTXTRACE("create");
dns_name_init(&fctx->name, NULL);
- result = dns_name_dup(name, res->buckets[bucketnum].mctx, &fctx->name);
+ result = dns_name_dup(name, mctx, &fctx->name);
if (result != ISC_R_SUCCESS)
goto cleanup_info;
dns_name_init(&fctx->domain, NULL);
@@ -3596,9 +3621,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
NULL);
if (result != ISC_R_SUCCESS)
goto cleanup_name;
- result = dns_name_dup(domain,
- res->buckets[bucketnum].mctx,
- &fctx->domain);
+ result = dns_name_dup(domain, mctx, &fctx->domain);
if (result != ISC_R_SUCCESS) {
dns_rdataset_disassociate(&fctx->nameservers);
goto cleanup_name;
@@ -3609,16 +3632,12 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
/*
* We're in forward-only mode. Set the query domain.
*/
- result = dns_name_dup(domain,
- res->buckets[bucketnum].mctx,
- &fctx->domain);
+ result = dns_name_dup(domain, mctx, &fctx->domain);
if (result != ISC_R_SUCCESS)
goto cleanup_name;
}
} else {
- result = dns_name_dup(domain,
- res->buckets[bucketnum].mctx,
- &fctx->domain);
+ result = dns_name_dup(domain, mctx, &fctx->domain);
if (result != ISC_R_SUCCESS)
goto cleanup_name;
dns_rdataset_clone(nameservers, &fctx->nameservers);
@@ -3631,16 +3650,14 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
fctx->qmessage = NULL;
- result = dns_message_create(res->buckets[bucketnum].mctx,
- DNS_MESSAGE_INTENTRENDER,
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
&fctx->qmessage);
if (result != ISC_R_SUCCESS)
goto cleanup_domain;
fctx->rmessage = NULL;
- result = dns_message_create(res->buckets[bucketnum].mctx,
- DNS_MESSAGE_INTENTPARSE,
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
&fctx->rmessage);
if (result != ISC_R_SUCCESS)
@@ -3690,6 +3707,8 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
dns_db_attach(res->view->cachedb, &fctx->cache);
fctx->adb = NULL;
dns_adb_attach(res->view->adb, &fctx->adb);
+ fctx->mctx = NULL;
+ isc_mem_attach(mctx, &fctx->mctx);
ISC_LIST_INIT(fctx->events);
ISC_LINK_INIT(fctx, link);
@@ -3713,18 +3732,18 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
cleanup_domain:
if (dns_name_countlabels(&fctx->domain) > 0)
- dns_name_free(&fctx->domain, res->buckets[bucketnum].mctx);
+ dns_name_free(&fctx->domain, mctx);
if (dns_rdataset_isassociated(&fctx->nameservers))
dns_rdataset_disassociate(&fctx->nameservers);
cleanup_name:
- dns_name_free(&fctx->name, res->buckets[bucketnum].mctx);
+ dns_name_free(&fctx->name, mctx);
cleanup_info:
- isc_mem_free(res->buckets[bucketnum].mctx, fctx->info);
+ isc_mem_free(mctx, fctx->info);
cleanup_fetch:
- isc_mem_put(res->buckets[bucketnum].mctx, fctx, sizeof(*fctx));
+ isc_mem_put(mctx, fctx, sizeof(*fctx));
return (result);
}
@@ -3934,6 +3953,7 @@ maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) {
isc_boolean_t bucket_empty = ISC_FALSE;
dns_resolver_t *res = fctx->res;
dns_validator_t *validator, *next_validator;
+ isc_boolean_t destroy = ISC_FALSE;
REQUIRE(SHUTTINGDOWN(fctx));
@@ -3949,11 +3969,15 @@ maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) {
dns_validator_cancel(validator);
}
- if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators))
- bucket_empty = fctx_destroy(fctx);
+ if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators)) {
+ bucket_empty = fctx_unlink(fctx);
+ destroy = ISC_TRUE;
+ }
unlock:
if (!locked)
UNLOCK(&res->buckets[bucketnum].lock);
+ if (destroy)
+ fctx_destroy(fctx);
return (bucket_empty);
}
@@ -4008,8 +4032,7 @@ validated(isc_task_t *task, isc_event_t *event) {
* destroy the fctx if necessary.
*/
dns_validator_destroy(&vevent->validator);
- isc_mem_put(res->buckets[fctx->bucketnum].mctx,
- valarg, sizeof(*valarg));
+ isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
negative = ISC_TF(vevent->rdataset == NULL);
@@ -5723,14 +5746,11 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
* if so we should bail out.
*/
INSIST(dns_name_countlabels(&fctx->domain) > 0);
- dns_name_free(&fctx->domain,
- fctx->res->buckets[fctx->bucketnum].mctx);
+ dns_name_free(&fctx->domain, fctx->mctx);
if (dns_rdataset_isassociated(&fctx->nameservers))
dns_rdataset_disassociate(&fctx->nameservers);
dns_name_init(&fctx->domain, NULL);
- result = dns_name_dup(ns_name,
- fctx->res->buckets[fctx->bucketnum].mctx,
- &fctx->domain);
+ result = dns_name_dup(ns_name, fctx->mctx, &fctx->domain);
if (result != ISC_R_SUCCESS)
return (result);
fctx->attributes |= FCTX_ATTR_WANTCACHE;
@@ -6232,7 +6252,8 @@ fctx_decreference(fetchctx_t *fctx) {
* This fctx is already shutdown; we were just
* waiting for the last reference to go away.
*/
- bucket_empty = fctx_destroy(fctx);
+ bucket_empty = fctx_unlink(fctx);
+ fctx_destroy(fctx);
} else {
/*
* Initiate shutdown.
@@ -6287,12 +6308,9 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
fctx->ns_ttl = fctx->nameservers.ttl;
fctx->ns_ttl_ok = ISC_TRUE;
log_ns_ttl(fctx, "resume_dslookup");
- dns_name_free(&fctx->domain,
- fctx->res->buckets[bucketnum].mctx);
+ dns_name_free(&fctx->domain, fctx->mctx);
dns_name_init(&fctx->domain, NULL);
- result = dns_name_dup(&fctx->nsname,
- fctx->res->buckets[bucketnum].mctx,
- &fctx->domain);
+ result = dns_name_dup(&fctx->nsname, fctx->mctx, &fctx->domain);
if (result != ISC_R_SUCCESS) {
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
goto cleanup;
@@ -7210,12 +7228,9 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
return;
}
- dns_name_free(&fctx->domain,
- fctx->res->buckets[fctx->bucketnum].mctx);
+ dns_name_free(&fctx->domain, fctx->mctx);
dns_name_init(&fctx->domain, NULL);
- result = dns_name_dup(fname,
- fctx->res->buckets[fctx->bucketnum].mctx,
- &fctx->domain);
+ result = dns_name_dup(fname, fctx->mctx, &fctx->domain);
if (result != ISC_R_SUCCESS) {
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
return;
@@ -7955,6 +7970,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
unsigned int count = 0;
unsigned int spillat;
unsigned int spillatmin;
+ isc_boolean_t destroy = ISC_FALSE;
UNUSED(forwarders);
@@ -8052,16 +8068,20 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
isc_task_send(res->buckets[bucketnum].task, &event);
} else {
/*
- * We don't care about the result of fctx_destroy()
+ * We don't care about the result of fctx_unlink()
* since we know we're not exiting.
*/
- (void)fctx_destroy(fctx);
+ (void)fctx_unlink(fctx);
+ destroy = ISC_TRUE;
}
}
unlock:
UNLOCK(&res->buckets[bucketnum].lock);
+ if (destroy)
+ fctx_destroy(fctx);
+
if (result == ISC_R_SUCCESS) {
FTRACE("created");
*fetchp = fetch;
diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c
index 01ab17c..8092c5a 100644
--- a/lib/dns/sdb.c
+++ b/lib/dns/sdb.c
@@ -216,12 +216,13 @@ dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
REQUIRE(drivername != NULL);
REQUIRE(methods != NULL);
- REQUIRE(methods->lookup != NULL);
+ REQUIRE(methods->lookup != NULL || methods->lookup2 != NULL);
REQUIRE(mctx != NULL);
REQUIRE(sdbimp != NULL && *sdbimp == NULL);
REQUIRE((flags & ~(DNS_SDBFLAG_RELATIVEOWNER |
DNS_SDBFLAG_RELATIVERDATA |
- DNS_SDBFLAG_THREADSAFE)) == 0);
+ DNS_SDBFLAG_THREADSAFE|
+ DNS_SDBFLAG_DNS64)) == 0);
imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
if (imp == NULL)
@@ -280,8 +281,9 @@ initial_size(unsigned int len) {
}
isc_result_t
-dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval, dns_ttl_t ttl,
- const unsigned char *rdatap, unsigned int rdlen)
+dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval,
+ dns_ttl_t ttl, const unsigned char *rdatap,
+ unsigned int rdlen)
{
dns_rdatalist_t *rdatalist;
dns_rdata_t *rdata;
@@ -338,7 +340,6 @@ dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval, dns_ttl_t ttl
return (result);
}
-
isc_result_t
dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
const char *data)
@@ -737,6 +738,8 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
char namestr[DNS_NAME_MAXTEXT + 1];
isc_boolean_t isorigin;
dns_sdbimplementation_t *imp;
+ dns_name_t relname;
+ unsigned int labels;
REQUIRE(VALID_SDB(sdb));
REQUIRE(create == ISC_FALSE);
@@ -747,33 +750,46 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
imp = sdb->implementation;
- isc_buffer_init(&b, namestr, sizeof(namestr));
- if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
- dns_name_t relname;
- unsigned int labels;
+ isorigin = dns_name_equal(name, &sdb->common.origin);
- labels = dns_name_countlabels(name) -
- dns_name_countlabels(&db->origin);
- dns_name_init(&relname, NULL);
- dns_name_getlabelsequence(name, 0, labels, &relname);
- result = dns_name_totext(&relname, ISC_TRUE, &b);
- if (result != ISC_R_SUCCESS)
- return (result);
+ if (imp->methods->lookup2 != NULL) {
+ if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
+ labels = dns_name_countlabels(name) -
+ dns_name_countlabels(&db->origin);
+ dns_name_init(&relname, NULL);
+ dns_name_getlabelsequence(name, 0, labels, &relname);
+ name = &relname;
+ }
} else {
- result = dns_name_totext(name, ISC_TRUE, &b);
- if (result != ISC_R_SUCCESS)
- return (result);
+ isc_buffer_init(&b, namestr, sizeof(namestr));
+ if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
+
+ labels = dns_name_countlabels(name) -
+ dns_name_countlabels(&db->origin);
+ dns_name_init(&relname, NULL);
+ dns_name_getlabelsequence(name, 0, labels, &relname);
+ result = dns_name_totext(&relname, ISC_TRUE, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else {
+ result = dns_name_totext(name, ISC_TRUE, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ isc_buffer_putuint8(&b, 0);
}
- isc_buffer_putuint8(&b, 0);
result = createnode(sdb, &node);
if (result != ISC_R_SUCCESS)
return (result);
- isorigin = dns_name_equal(name, &sdb->common.origin);
-
MAYBE_LOCK(sdb);
- result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata, node);
+ if (imp->methods->lookup2 != NULL)
+ result = imp->methods->lookup2(&sdb->common.origin, name,
+ sdb->dbdata, node);
+ else
+ result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata,
+ node);
MAYBE_UNLOCK(sdb);
if (result != ISC_R_SUCCESS &&
!(result == ISC_R_NOTFOUND &&
@@ -811,13 +827,13 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
unsigned int nlabels, olabels;
isc_result_t result;
unsigned int i;
+ unsigned int flags;
REQUIRE(VALID_SDB(sdb));
REQUIRE(nodep == NULL || *nodep == NULL);
REQUIRE(version == NULL || version == (void *) &dummy);
UNUSED(options);
- UNUSED(sdb);
if (!dns_name_issubdomain(name, &db->origin))
return (DNS_R_NXDOMAIN);
@@ -834,17 +850,37 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
}
result = DNS_R_NXDOMAIN;
-
- for (i = olabels; i <= nlabels; i++) {
+ flags = sdb->implementation->flags;
+ i = (flags & DNS_SDBFLAG_DNS64) != 0 ? nlabels : olabels;
+ for (; i <= nlabels; i++) {
/*
* Look up the next label.
*/
dns_name_getlabelsequence(name, nlabels - i, i, xname);
result = findnode(db, xname, ISC_FALSE, &node);
- if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_NOTFOUND) {
+ /*
+ * No data at zone apex?
+ */
+ if (i == olabels)
+ return (DNS_R_BADDB);
result = DNS_R_NXDOMAIN;
continue;
}
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * DNS64 zone's don't have DNAME or NS records.
+ */
+ if ((flags & DNS_SDBFLAG_DNS64) != 0)
+ goto skip;
+
+ /*
+ * DNS64 zone's don't have DNAME or NS records.
+ */
+ if ((flags & DNS_SDBFLAG_DNS64) != 0)
+ goto skip;
/*
* Look for a DNAME at the current label, unless this is
@@ -895,6 +931,7 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
continue;
}
+ skip:
/*
* If we're looking for ANY, we're done.
*/
diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c
index bfc8e8b..0112f7e 100644
--- a/lib/dns/tkey.c
+++ b/lib/dns/tkey.c
@@ -485,9 +485,9 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
tkeyout->error = dns_tsigerror_badkey;
tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA */
return (ISC_R_SUCCESS);
- } else if (result == ISC_R_FAILURE)
+ }
+ if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
goto failure;
- ENSURE(result == DNS_R_CONTINUE || result == ISC_R_SUCCESS);
/*
* XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
*/
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 61a8170..22870dc 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -429,6 +429,7 @@ struct dns_zonemgr {
isc_ratelimiter_t * rl;
isc_rwlock_t rwlock;
isc_mutex_t iolock;
+ isc_rwlock_t urlock;
/* Locked by rwlock. */
dns_zonelist_t zones;
@@ -446,7 +447,7 @@ struct dns_zonemgr {
dns_iolist_t high;
dns_iolist_t low;
- /* Locked by rwlock. */
+ /* Locked by urlock. */
/* LRU cache */
struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
};
@@ -1676,12 +1677,16 @@ 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_style_default,
- zone->masterfile, zone->task, dump_done,
- zone, &zone->dctx, zone->masterformat);
- dns_db_closeversion(zone->db, &version, ISC_FALSE);
+ if (zone->db != NULL) {
+ dns_db_currentversion(zone->db, &version);
+ result = dns_master_dumpinc2(zone->mctx, zone->db, version,
+ &dns_master_style_default,
+ zone->masterfile, zone->task,
+ dump_done, zone, &zone->dctx,
+ zone->masterformat);
+ dns_db_closeversion(zone->db, &version, ISC_FALSE);
+ } else
+ result = ISC_R_CANCELED;
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
UNLOCK_ZONE(zone);
if (result != DNS_R_CONTINUE)
@@ -2695,7 +2700,8 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
*/
static void
set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
- isc_stdtime_t now) {
+ isc_stdtime_t now)
+{
const char me[] = "set_refreshkeytimer";
isc_stdtime_t then;
isc_time_t timenow, timethen;
@@ -4443,6 +4449,7 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,
/*
* Everything is ok so attach to the zone.
*/
+ zone->curmaster = 0;
zone->masters = new;
zone->mastersok = newok;
zone->masterkeynames = newname;
@@ -8531,6 +8538,14 @@ zone_unload(dns_zone_t *zone) {
REQUIRE(LOCKED_ZONE(zone));
+ if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
+ !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
+ if (zone->writeio != NULL)
+ zonemgr_cancelio(zone->writeio);
+
+ if (zone->dctx != NULL)
+ dns_dumpctx_cancel(zone->dctx);
+ }
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
zone_detachdb(zone);
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
@@ -9245,6 +9260,8 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
TIME_NOW(&now);
+ LOCK_ZONE(zone);
+
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
zone_debuglog(zone, me, 1, "exiting");
exiting = ISC_TRUE;
@@ -9257,9 +9274,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
if (revent->result != ISC_R_SUCCESS) {
if (revent->result == ISC_R_TIMEDOUT &&
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
- UNLOCK_ZONE(zone);
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"refreshing stub: timeout retrying "
" without EDNS master %s (source %s)",
@@ -9301,9 +9316,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
"refreshing stub: rcode (%.*s) retrying "
"without EDNS master %s (source %s)",
(int)rb.used, rcode, master, source);
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
- UNLOCK_ZONE(zone);
goto same_master;
}
@@ -9325,9 +9338,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
master, source);
goto next_master;
}
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
- UNLOCK_ZONE(zone);
goto same_master;
}
@@ -9382,21 +9393,17 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
dns_db_detach(&stub->db);
- if (zone->masterfile != NULL) {
- dns_zone_dump(zone);
- TIME_NOW(&zone->loadtime);
- }
+ if (zone->masterfile != NULL)
+ zone_needdump(zone, 0);
dns_message_destroy(&msg);
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
isc_interval_set(&i, zone->expire, 0);
DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
zone_settimer(zone, &now);
- UNLOCK_ZONE(zone);
goto free_stub;
next_master:
@@ -9407,7 +9414,6 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
if (msg != NULL)
dns_message_destroy(&msg);
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
/*
* Skip to next failed / untried master.
@@ -9445,25 +9451,23 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
zone_settimer(zone, &now);
- UNLOCK_ZONE(zone);
goto free_stub;
}
}
queue_soa_query(zone);
- UNLOCK_ZONE(zone);
goto free_stub;
same_master:
if (msg != NULL)
dns_message_destroy(&msg);
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
- UNLOCK_ZONE(zone);
ns_query(zone, NULL, stub);
+ UNLOCK_ZONE(zone);
goto done;
free_stub:
+ UNLOCK_ZONE(zone);
stub->magic = 0;
dns_zone_idetach(&stub->zone);
INSIST(stub->db == NULL);
@@ -9494,6 +9498,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
isc_result_t result;
isc_uint32_t serial, oldserial = 0;
unsigned int j;
+ isc_boolean_t do_queue_xfrin = ISC_FALSE;
zone = revent->ev_arg;
INSIST(DNS_ZONE_VALID(zone));
@@ -9502,6 +9507,10 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
ENTER;
+ TIME_NOW(&now);
+
+ LOCK_ZONE(zone);
+
/*
* if timeout log and next master;
*/
@@ -9509,14 +9518,10 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
- TIME_NOW(&now);
-
if (revent->result != ISC_R_SUCCESS) {
if (revent->result == ISC_R_TIMEDOUT &&
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
- UNLOCK_ZONE(zone);
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"refresh: timeout retrying without EDNS "
"master %s (source %s)", master, source);
@@ -9536,10 +9541,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
&zone->sourceaddr,
&now))
{
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone,
DNS_ZONEFLG_SOABEFOREAXFR);
- UNLOCK_ZONE(zone);
goto tcp_transfer;
}
dns_zone_log(zone, ISC_LOG_DEBUG(1),
@@ -9586,9 +9589,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
"refresh: rcode (%.*s) retrying without "
"EDNS master %s (source %s)",
(int)rb.used, rcode, master, source);
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
- UNLOCK_ZONE(zone);
goto same_master;
}
dns_zone_log(zone, ISC_LOG_INFO,
@@ -9614,9 +9615,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
"initiating TCP zone xfer "
"for master %s (source %s)",
master, source);
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
- UNLOCK_ZONE(zone);
goto tcp_transfer;
} else {
INSIST(zone->type == dns_zone_stub);
@@ -9627,9 +9626,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
master, source);
goto next_master;
}
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
- UNLOCK_ZONE(zone);
goto same_master;
}
}
@@ -9690,6 +9687,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
soacnt, master, source);
goto next_master;
}
+
/*
* Extract serial
*/
@@ -9717,7 +9715,9 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
serial = soa.serial;
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
- result = dns_zone_getserial2(zone, &oldserial);
+ result = zone_get_from_db(zone, zone->db, NULL, NULL,
+ &oldserial, NULL, NULL, NULL, NULL,
+ NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
zone_debuglog(zone, me, 1, "serial: new %u, old %u",
serial, oldserial);
@@ -9741,11 +9741,9 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
}
tcp_transfer:
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
- UNLOCK_ZONE(zone);
if (zone->type == dns_zone_slave) {
- queue_xfrin(zone);
+ do_queue_xfrin = ISC_TRUE;
} else {
INSIST(zone->type == dns_zone_stub);
ns_query(zone, rdataset, NULL);
@@ -9767,9 +9765,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
&now);
/* Someone removed the file from underneath us! */
if (result == ISC_R_FILENOTFOUND) {
- LOCK_ZONE(zone);
zone_needdump(zone, DNS_DUMP_DELAY);
- UNLOCK_ZONE(zone);
} else if (result != ISC_R_SUCCESS)
dns_zone_log(zone, ISC_LOG_ERROR,
"refresh: could not set file "
@@ -9799,7 +9795,6 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
if (msg != NULL)
dns_message_destroy(&msg);
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
/*
* Skip to next failed / untried master.
@@ -9841,25 +9836,24 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
}
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
zone_settimer(zone, &now);
- UNLOCK_ZONE(zone);
goto detach;
}
requeue:
queue_soa_query(zone);
- UNLOCK_ZONE(zone);
goto detach;
same_master:
if (msg != NULL)
dns_message_destroy(&msg);
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
queue_soa_query(zone);
- UNLOCK_ZONE(zone);
detach:
+ UNLOCK_ZONE(zone);
+ if (do_queue_xfrin)
+ queue_xfrin(zone);
dns_zone_idetach(&zone);
return;
}
@@ -10217,13 +10211,13 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
isc_uint16_t udpsize = SEND_BUFFER_SIZE;
REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(LOCKED_ZONE(zone));
REQUIRE((soardataset != NULL && stub == NULL) ||
(soardataset == NULL && stub != NULL));
REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
ENTER;
- LOCK_ZONE(zone);
if (stub == NULL) {
stub = isc_mem_get(zone->mctx, sizeof(*stub));
if (stub == NULL)
@@ -10414,10 +10408,9 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
}
if (message != NULL)
dns_message_destroy(&message);
- unlock:
+ unlock:
if (key != NULL)
dns_tsigkey_detach(&key);
- UNLOCK_ZONE(zone);
return;
}
@@ -12597,15 +12590,22 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
zmgr->transfersin = 10;
zmgr->transfersperns = 2;
+ /* Unreachable lock. */
+ result = isc_rwlock_init(&zmgr->urlock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ goto free_rwlock;
+
/* Create a single task for queueing of SOA queries. */
result = isc_task_create(taskmgr, 1, &zmgr->task);
if (result != ISC_R_SUCCESS)
- goto free_rwlock;
+ goto free_urlock;
+
isc_task_setname(zmgr->task, "zmgr", zmgr);
result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
&zmgr->rl);
if (result != ISC_R_SUCCESS)
goto free_task;
+
/* default to 20 refresh queries / notifies per second. */
isc_interval_set(&interval, 0, 1000000000/2);
result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
@@ -12634,6 +12634,8 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_ratelimiter_detach(&zmgr->rl);
free_task:
isc_task_detach(&zmgr->task);
+ free_urlock:
+ isc_rwlock_destroy(&zmgr->urlock);
free_rwlock:
isc_rwlock_destroy(&zmgr->rwlock);
free_mem:
@@ -12814,7 +12816,6 @@ dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
UNLOCK_ZONE(zone);
}
RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
-
}
isc_result_t
@@ -12858,6 +12859,7 @@ zonemgr_free(dns_zonemgr_t *zmgr) {
DESTROYLOCK(&zmgr->iolock);
isc_ratelimiter_detach(&zmgr->rl);
+ isc_rwlock_destroy(&zmgr->urlock);
isc_rwlock_destroy(&zmgr->rwlock);
mctx = zmgr->mctx;
isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
@@ -13270,12 +13272,12 @@ dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
locktype = isc_rwlocktype_read;
- RWLOCK(&zmgr->rwlock, locktype);
+ RWLOCK(&zmgr->urlock, locktype);
for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
if (zmgr->unreachable[i].expire >= seconds &&
isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
- result = isc_rwlock_tryupgrade(&zmgr->rwlock);
+ result = isc_rwlock_tryupgrade(&zmgr->urlock);
if (result == ISC_R_SUCCESS) {
locktype = isc_rwlocktype_write;
zmgr->unreachable[i].last = seconds;
@@ -13283,7 +13285,7 @@ dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
break;
}
}
- RWUNLOCK(&zmgr->rwlock, locktype);
+ RWUNLOCK(&zmgr->urlock, locktype);
return (ISC_TF(i < UNREACH_CHACHE_SIZE));
}
@@ -13304,11 +13306,11 @@ dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
locktype = isc_rwlocktype_read;
- RWLOCK(&zmgr->rwlock, locktype);
+ RWLOCK(&zmgr->urlock, locktype);
for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
- result = isc_rwlock_tryupgrade(&zmgr->rwlock);
+ result = isc_rwlock_tryupgrade(&zmgr->urlock);
if (result == ISC_R_SUCCESS) {
locktype = isc_rwlocktype_write;
zmgr->unreachable[i].expire = 0;
@@ -13321,7 +13323,7 @@ dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
break;
}
}
- RWUNLOCK(&zmgr->rwlock, locktype);
+ RWUNLOCK(&zmgr->urlock, locktype);
}
void
@@ -13334,7 +13336,7 @@ dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
- RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
+ RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
/* Existing entry? */
if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
@@ -13373,7 +13375,7 @@ dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
zmgr->unreachable[oldest].remote = *remote;
zmgr->unreachable[oldest].local = *local;
}
- RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
+ RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
}
void
diff --git a/lib/isc/pthreads/mutex.c b/lib/isc/pthreads/mutex.c
index ba04f16..c7e5795 100644
--- a/lib/isc/pthreads/mutex.c
+++ b/lib/isc/pthreads/mutex.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2008, 2011 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -78,7 +78,7 @@ struct isc_mutexstats {
};
#ifndef ISC_MUTEX_PROFTABLESIZE
-#define ISC_MUTEX_PROFTABLESIZE (16 * 1024)
+#define ISC_MUTEX_PROFTABLESIZE (1024 * 1024)
#endif
static isc_mutexstats_t stats[ISC_MUTEX_PROFTABLESIZE];
static int stats_next = 0;
@@ -200,24 +200,24 @@ isc_mutex_statsprofile(FILE *fp) {
fprintf(fp, "Mutex stats (in us)\n");
for (i = 0; i < stats_next; i++) {
- fprintf(fp, "%-12s %4d: %10u %lu.%06lu %lu.%06lu\n",
+ fprintf(fp, "%-12s %4d: %10u %lu.%06lu %lu.%06lu %5d\n",
stats[i].file, stats[i].line, stats[i].count,
stats[i].locked_total.tv_sec,
stats[i].locked_total.tv_usec,
stats[i].wait_total.tv_sec,
- stats[i].wait_total.tv_usec
- );
+ stats[i].wait_total.tv_usec,
+ i);
for (j = 0; j < ISC_MUTEX_MAX_LOCKERS; j++) {
locker = &stats[i].lockers[j];
if (locker->file == NULL)
continue;
- fprintf(fp, " %-11s %4d: %10u %lu.%06lu %lu.%06lu\n",
+ fprintf(fp, " %-11s %4d: %10u %lu.%06lu %lu.%06lu %5d\n",
locker->file, locker->line, locker->count,
locker->locked_total.tv_sec,
locker->locked_total.tv_usec,
locker->wait_total.tv_sec,
- locker->wait_total.tv_usec
- );
+ locker->wait_total.tv_usec,
+ i);
}
}
}
diff --git a/lib/isccfg/api b/lib/isccfg/api
index 2b2a12d..9f3d38c 100644
--- a/lib/isccfg/api
+++ b/lib/isccfg/api
@@ -4,5 +4,5 @@
# 9.8: 80-89
# 9.9: 90-109
LIBINTERFACE = 82
-LIBREVISION = 1
+LIBREVISION = 2
LIBAGE = 0
diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c
index 1d1f08e..ef20184 100644
--- a/lib/isccfg/parser.c
+++ b/lib/isccfg/parser.c
@@ -2232,16 +2232,30 @@ cfg_parser_warning(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...)
#define MAX_LOG_TOKEN 30 /* How much of a token to quote in log messages. */
+static isc_boolean_t
+have_current_file(cfg_parser_t *pctx) {
+ cfg_listelt_t *elt;
+ if (pctx->open_files == NULL)
+ return (ISC_FALSE);
+
+ elt = ISC_LIST_TAIL(pctx->open_files->value.list);
+ if (elt == NULL)
+ return (ISC_FALSE);
+
+ return (ISC_TRUE);
+}
+
static char *
current_file(cfg_parser_t *pctx) {
static char none[] = "none";
cfg_listelt_t *elt;
cfg_obj_t *fileobj;
- if (pctx->open_files == NULL)
+ if (!have_current_file(pctx))
return (none);
+
elt = ISC_LIST_TAIL(pctx->open_files->value.list);
- if (elt == NULL)
+ if (elt == NULL) /* shouldn't be possible, but... */
return (none);
fileobj = elt->obj;
@@ -2264,8 +2278,10 @@ parser_complain(cfg_parser_t *pctx, isc_boolean_t is_warning,
if (is_warning)
level = ISC_LOG_WARNING;
- snprintf(where, sizeof(where), "%s:%u: ",
- current_file(pctx), pctx->line);
+ where[0] = '\0';
+ if (have_current_file(pctx))
+ snprintf(where, sizeof(where), "%s:%u: ",
+ current_file(pctx), pctx->line);
len = vsnprintf(message, sizeof(message), format, args);
if (len >= sizeof(message))
diff --git a/version b/version
index aa5d40c..0f23b2e 100644
--- a/version
+++ b/version
@@ -5,6 +5,6 @@
#
MAJORVER=9
MINORVER=8
-PATCHVER=2
+PATCHVER=3
RELEASETYPE=
RELEASEVER=
OpenPOWER on IntegriCloud