summaryrefslogtreecommitdiff
path: root/lib/dns
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns')
-rw-r--r--lib/dns/Makefile.in4
-rw-r--r--lib/dns/acl.c3
-rw-r--r--lib/dns/adb.c168
-rw-r--r--lib/dns/api6
-rw-r--r--lib/dns/dispatch.c28
-rw-r--r--lib/dns/dns64.c8
-rw-r--r--lib/dns/dnssec.c9
-rw-r--r--lib/dns/ecdb.c23
-rw-r--r--lib/dns/gen.c19
-rw-r--r--lib/dns/gssapictx.c4
-rw-r--r--lib/dns/include/dns/Makefile.in24
-rw-r--r--lib/dns/include/dns/adb.h46
-rw-r--r--lib/dns/include/dns/dns64.h4
-rw-r--r--lib/dns/include/dns/dnssec.h6
-rw-r--r--lib/dns/include/dns/message.h6
-rw-r--r--lib/dns/include/dns/rbt.h28
-rw-r--r--lib/dns/include/dns/rdataset.h7
-rw-r--r--lib/dns/include/dns/resolver.h39
-rw-r--r--lib/dns/include/dns/view.h4
-rw-r--r--lib/dns/keytable.c7
-rw-r--r--lib/dns/master.c22
-rw-r--r--lib/dns/message.c16
-rw-r--r--lib/dns/name.c15
-rw-r--r--lib/dns/nsec.c2
-rw-r--r--lib/dns/nsec3.c18
-rw-r--r--lib/dns/openssl_link.c5
-rw-r--r--lib/dns/peer.c11
-rw-r--r--lib/dns/rbt.c7
-rw-r--r--lib/dns/rbtdb.c216
-rw-r--r--lib/dns/rcode.c8
-rw-r--r--lib/dns/rdata.c95
-rw-r--r--lib/dns/rdata/generic/caa_257.c370
-rw-r--r--lib/dns/rdata/generic/caa_257.h32
-rw-r--r--lib/dns/rdata/generic/cdnskey_60.c378
-rw-r--r--lib/dns/rdata/generic/cdnskey_60.h32
-rw-r--r--lib/dns/rdata/generic/cds_59.c354
-rw-r--r--lib/dns/rdata/generic/cds_59.h31
-rw-r--r--lib/dns/rdata/generic/gpos_27.c4
-rw-r--r--lib/dns/rdata/generic/hinfo_13.c6
-rw-r--r--lib/dns/rdata/generic/hip_55.c16
-rw-r--r--lib/dns/rdata/generic/isdn_20.c6
-rw-r--r--lib/dns/rdata/generic/naptr_35.c8
-rw-r--r--lib/dns/rdata/generic/nsec3_50.c29
-rw-r--r--lib/dns/rdata/generic/opt_41.c8
-rw-r--r--lib/dns/rdata/generic/spf_99.c2
-rw-r--r--lib/dns/rdata/generic/tkey_249.c4
-rw-r--r--lib/dns/rdata/generic/tlsa_52.c4
-rw-r--r--lib/dns/rdata/generic/tlsa_52.h4
-rw-r--r--lib/dns/rdata/generic/txt_16.c2
-rw-r--r--lib/dns/rdata/generic/uri_256.c25
-rw-r--r--lib/dns/rdata/generic/x25_19.c4
-rw-r--r--lib/dns/rdataslab.c61
-rw-r--r--lib/dns/resolver.c251
-rw-r--r--lib/dns/rootns.c3
-rw-r--r--lib/dns/rpz.c8
-rw-r--r--lib/dns/rrl.c1
-rw-r--r--lib/dns/time.c10
-rw-r--r--lib/dns/tsig.c2
-rw-r--r--lib/dns/validator.c25
-rw-r--r--lib/dns/view.c31
-rw-r--r--lib/dns/zone.c178
61 files changed, 2257 insertions, 490 deletions
diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in
index a3e3e9a4e86a..eec4c9ef0e77 100644
--- a/lib/dns/Makefile.in
+++ b/lib/dns/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 1998-2003 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -142,7 +142,7 @@ installdirs:
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir}
install:: timestamp installdirs
- ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libdns.@A@ ${DESTDIR}${libdir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libdns.@A@ ${DESTDIR}${libdir}
clean distclean::
rm -f libdns.@A@ timestamp
diff --git a/lib/dns/acl.c b/lib/dns/acl.c
index dbc6f9cb4f3a..8d3718a22b27 100644
--- a/lib/dns/acl.c
+++ b/lib/dns/acl.c
@@ -290,6 +290,9 @@ dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
if (newmem == NULL)
return (ISC_R_NOMEMORY);
+ /* Zero. */
+ memset(newmem, 0, newalloc * sizeof(dns_aclelement_t));
+
/* Copy in the original elements */
memmove(newmem, dest->elements,
dest->length * sizeof(dns_aclelement_t));
diff --git a/lib/dns/adb.c b/lib/dns/adb.c
index 10d51bc44143..c75ea59f751f 100644
--- a/lib/dns/adb.c
+++ b/lib/dns/adb.c
@@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: adb.c,v 1.264 2011/12/05 17:10:51 each Exp $ */
-
/*! \file
*
* \note
@@ -157,7 +155,7 @@ struct dns_adb {
unsigned int *entry_refcnt;
isc_event_t cevent;
- isc_boolean_t cevent_sent;
+ isc_boolean_t cevent_out;
isc_boolean_t shutting_down;
isc_eventlist_t whenshutdown;
isc_event_t growentries;
@@ -201,6 +199,7 @@ struct dns_adbfetch {
unsigned int magic;
dns_fetch_t *fetch;
dns_rdataset_t rdataset;
+ unsigned int depth;
};
/*%
@@ -245,6 +244,7 @@ struct dns_adbentry {
isc_sockaddr_t sockaddr;
isc_stdtime_t expires;
+ isc_stdtime_t lastage;
/*%<
* A nonzero 'expires' field indicates that the entry should
* persist until that time. This allows entries found
@@ -300,8 +300,7 @@ static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t,
static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
static void clean_target(dns_adb_t *, dns_name_t *);
-static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
- unsigned int);
+static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int);
static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
isc_stdtime_t);
@@ -309,6 +308,7 @@ static void cancel_fetches_at_name(dns_adbname_t *);
static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
dns_rdatatype_t);
static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
+ unsigned int, isc_counter_t *qc,
dns_rdatatype_t);
static inline void check_exit(dns_adb_t *);
static void destroy(dns_adb_t *);
@@ -321,6 +321,9 @@ static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *);
static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t);
static void water(void *, int);
static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
+static void adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt,
+ unsigned int factor, isc_stdtime_t now);
+static void shutdown_task(isc_task_t *task, isc_event_t *ev);
/*
* MUST NOT overlap DNS_ADBFIND_* flags!
@@ -344,7 +347,7 @@ static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
* Private flag(s) for entries.
* MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0.
*/
-#define ENTRY_IS_DEAD 0x80000000
+#define ENTRY_IS_DEAD 0x00400000
/*
* To the name, address classes are all that really exist. If it has a
@@ -1498,10 +1501,13 @@ check_exit(dns_adb_t *adb) {
* If there aren't any external references either, we're
* done. Send the control event to initiate shutdown.
*/
- INSIST(!adb->cevent_sent); /* Sanity check. */
+ INSIST(!adb->cevent_out); /* Sanity check. */
+ ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
+ DNS_EVENT_ADBCONTROL, shutdown_task, adb,
+ adb, NULL, NULL);
event = &adb->cevent;
isc_task_send(adb->task, &event);
- adb->cevent_sent = ISC_TRUE;
+ adb->cevent_out = ISC_TRUE;
}
}
@@ -1756,6 +1762,7 @@ new_adbentry(dns_adb_t *adb) {
e->flags = 0;
isc_random_get(&r);
e->srtt = (r & 0x1f) + 1;
+ e->lastage = 0;
e->expires = 0;
ISC_LIST_INIT(e->lameinfo);
ISC_LINK_INIT(e, plink);
@@ -2430,10 +2437,9 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb->view = view;
adb->taskmgr = taskmgr;
adb->next_cleanbucket = 0;
- ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
- DNS_EVENT_ADBCONTROL, shutdown_task, adb,
- adb, NULL, NULL);
- adb->cevent_sent = ISC_FALSE;
+ ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent),
+ 0, NULL, 0, NULL, NULL, NULL, NULL, NULL);
+ adb->cevent_out = ISC_FALSE;
adb->shutting_down = ISC_FALSE;
ISC_LIST_INIT(adb->whenshutdown);
@@ -2467,7 +2473,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
"intializing table sizes to %u\n",
nbuckets[11]);
adb->nentries = nbuckets[11];
- adb->nnames= nbuckets[11];
+ adb->nnames = nbuckets[11];
}
@@ -2740,9 +2746,28 @@ dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) {
UNLOCK(&adb->lock);
}
+static void
+shutdown_stage2(isc_task_t *task, isc_event_t *event) {
+ dns_adb_t *adb;
+
+ UNUSED(task);
+
+ adb = event->ev_arg;
+ INSIST(DNS_ADB_VALID(adb));
+
+ LOCK(&adb->lock);
+ INSIST(adb->shutting_down);
+ adb->cevent_out = ISC_FALSE;
+ (void)shutdown_names(adb);
+ (void)shutdown_entries(adb);
+ if (dec_adb_irefcnt(adb))
+ check_exit(adb);
+ UNLOCK(&adb->lock);
+}
+
void
dns_adb_shutdown(dns_adb_t *adb) {
- isc_boolean_t need_check_exit;
+ isc_event_t *event;
/*
* Shutdown 'adb'.
@@ -2753,11 +2778,16 @@ dns_adb_shutdown(dns_adb_t *adb) {
if (!adb->shutting_down) {
adb->shutting_down = ISC_TRUE;
isc_mem_setwater(adb->mctx, water, adb, 0, 0);
- need_check_exit = shutdown_names(adb);
- if (!need_check_exit)
- need_check_exit = shutdown_entries(adb);
- if (need_check_exit)
- check_exit(adb);
+ /*
+ * Isolate shutdown_names and shutdown_entries calls.
+ */
+ inc_adb_irefcnt(adb);
+ ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
+ DNS_EVENT_ADBCONTROL, shutdown_stage2, adb,
+ adb, NULL, NULL);
+ adb->cevent_out = ISC_TRUE;
+ event = &adb->cevent;
+ isc_task_send(adb->task, &event);
}
UNLOCK(&adb->lock);
@@ -2770,6 +2800,19 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
isc_stdtime_t now, dns_name_t *target,
in_port_t port, dns_adbfind_t **findp)
{
+ return (dns_adb_createfind2(adb, task, action, arg, name,
+ qname, qtype, options, now,
+ target, port, 0, NULL, findp));
+}
+
+isc_result_t
+dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
+ void *arg, dns_name_t *name, dns_name_t *qname,
+ dns_rdatatype_t qtype, unsigned int options,
+ isc_stdtime_t now, dns_name_t *target,
+ in_port_t port, unsigned int depth, isc_counter_t *qc,
+ dns_adbfind_t **findp)
+{
dns_adbfind_t *find;
dns_adbname_t *adbname;
int bucket;
@@ -3000,7 +3043,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
* Start V4.
*/
if (WANT_INET(wanted_fetches) &&
- fetch_name(adbname, start_at_zone,
+ fetch_name(adbname, start_at_zone, depth, qc,
dns_rdatatype_a) == ISC_R_SUCCESS) {
DP(DEF_LEVEL,
"dns_adb_createfind: started A fetch for name %p",
@@ -3011,7 +3054,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
* Start V6.
*/
if (WANT_INET6(wanted_fetches) &&
- fetch_name(adbname, start_at_zone,
+ fetch_name(adbname, start_at_zone, depth, qc,
dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
DP(DEF_LEVEL,
"dns_adb_createfind: "
@@ -3754,6 +3797,12 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s",
buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
dns_result_totext(dev->result));
+ /*
+ * Don't record a failure unless this is the initial
+ * fetch of a chain.
+ */
+ if (fetch->depth > 1)
+ goto out;
/* XXXMLG Don't pound on bad servers. */
if (address_type == DNS_ADBFIND_INET) {
name->expire_v4 = ISC_MIN(name->expire_v4, now + 300);
@@ -3791,9 +3840,8 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
}
static isc_result_t
-fetch_name(dns_adbname_t *adbname,
- isc_boolean_t start_at_zone,
- dns_rdatatype_t type)
+fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone,
+ unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type)
{
isc_result_t result;
dns_adbfetch_t *fetch = NULL;
@@ -3838,12 +3886,14 @@ fetch_name(dns_adbname_t *adbname,
result = ISC_R_NOMEMORY;
goto cleanup;
}
-
- result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
- type, name, nameservers, NULL,
- options, adb->task, fetch_callback,
- adbname, &fetch->rdataset, NULL,
- &fetch->fetch);
+ fetch->depth = depth;
+
+ result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name,
+ type, name, nameservers, NULL,
+ NULL, 0, options, depth, qc,
+ adb->task, fetch_callback, adbname,
+ &fetch->rdataset, NULL,
+ &fetch->fetch);
if (result != ISC_R_SUCCESS)
goto cleanup;
@@ -3912,8 +3962,7 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
unsigned int rtt, unsigned int factor)
{
int bucket;
- unsigned int new_srtt;
- isc_stdtime_t now;
+ isc_stdtime_t now = 0;
REQUIRE(DNS_ADB_VALID(adb));
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
@@ -3922,21 +3971,53 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
bucket = addr->entry->lock_bucket;
LOCK(&adb->entrylocks[bucket]);
- if (factor == DNS_ADB_RTTADJAGE)
- new_srtt = addr->entry->srtt * 98 / 100;
- else
+ if (addr->entry->expires == 0 || factor == DNS_ADB_RTTADJAGE)
+ isc_stdtime_get(&now);
+ adjustsrtt(addr, rtt, factor, now);
+
+ UNLOCK(&adb->entrylocks[bucket]);
+}
+
+void
+dns_adb_agesrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now) {
+ int bucket;
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(DNS_ADBADDRINFO_VALID(addr));
+
+ bucket = addr->entry->lock_bucket;
+ LOCK(&adb->entrylocks[bucket]);
+
+ adjustsrtt(addr, 0, DNS_ADB_RTTADJAGE, now);
+
+ UNLOCK(&adb->entrylocks[bucket]);
+}
+
+static void
+adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor,
+ isc_stdtime_t now)
+{
+ isc_uint64_t new_srtt;
+
+ if (factor == DNS_ADB_RTTADJAGE) {
+ if (addr->entry->lastage != now) {
+ new_srtt = addr->entry->srtt;
+ new_srtt <<= 9;
+ new_srtt -= addr->entry->srtt;
+ new_srtt >>= 9;
+ addr->entry->lastage = now;
+ } else
+ new_srtt = addr->entry->srtt;
+ } else
new_srtt = (addr->entry->srtt / 10 * factor)
+ (rtt / 10 * (10 - factor));
- addr->entry->srtt = new_srtt;
- addr->srtt = new_srtt;
+ new_srtt &= 0xffffffff;
+ addr->entry->srtt = (unsigned int) new_srtt;
+ addr->srtt = (unsigned int) new_srtt;
- if (addr->entry->expires == 0) {
- isc_stdtime_get(&now);
+ if (addr->entry->expires == 0)
addr->entry->expires = now + ADB_ENTRY_WINDOW;
- }
-
- UNLOCK(&adb->entrylocks[bucket]);
}
void
@@ -3949,6 +4030,9 @@ dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
REQUIRE(DNS_ADB_VALID(adb));
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
+ REQUIRE((bits & ENTRY_IS_DEAD) == 0);
+ REQUIRE((mask & ENTRY_IS_DEAD) == 0);
+
bucket = addr->entry->lock_bucket;
LOCK(&adb->entrylocks[bucket]);
diff --git a/lib/dns/api b/lib/dns/api
index cc5437d0be7b..b11beb8343db 100644
--- a/lib/dns/api
+++ b/lib/dns/api
@@ -4,6 +4,6 @@
# 9.8: 80-89, 120-129
# 9.9: 90-109
# 9.9-sub: 130-139
-LIBINTERFACE = 102
-LIBREVISION = 2
-LIBAGE = 2
+LIBINTERFACE = 105
+LIBREVISION = 0
+LIBAGE = 1
diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c
index 7af8e644b197..129895431ddf 100644
--- a/lib/dns/dispatch.c
+++ b/lib/dns/dispatch.c
@@ -819,14 +819,19 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
portentry, link);
isc_mempool_put(disp->portpool, portentry);
}
- UNLOCK(&qid->lock);
+ /*
+ * Set '*portentryp' to NULL inside the lock so that
+ * dispsock->portentry does not change in socket_search.
+ */
*portentryp = NULL;
+
+ UNLOCK(&qid->lock);
}
/*%
* Find a dispsocket for socket address 'dest', and port number 'port'.
- * Return NULL if no such entry exists.
+ * Return NULL if no such entry exists. Requires qid->lock to be held.
*/
static dispsocket_t *
socket_search(dns_qid_t *qid, isc_sockaddr_t *dest, in_port_t port,
@@ -1322,8 +1327,8 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) {
} else {
free_buffer(disp, ev->region.base, ev->region.length);
- UNLOCK(&disp->lock);
isc_event_free(&ev_in);
+ UNLOCK(&disp->lock);
return;
}
} else if (ev->result != ISC_R_SUCCESS) {
@@ -1334,8 +1339,8 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) {
"odd socket result in udp_recv(): %s",
isc_result_totext(ev->result));
- UNLOCK(&disp->lock);
isc_event_free(&ev_in);
+ UNLOCK(&disp->lock);
return;
}
@@ -1510,9 +1515,8 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) {
*/
deactivate_dispsocket(disp, dispsock);
}
- UNLOCK(&disp->lock);
-
isc_event_free(&ev_in);
+ UNLOCK(&disp->lock);
}
/*
@@ -1694,9 +1698,8 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
restart:
(void)startrecv(disp, NULL);
- UNLOCK(&disp->lock);
-
isc_event_free(&ev_in);
+ UNLOCK(&disp->lock);
}
/*
@@ -2286,9 +2289,12 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr,
/* Create or adjust socket pool */
if (mgr->spool != NULL) {
- if (maxrequests < DNS_DISPATCH_POOLSOCKS * 2)
- isc_mempool_setmaxalloc(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2);
- isc_mempool_setfreemax(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2);
+ if (maxrequests < DNS_DISPATCH_POOLSOCKS * 2) {
+ isc_mempool_setmaxalloc(mgr->spool,
+ DNS_DISPATCH_POOLSOCKS * 2);
+ isc_mempool_setfreemax(mgr->spool,
+ DNS_DISPATCH_POOLSOCKS * 2);
+ }
UNLOCK(&mgr->buffer_lock);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/dns64.c b/lib/dns/dns64.c
index 7d47c66933b5..9bc3cd8266df 100644
--- a/lib/dns/dns64.c
+++ b/lib/dns/dns64.c
@@ -63,7 +63,7 @@ dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix,
unsigned int nbytes = 16;
REQUIRE(prefix != NULL && prefix->family == AF_INET6);
- /* Legal prefix lengths from draft-ietf-behave-address-format-04. */
+ /* Legal prefix lengths from rfc6052.txt. */
REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 ||
prefixlen == 56 || prefixlen == 64 || prefixlen == 96);
REQUIRE(isc_netaddr_prefixok(prefix, prefixlen) == ISC_R_SUCCESS);
@@ -73,7 +73,7 @@ dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix,
static const unsigned char zeros[16];
REQUIRE(prefix->family == AF_INET6);
nbytes = prefixlen / 8 + 4;
- /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */
+ /* Bits 64-71 are zeros. rfc6052.txt */
if (prefixlen >= 32 && prefixlen <= 64)
nbytes++;
REQUIRE(memcmp(suffix->type.in6.s6_addr, zeros, nbytes) == 0);
@@ -169,13 +169,13 @@ dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
INSIST(nbytes <= 12);
/* Copy prefix. */
memmove(aaaa, dns64->bits, nbytes);
- /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */
+ /* Bits 64-71 are zeros. rfc6052.txt */
if (nbytes == 8)
aaaa[nbytes++] = 0;
/* Copy mapped address. */
for (i = 0; i < 4U; i++) {
aaaa[nbytes++] = a[i];
- /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */
+ /* Bits 64-71 are zeros. rfc6052.txt */
if (nbytes == 8)
aaaa[nbytes++] = 0;
}
diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c
index d7addc681430..6a749ea56b32 100644
--- a/lib/dns/dnssec.c
+++ b/lib/dns/dnssec.c
@@ -1247,7 +1247,10 @@ get_hints(dns_dnsseckey_t *key, isc_stdtime_t now) {
/* Metadata says activate (so we must also publish) */
if (actset && active <= now) {
key->hint_sign = ISC_TRUE;
- key->hint_publish = ISC_TRUE;
+
+ /* Only publish if publish time has already passed. */
+ if (pubset && publish <= now)
+ key->hint_publish = ISC_TRUE;
}
/*
@@ -1522,7 +1525,7 @@ dns_dnssec_keylistfromrdataset(dns_name_t *origin,
const char *directory, isc_mem_t *mctx,
dns_rdataset_t *keyset, dns_rdataset_t *keysigs,
dns_rdataset_t *soasigs, isc_boolean_t savekeys,
- isc_boolean_t public,
+ isc_boolean_t publickey,
dns_dnsseckeylist_t *keylist)
{
dns_rdataset_t keys;
@@ -1551,7 +1554,7 @@ dns_dnssec_keylistfromrdataset(dns_name_t *origin,
if (!dns_name_equal(origin, dst_key_name(pubkey)))
goto skip;
- if (public) {
+ if (publickey) {
RETERR(addkey(keylist, &pubkey, savekeys, mctx));
goto skip;
}
diff --git a/lib/dns/ecdb.c b/lib/dns/ecdb.c
index 8b3f7740081b..22cd810a773c 100644
--- a/lib/dns/ecdb.c
+++ b/lib/dns/ecdb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2011, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009-2011, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,8 +14,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ecdb.c,v 1.10 2011/12/20 00:06:53 marka Exp $ */
-
#include "config.h"
#include <isc/result.h>
@@ -772,19 +770,24 @@ rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
static void
rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
- ecdb_rdatasetiter_t *ecdbiterator;
isc_mem_t *mctx;
+ union {
+ dns_rdatasetiter_t *rdatasetiterator;
+ ecdb_rdatasetiter_t *ecdbiterator;
+ } u;
REQUIRE(iteratorp != NULL);
- ecdbiterator = (ecdb_rdatasetiter_t *)*iteratorp;
- REQUIRE(DNS_RDATASETITER_VALID(&ecdbiterator->common));
+ REQUIRE(DNS_RDATASETITER_VALID(*iteratorp));
- mctx = ecdbiterator->common.db->mctx;
+ u.rdatasetiterator = *iteratorp;
- ecdbiterator->common.magic = 0;
+ mctx = u.ecdbiterator->common.db->mctx;
+ u.ecdbiterator->common.magic = 0;
- dns_db_detachnode(ecdbiterator->common.db, &ecdbiterator->common.node);
- isc_mem_put(mctx, ecdbiterator, sizeof(ecdb_rdatasetiter_t));
+ dns_db_detachnode(u.ecdbiterator->common.db,
+ &u.ecdbiterator->common.node);
+ isc_mem_put(mctx, u.ecdbiterator,
+ sizeof(ecdb_rdatasetiter_t));
*iteratorp = NULL;
}
diff --git a/lib/dns/gen.c b/lib/dns/gen.c
index b934c9990fb3..ff41de6d624a 100644
--- a/lib/dns/gen.c
+++ b/lib/dns/gen.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009, 2012, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2012-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -331,15 +331,20 @@ insert_into_typenames(int type, const char *typename, const char *attr) {
exit(1);
}
+ /* XXXMUKS: This is redundant due to the INSIST above. */
if (strlen(typename) > sizeof(ttn->typename) - 1) {
fprintf(stderr, "Error: type name %s is too long\n",
typename);
exit(1);
}
+
strncpy(ttn->typename, typename, sizeof(ttn->typename));
- ttn->type = type;
+ ttn->typename[sizeof(ttn->typename) - 1] = '\0';
strncpy(ttn->macroname, ttn->typename, sizeof(ttn->macroname));
+ ttn->macroname[sizeof(ttn->macroname) - 1] = '\0';
+
+ ttn->type = type;
c = strlen(ttn->macroname);
while (c > 0) {
if (ttn->macroname[c - 1] == '-')
@@ -365,7 +370,10 @@ insert_into_typenames(int type, const char *typename, const char *attr) {
attr, typename);
exit(1);
}
+
strncpy(ttn->attr, attr, sizeof(ttn->attr));
+ ttn->attr[sizeof(ttn->attr) - 1] = '\0';
+
ttn->sorted = 0;
if (maxtype < type)
maxtype = type;
@@ -394,11 +402,17 @@ add(int rdclass, const char *classname, int type, const char *typename,
newtt->next = NULL;
newtt->rdclass = rdclass;
newtt->type = type;
+
strncpy(newtt->classname, classname, sizeof(newtt->classname));
+ newtt->classname[sizeof(newtt->classname) - 1] = '\0';
+
strncpy(newtt->typename, typename, sizeof(newtt->typename));
+ newtt->typename[sizeof(newtt->typename) - 1] = '\0';
+
if (strncmp(dirname, "./", 2) == 0)
dirname += 2;
strncpy(newtt->dirname, dirname, sizeof(newtt->dirname));
+ newtt->dirname[sizeof(newtt->dirname) - 1] = '\0';
tt = types;
oldtt = NULL;
@@ -437,6 +451,7 @@ add(int rdclass, const char *classname, int type, const char *typename,
}
newcc->rdclass = rdclass;
strncpy(newcc->classname, classname, sizeof(newcc->classname));
+ newcc->classname[sizeof(newcc->classname) - 1] = '\0';
cc = classes;
oldcc = NULL;
diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c
index d4209d378a76..f28c07aba436 100644
--- a/lib/dns/gssapictx.c
+++ b/lib/dns/gssapictx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -233,7 +233,7 @@ check_config(const char *gss_name) {
krb5_free_context(krb5_ctx);
return;
}
- p = strchr(gss_name, '/');
+ p = strchr(gss_name, '@');
if (p == NULL) {
gss_log(ISC_LOG_ERROR, "badly formatted "
"tkey-gssapi-credentials (%s)", gss_name);
diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in
index 6ff682f70d37..640a63e2c8e7 100644
--- a/lib/dns/include/dns/Makefile.in
+++ b/lib/dns/include/dns/Makefile.in
@@ -21,18 +21,22 @@ top_srcdir = @top_srcdir@
@BIND9_VERSION@
-HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.h \
+HEADERS = acache.h acl.h adb.h bit.h byaddr.h cache.h callbacks.h cert.h \
client.h clientinfo.h compress.h \
db.h dbiterator.h dbtable.h diff.h dispatch.h \
- dlz.h dnssec.h ds.h events.h fixedname.h iptable.h journal.h \
- keyflags.h keytable.h keyvalues.h lib.h log.h \
- master.h masterdump.h message.h name.h ncache.h nsec.h \
- peer.h portlist.h private.h rbt.h rcode.h \
- rdata.h rdataclass.h rdatalist.h rdataset.h rdatasetiter.h \
- rdataslab.h rdatatype.h request.h resolver.h result.h \
- rootns.h rpz.h sdb.h sdlz.h secalg.h secproto.h soa.h ssu.h \
- tcpmsg.h time.h tkey.h tsec.h tsig.h ttl.h types.h \
- validator.h version.h view.h xfrin.h zone.h zonekey.h zt.h
+ dlz.h dlz_dlopen.h dns64.h dnssec.h ds.h \
+ ecdb.h events.h fixedname.h forward.h iptable.h \
+ journal.h keydata.h keyflags.h keytable.h keyvalues.h \
+ lib.h lookup.h log.h master.h masterdump.h message.h \
+ name.h ncache.h nsec.h nsec3.h opcode.h order.h \
+ peer.h portlist.h private.h \
+ rbt.h rcode.h rdata.h rdataclass.h rdatalist.h \
+ rdataset.h rdatasetiter.h rdataslab.h rdatatype.h request.h \
+ resolver.h result.h rootns.h rpz.h rriterator.h rrl.h \
+ sdb.h sdlz.h secalg.h secproto.h soa.h ssu.h stats.h \
+ tcpmsg.h time.h timer.h tkey.h tsec.h tsig.h ttl.h types.h \
+ update.h validator.h version.h view.h xfrin.h \
+ zone.h zonekey.h zt.h
GENHEADERS = enumclass.h enumtype.h rdatastruct.h
diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h
index a5a312406aff..8222bd211006 100644
--- a/lib/dns/include/dns/adb.h
+++ b/lib/dns/include/dns/adb.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2011, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2011, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -334,6 +334,13 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
dns_rdatatype_t qtype, unsigned int options,
isc_stdtime_t now, dns_name_t *target,
in_port_t port, dns_adbfind_t **find);
+isc_result_t
+dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
+ void *arg, dns_name_t *name, dns_name_t *qname,
+ dns_rdatatype_t qtype, unsigned int options,
+ isc_stdtime_t now, dns_name_t *target, in_port_t port,
+ unsigned int depth, isc_counter_t *qc,
+ dns_adbfind_t **find);
/*%<
* Main interface for clients. The adb will look up the name given in
* "name" and will build up a list of found addresses, and perhaps start
@@ -510,7 +517,12 @@ dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *qname,
*/
/*
- * A reasonable default for RTT adjustments
+ * Reasonable defaults for RTT adjustments
+ *
+ * (Note: these values function both as scaling factors and as
+ * indicators of the type of RTT adjustment operation taking place.
+ * Adjusting the scaling factors is fine, as long as they all remain
+ * unique values.)
*/
#define DNS_ADB_RTTADJDEFAULT 7 /*%< default scale */
#define DNS_ADB_RTTADJREPLACE 0 /*%< replace with our rtt */
@@ -521,18 +533,6 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
unsigned int rtt, unsigned int factor);
/*%<
* Mix the round trip time into the existing smoothed rtt.
-
- * The formula used
- * (where srtt is the existing rtt value, and rtt and factor are arguments to
- * this function):
- *
- *\code
- * new_srtt = (old_srtt / 10 * factor) + (rtt / 10 * (10 - factor));
- *\endcode
- *
- * XXXRTH Do we want to publish the formula? What if we want to change how
- * this works later on? Recommend/require that the units are
- * microseconds?
*
* Requires:
*
@@ -549,6 +549,24 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
*/
void
+dns_adb_agesrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now);
+/*
+ * dns_adb_agesrtt is equivalent to dns_adb_adjustsrtt with factor
+ * equal to DNS_ADB_RTTADJAGE and the current time passed in.
+ *
+ * Requires:
+ *
+ *\li adb be valid.
+ *
+ *\li addr be valid.
+ *
+ * Note:
+ *
+ *\li The srtt in addr will be updated to reflect the new global
+ * srtt value. This may include changes made by others.
+ */
+
+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/dns64.h b/lib/dns/include/dns/dns64.h
index eb8f8d6436a6..4d0e80158541 100644
--- a/lib/dns/include/dns/dns64.h
+++ b/lib/dns/include/dns/dns64.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2010, 2014 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
@@ -84,7 +84,7 @@ dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix,
* zero.
* 'client' to be NULL or a valid acl.
* 'mapped' to be NULL or a valid acl.
- * 'exculded' to be NULL or a valid acl.
+ * 'excluded' to be NULL or a valid acl.
*
* Returns:
* ISC_R_SUCCESS
diff --git a/lib/dns/include/dns/dnssec.h b/lib/dns/include/dns/dnssec.h
index 7202d99b5da9..936454fc465e 100644
--- a/lib/dns/include/dns/dnssec.h
+++ b/lib/dns/include/dns/dnssec.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009-2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -314,11 +314,11 @@ dns_dnssec_keylistfromrdataset(dns_name_t *origin,
const char *directory, isc_mem_t *mctx,
dns_rdataset_t *keyset, dns_rdataset_t *keysigs,
dns_rdataset_t *soasigs, isc_boolean_t savekeys,
- isc_boolean_t public,
+ isc_boolean_t publickey,
dns_dnsseckeylist_t *keylist);
/*%<
* Append the contents of a DNSKEY rdataset 'keyset' to 'keylist'.
- * Omit duplicates. If 'public' is ISC_FALSE, search 'directory' for
+ * Omit duplicates. If 'publickey' is ISC_FALSE, search 'directory' for
* matching key files, and load the private keys that go with
* the public ones. If 'savekeys' is ISC_TRUE, mark the keys so
* they will not be deleted or inactivated regardless of metadata.
diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h
index 6b2f39fc9583..c678238d2224 100644
--- a/lib/dns/include/dns/message.h
+++ b/lib/dns/include/dns/message.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010, 2012, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010, 2012-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -106,6 +106,10 @@
/*%< EDNS0 extended OPT codes */
#define DNS_OPT_NSID 0x0003 /*%< NSID opt code */
#define DNS_OPT_CLIENT_SUBNET 0x0008 /*%< client subnet opt code */
+#define DNS_OPT_EXPIRE 0x0009 /*%< EXPIRE opt code */
+
+/*%< The number of EDNS options we know about. */
+#define DNS_EDNSOPTIONS 3
#define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD|DNS_MESSAGEFLAG_CD)
#define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)
diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h
index 3e9dc886576f..8b382b5ed6be 100644
--- a/lib/dns/include/dns/rbt.h
+++ b/lib/dns/include/dns/rbt.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -914,6 +914,31 @@ dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name);
#define dns_rbtnode_refinit(node, n) ((node)->references = (n))
#define dns_rbtnode_refdestroy(node) REQUIRE((node)->references == 0)
#define dns_rbtnode_refcurrent(node) ((node)->references)
+
+#if (__STDC_VERSION__ + 0) >= 199901L || defined __GNUC__
+static inline void
+dns_rbtnode_refincrement0(dns_rbtnode_t *node, unsigned int *refs) {
+ node->references++;
+ if (refs != NULL)
+ *refs = node->references;
+}
+
+static inline void
+dns_rbtnode_refincrement(dns_rbtnode_t *node, unsigned int *refs) {
+ REQUIRE(node->references > 0);
+ node->references++;
+ if (refs != NULL)
+ *refs = node->references;
+}
+
+static inline void
+dns_rbtnode_refdecrement(dns_rbtnode_t *node, unsigned int *refs) {
+ REQUIRE(node->references > 0);
+ node->references--;
+ if (refs != NULL)
+ *refs = node->references;
+}
+#else
#define dns_rbtnode_refincrement0(node, refs) \
do { \
unsigned int *_tmp = (unsigned int *)(refs); \
@@ -935,6 +960,7 @@ dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name);
if ((refs) != NULL) \
(*refs) = (node)->references; \
} while (0)
+#endif
#endif /* DNS_RBT_USEISCREFCOUNT */
ISC_LANG_ENDDECLS
diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h
index 31bcd15f1424..c266d14655ee 100644
--- a/lib/dns/include/dns/rdataset.h
+++ b/lib/dns/include/dns/rdataset.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2012, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -199,7 +199,8 @@ struct dns_rdataset {
#define DNS_RDATASETATTR_NXDOMAIN 0x00002000
#define DNS_RDATASETATTR_NOQNAME 0x00004000
#define DNS_RDATASETATTR_CHECKNAMES 0x00008000 /*%< Used by resolver. */
-#define DNS_RDATASETATTR_REQUIREDGLUE 0x00010000
+#define DNS_RDATASETATTR_REQUIRED 0x00010000
+#define DNS_RDATASETATTR_REQUIREDGLUE DNS_RDATASETATTR_REQUIRED
#define DNS_RDATASETATTR_LOADORDER 0x00020000
#define DNS_RDATASETATTR_RESIGN 0x00040000
#define DNS_RDATASETATTR_CLOSEST 0x00080000
@@ -673,7 +674,7 @@ dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
const char *
dns_trust_totext(dns_trust_t trust);
-/*
+/*%<
* Display trust in textual form.
*/
diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h
index 095269ea2dd2..a533f4ed2b24 100644
--- a/lib/dns/include/dns/resolver.h
+++ b/lib/dns/include/dns/resolver.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2012, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -97,6 +97,7 @@ typedef struct dns_fetchevent {
UDP buffer. */
#define DNS_FETCHOPT_WANTNSID 0x80 /*%< Request NSID */
+/* Reserved in use by adb.c 0x00400000 */
#define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000
#define DNS_FETCHOPT_EDNSVERSIONMASK 0xff000000
#define DNS_FETCHOPT_EDNSVERSIONSHIFT 24
@@ -274,6 +275,18 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset,
dns_fetch_t **fetchp);
+isc_result_t
+dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_name_t *domain, dns_rdataset_t *nameservers,
+ dns_forwarders_t *forwarders,
+ isc_sockaddr_t *client, isc_uint16_t id,
+ unsigned int options, unsigned int depth,
+ isc_counter_t *qc, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset,
+ dns_fetch_t **fetchp);
/*%<
* Recurse to answer a question.
*
@@ -575,6 +588,30 @@ dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp);
* \li resolver to be valid.
*/
+void
+dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth);
+unsigned int
+dns_resolver_getmaxdepth(dns_resolver_t *resolver);
+/*%
+ * Get and set how many NS indirections will be followed when looking for
+ * nameserver addresses.
+ *
+ * Requires:
+ * \li resolver to be valid.
+ */
+
+void
+dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries);
+unsigned int
+dns_resolver_getmaxqueries(dns_resolver_t *resolver);
+/*%
+ * Get and set how many iterative queries will be allowed before
+ * terminating a recursive query.
+ *
+ * Requires:
+ * \li resolver to be valid.
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_RESOLVER_H */
diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h
index 704e5fe3e999..b9d6084f351c 100644
--- a/lib/dns/include/dns/view.h
+++ b/lib/dns/include/dns/view.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -140,6 +140,7 @@ struct dns_view {
dns_acl_t * updateacl;
dns_acl_t * upfwdacl;
dns_acl_t * denyansweracl;
+ dns_acl_t * nocasecompress;
dns_rbt_t * answeracl_exclude;
dns_rbt_t * denyanswernames;
dns_rbt_t * answernames_exclude;
@@ -711,6 +712,7 @@ dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name, isc_boolean_t allc
* Returns:
*\li #ISC_R_SUCCESS A matching zone was found.
*\li #ISC_R_NOTFOUND No matching zone was found.
+ *\li #ISC_R_MULTIPLE Multiple zones with the same name were found.
*/
isc_result_t
diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c
index c49847f326ad..56fefcd2c122 100644
--- a/lib/dns/keytable.c
+++ b/lib/dns/keytable.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009, 2010, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2010, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -174,6 +174,7 @@ insert(dns_keytable_t *keytable, isc_boolean_t managed,
for (k = node->data; k != NULL; k = k->next) {
if (k->key == NULL) {
k->key = *keyp;
+ *keyp = NULL; /* transfer ownership */
break;
}
if (dst_key_compare(k->key, *keyp) == ISC_TRUE)
@@ -182,7 +183,7 @@ insert(dns_keytable_t *keytable, isc_boolean_t managed,
if (k == NULL)
result = ISC_R_SUCCESS;
- else
+ else if (*keyp != NULL)
dst_key_free(keyp);
}
@@ -575,6 +576,8 @@ dns_keytable_dump(dns_keytable_t *keytable, FILE *fp)
dns_rbtnodechain_current(&chain, NULL, NULL, &node);
for (knode = node->data; knode != NULL; knode = knode->next) {
+ if (knode->key == NULL)
+ continue;
dst_key_format(knode->key, pbuf, sizeof(pbuf));
fprintf(fp, "%s ; %s\n", pbuf,
knode->managed ? "managed" : "trusted");
diff --git a/lib/dns/master.c b/lib/dns/master.c
index 9e796e6e0ac7..dcea97a0bdd4 100644
--- a/lib/dns/master.c
+++ b/lib/dns/master.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -91,6 +91,8 @@
#define DNS_MASTER_LHS 2048
#define DNS_MASTER_RHS MINTSIZ
+#define CHECKNAMESFAIL(x) (((x) & DNS_MASTER_CHECKNAMESFAIL) != 0)
+
typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
typedef struct dns_incctx dns_incctx_t;
@@ -798,13 +800,12 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
dns_rdatalist_t rdatalist;
dns_rdatatype_t type;
rdatalist_head_t head;
- int n;
int target_size = MINTSIZ; /* only one rdata at a time */
isc_buffer_t buffer;
isc_buffer_t target;
isc_result_t result;
isc_textregion_t r;
- unsigned int start, stop, step, i;
+ int i, n, start, stop, step = 0;
dns_incctx_t *ictx;
ictx = lctx->inc;
@@ -822,8 +823,10 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
}
isc_buffer_init(&target, target_mem, target_size);
- n = sscanf(range, "%u-%u/%u", &start, &stop, &step);
- if (n < 2 || stop < start) {
+ n = sscanf(range, "%d-%d/%d", &start, &stop, &step);
+ if ((n < 2) || (start < 0) || (stop < 0) || (step < 0) ||
+ (stop < start))
+ {
(*callbacks->error)(callbacks,
"%s: %s:%lu: invalid range '%s'",
"$GENERATE", source, line, range);
@@ -1759,7 +1762,8 @@ load_text(dns_loadctx_t *lctx) {
dns_name_format(name, namebuf, sizeof(namebuf));
result = DNS_R_BADOWNERNAME;
desc = dns_result_totext(result);
- if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
+ if (CHECKNAMESFAIL(lctx->options) ||
+ type == dns_rdatatype_nsec3) {
(*callbacks->error)(callbacks,
"%s:%lu: %s: %s",
source, line,
@@ -2132,7 +2136,7 @@ load_raw(dns_loadctx_t *lctx) {
isc_result_totext(result));
return (result);
}
- isc_buffer_add(&target, commonlen);
+ isc_buffer_add(&target, (unsigned int)commonlen);
header.format = isc_buffer_getuint32(&target);
if (header.format != dns_masterformat_raw) {
(*callbacks->error)(callbacks,
@@ -2165,7 +2169,7 @@ load_raw(dns_loadctx_t *lctx) {
return (result);
}
- isc_buffer_add(&target, remainder);
+ isc_buffer_add(&target, (unsigned int)remainder);
header.dumptime = isc_buffer_getuint32(&target);
if (header.version == DNS_RAWFORMAT_VERSION) {
header.flags = isc_buffer_getuint32(&target);
@@ -2275,7 +2279,7 @@ load_raw(dns_loadctx_t *lctx) {
rdatalist.covers = isc_buffer_getuint16(&target);
rdatalist.ttl = isc_buffer_getuint32(&target);
rdcount = isc_buffer_getuint32(&target);
- if (rdcount == 0) {
+ if (rdcount == 0 || rdcount > 0xffff) {
result = ISC_R_RANGE;
goto cleanup;
}
diff --git a/lib/dns/message.c b/lib/dns/message.c
index 901c6b6d991d..d76eb4fb26c6 100644
--- a/lib/dns/message.c
+++ b/lib/dns/message.c
@@ -1377,6 +1377,16 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
covers = 0;
/*
+ * Check the ownername of NSEC3 records
+ */
+ if (rdtype == dns_rdatatype_nsec3 &&
+ !dns_rdata_checkowner(name, msg->rdclass, rdtype,
+ ISC_FALSE)) {
+ result = DNS_R_BADOWNERNAME;
+ goto cleanup;
+ }
+
+ /*
* If we are doing a dynamic update or this is a meta-type,
* don't bother searching for a name, just append this one
* to the end of the message.
@@ -3196,7 +3206,8 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
dns_pseudosection_t section,
const dns_master_style_t *style,
dns_messagetextflag_t flags,
- isc_buffer_t *target) {
+ isc_buffer_t *target)
+{
dns_rdataset_t *ps = NULL;
dns_name_t *name = NULL;
isc_result_t result;
@@ -3270,8 +3281,11 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
sprintf(buf, "%02x ", optdata[i]);
ADD_STRING(target, buf);
}
+
for (i = 0; i < optlen; i++) {
ADD_STRING(target, " (");
+ if (!isc_buffer_availablelength(target))
+ return (ISC_R_NOSPACE);
if (isprint(optdata[i]))
isc_buffer_putmem(target,
&optdata[i],
diff --git a/lib/dns/name.c b/lib/dns/name.c
index 9b24ed363804..5207f74b4240 100644
--- a/lib/dns/name.c
+++ b/lib/dns/name.c
@@ -53,7 +53,6 @@ typedef enum {
typedef enum {
fw_start = 0,
fw_ordinary,
- fw_copy,
fw_newcurrent
} fw_state;
@@ -1161,7 +1160,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
count++;
CONVERTTOASCII(c);
if (downcase)
- c = maptolower[(int)c];
+ c = maptolower[c & 0xff];
*ndata++ = c;
nrem--;
nused++;
@@ -1185,7 +1184,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
count++;
CONVERTTOASCII(c);
if (downcase)
- c = maptolower[(int)c];
+ c = maptolower[c & 0xff];
*ndata++ = c;
nrem--;
nused++;
@@ -1200,7 +1199,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
if (!isdigit(c & 0xff))
return (DNS_R_BADESCAPE);
value *= 10;
- value += digitvalue[(int)c];
+ value += digitvalue[c & 0xff];
digits++;
if (digits == 3) {
if (value > 255)
@@ -1252,7 +1251,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
while (n2 > 0) {
c = *label++;
if (downcase)
- c = maptolower[(int)c];
+ c = maptolower[c & 0xff];
*ndata++ = c;
n2--;
}
@@ -1859,7 +1858,6 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
0)
return (DNS_R_DISALLOWED);
new_current = c & 0x3F;
- n = 1;
state = fw_newcurrent;
} else
return (DNS_R_BADLABELTYPE);
@@ -1867,8 +1865,6 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
case fw_ordinary:
if (downcase)
c = maptolower[c];
- /* FALLTHROUGH */
- case fw_copy:
*ndata++ = c;
n--;
if (n == 0)
@@ -1877,9 +1873,6 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
case fw_newcurrent:
new_current *= 256;
new_current += c;
- n--;
- if (n != 0)
- break;
if (new_current >= biggest_pointer)
return (DNS_R_BADPOINTER);
biggest_pointer = new_current;
diff --git a/lib/dns/nsec.c b/lib/dns/nsec.c
index 5d1197d093b0..6183ef281c02 100644
--- a/lib/dns/nsec.c
+++ b/lib/dns/nsec.c
@@ -436,7 +436,7 @@ dns_nsec_noexistnodata(dns_rdatatype_t type, dns_name_t *name,
nlabels, &common);
}
result = dns_name_concatenate(dns_wildcardname, &common,
- wild, NULL);
+ wild, NULL);
if (result != ISC_R_SUCCESS) {
dns_rdata_freestruct(&nsec);
(*logit)(arg, ISC_LOG_DEBUG(3),
diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c
index 3724118cb3fe..ef43c35d27bb 100644
--- a/lib/dns/nsec3.c
+++ b/lib/dns/nsec3.c
@@ -253,11 +253,11 @@ dns_nsec3_hashname(dns_fixedname_t *result,
if (hash_length != NULL)
*hash_length = len;
- /* convert the hash to base32hex */
+ /* convert the hash to base32hex non-padded */
region.base = rethash;
region.length = (unsigned int)len;
isc_buffer_init(&namebuffer, nametext, sizeof nametext);
- isc_base32hex_totext(&region, 1, "", &namebuffer);
+ isc_base32hexnp_totext(&region, 1, "", &namebuffer);
/* convert the hex to a domain name */
dns_fixedname_init(result);
@@ -269,7 +269,8 @@ unsigned int
dns_nsec3_hashlength(dns_hash_t hash) {
switch (hash) {
- case dns_hash_sha1: return(ISC_SHA1_DIGESTLENGTH);
+ case dns_hash_sha1:
+ return(ISC_SHA1_DIGESTLENGTH);
}
return (0);
}
@@ -277,7 +278,8 @@ dns_nsec3_hashlength(dns_hash_t hash) {
isc_boolean_t
dns_nsec3_supportedhash(dns_hash_t hash) {
switch (hash) {
- case dns_hash_sha1: return (ISC_TRUE);
+ case dns_hash_sha1:
+ return (ISC_TRUE);
}
return (ISC_FALSE);
}
@@ -565,6 +567,7 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
name, origin, hash, iterations,
salt, salt_length));
+ INSIST(next_length <= sizeof(nexthash));
/*
* Create the node if it doesn't exist and hold
@@ -842,8 +845,8 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
dns_db_detachnode(db, &newnode);
} while (1);
- if (result == ISC_R_NOMORE)
- result = ISC_R_SUCCESS;
+ /* result cannot be ISC_R_NOMORE here */
+ INSIST(result != ISC_R_NOMORE);
failure:
if (dbit != NULL)
@@ -2072,6 +2075,9 @@ dns_nsec3_noexistnodata(dns_rdatatype_t type, dns_name_t* name,
if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0)
(*logit)(arg, ISC_LOG_DEBUG(3),
"NSEC3 indicates optout");
+ else
+ (*logit)(arg, ISC_LOG_DEBUG(3),
+ "NSEC3 indicates secure range");
*optout =
ISC_TF(nsec3.flags & DNS_NSEC3FLAG_OPTOUT);
}
diff --git a/lib/dns/openssl_link.c b/lib/dns/openssl_link.c
index 56465aa00645..a0a2724f41c1 100644
--- a/lib/dns/openssl_link.c
+++ b/lib/dns/openssl_link.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2012, 2014 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -242,8 +242,7 @@ dst__openssl_init(const char *engine) {
}
void
-dst__openssl_destroy() {
-
+dst__openssl_destroy(void) {
/*
* Sequence taken from apps_shutdown() in <apps/apps.h>.
*/
diff --git a/lib/dns/peer.c b/lib/dns/peer.c
index ec9e08cb27b7..b17bbea1328a 100644
--- a/lib/dns/peer.c
+++ b/lib/dns/peer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2012, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -300,10 +300,15 @@ peer_delete(dns_peer_t **peer) {
isc_mem_put(mem, p->key, sizeof(dns_name_t));
}
- if (p->transfer_source != NULL) {
+ if (p->query_source != NULL)
+ isc_mem_put(mem, p->query_source, sizeof(*p->query_source));
+
+ if (p->notify_source != NULL)
+ isc_mem_put(mem, p->notify_source, sizeof(*p->notify_source));
+
+ if (p->transfer_source != NULL)
isc_mem_put(mem, p->transfer_source,
sizeof(*p->transfer_source));
- }
isc_mem_put(mem, p, sizeof(*p));
diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c
index d97fcce28eb9..0e9c5f950569 100644
--- a/lib/dns/rbt.c
+++ b/lib/dns/rbt.c
@@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id$ */
-
/*! \file */
/* Principal Authors: DCL */
@@ -134,7 +132,10 @@ struct dns_rbt {
* of memory concerns, when chains were first implemented).
*/
#define ADD_LEVEL(chain, node) \
- (chain)->levels[(chain)->level_count++] = (node)
+ do { \
+ INSIST((chain)->level_count < DNS_RBT_LEVELBLOCK); \
+ (chain)->levels[(chain)->level_count++] = (node); \
+ } while (0)
/*%
* The following macros directly access normally private name variables.
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index 013bf34a0a09..a8ad8329c73b 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id$ */
-
/*! \file */
/*
@@ -93,6 +91,127 @@ typedef isc_uint64_t rbtdb_serial_t;
#define dns_rbtdb_t dns_rbtdb64_t
#define rdatasetheader_t rdatasetheader64_t
#define rbtdb_version_t rbtdb_version64_t
+
+#define init_count init_count64
+
+#define cache_methods cache_methods64
+#define dbiterator_methods dbiterator_methods64
+#define rdataset_methods rdataset_methods64
+#define rdatasetiter_methods rdatasetiter_methods64
+#define zone_methods zone_methods64
+
+#define acache_callback acache_callback64
+#define acache_cancelentry acache_cancelentry64
+#define activeempty activeempty64
+#define activeemtpynode activeemtpynode64
+#define add32 add64
+#define add_changed add_changed64
+#define add_empty_wildcards add_empty_wildcards64
+#define add_wildcard_magic add_wildcard_magic64
+#define addrdataset addrdataset64
+#define allrdatasets allrdatasets64
+#define attach attach64
+#define attachnode attachnode64
+#define attachversion attachversion64
+#define beginload beginload64
+#define bind_rdataset bind_rdataset64
+#define cache_find cache_find64
+#define cache_findrdataset cache_findrdataset64
+#define cache_findzonecut cache_findzonecut64
+#define cache_zonecut_callback cache_zonecut_callback64
+#define cleanup_dead_nodes cleanup_dead_nodes64
+#define cleanup_dead_nodes_callback cleanup_dead_nodes_callback64
+#define closeversion closeversion64
+#define createiterator createiterator64
+#define currentversion currentversion64
+#define dbiterator_current dbiterator_current64
+#define dbiterator_destroy dbiterator_destroy64
+#define dbiterator_first dbiterator_first64
+#define dbiterator_last dbiterator_last64
+#define dbiterator_next dbiterator_next64
+#define dbiterator_origin dbiterator_origin64
+#define dbiterator_pause dbiterator_pause64
+#define dbiterator_prev dbiterator_prev64
+#define dbiterator_seek dbiterator_seek64
+#define decrement_reference decrement_reference64
+#define delete_callback delete_callback64
+#define delete_node delete_node64
+#define deleterdataset deleterdataset64
+#define detach detach64
+#define detachnode detachnode64
+#define dump dump64
+#define endload endload64
+#define expire_header expire_header64
+#define expirenode expirenode64
+#define find_closest_nsec find_closest_nsec64
+#define find_coveringnsec find_coveringnsec64
+#define find_deepest_zonecut find_deepest_zonecut64
+#define findnode findnode64
+#define findnodeintree findnodeintree64
+#define findnsec3node findnsec3node64
+#define flush_deletions flush_deletions64
+#define free_acachearray free_acachearray64
+#define free_noqname free_noqname64
+#define free_rbtdb free_rbtdb64
+#define free_rbtdb_callback free_rbtdb_callback64
+#define free_rdataset free_rdataset64
+#define getnsec3parameters getnsec3parameters64
+#define getoriginnode getoriginnode64
+#define getrrsetstats getrrsetstats64
+#define getsigningtime getsigningtime64
+#define isdnssec isdnssec64
+#define ispersistent ispersistent64
+#define issecure issecure64
+#define iszonesecure iszonesecure64
+#define loading_addrdataset loading_addrdataset64
+#define loadnode loadnode64
+#define matchparams matchparams64
+#define maybe_free_rbtdb maybe_free_rbtdb64
+#define new_reference new_reference64
+#define newversion newversion64
+#define nodecount nodecount64
+#define overmem overmem64
+#define previous_closest_nsec previous_closest_nsec64
+#define printnode printnode64
+#define prune_tree prune_tree64
+#define rdataset_clone rdataset_clone64
+#define rdataset_count rdataset_count64
+#define rdataset_current rdataset_current64
+#define rdataset_disassociate rdataset_disassociate64
+#define rdataset_expire rdataset_expire64
+#define rdataset_first rdataset_first64
+#define rdataset_getadditional rdataset_getadditional64
+#define rdataset_getclosest rdataset_getclosest64
+#define rdataset_getnoqname rdataset_getnoqname64
+#define rdataset_next rdataset_next64
+#define rdataset_putadditional rdataset_putadditional64
+#define rdataset_setadditional rdataset_setadditional64
+#define rdataset_settrust rdataset_settrust64
+#define rdatasetiter_current rdatasetiter_current64
+#define rdatasetiter_destroy rdatasetiter_destroy64
+#define rdatasetiter_first rdatasetiter_first64
+#define rdatasetiter_next rdatasetiter_next64
+#define reactivate_node reactivate_node64
+#define resign_delete resign_delete64
+#define resign_insert resign_insert64
+#define resign_sooner resign_sooner64
+#define resigned resigned64
+#define rpz_enabled rpz_enabled64
+#define rpz_findips rpz_findips64
+#define set_index set_index64
+#define set_ttl set_ttl64
+#define setsigningtime setsigningtime64
+#define settask settask64
+#define setup_delegation setup_delegation64
+#define subtractrdataset subtractrdataset64
+#define ttl_sooner ttl_sooner64
+#define update_header update_header64
+#define update_rrsetstats update_rrsetstats64
+#define zone_find zone_find64
+#define zone_findrdataset zone_findrdataset64
+#define zone_findzonecut zone_findzonecut64
+#define zone_zonecut_callback zone_zonecut_callback64
+
#else
typedef isc_uint32_t rbtdb_serial_t;
#endif
@@ -537,6 +656,8 @@ static void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
isc_stdtime_t now, isc_boolean_t tree_locked);
static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx,
rdatasetheader_t *newheader);
+static void resign_delete(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,
+ rdatasetheader_t *header);
static void prune_tree(isc_task_t *task, isc_event_t *event);
static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
static void rdataset_expire(dns_rdataset_t *rdataset);
@@ -774,7 +895,7 @@ resign_sooner(void *v1, void *v2) {
rdatasetheader_t *h1 = v1;
rdatasetheader_t *h2 = v2;
- if (h1->resign < h2->resign)
+ if (isc_serial_lt(h1->resign, h2->resign))
return (ISC_TRUE);
return (ISC_FALSE);
}
@@ -2372,8 +2493,18 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
lock = &rbtdb->node_locks[header->node->locknum].lock;
NODE_LOCK(lock, isc_rwlocktype_write);
- if (rollback)
- resign_insert(rbtdb, header->node->locknum, header);
+ if (rollback && !IGNORE(header)) {
+ isc_result_t result;
+ result = resign_insert(rbtdb, header->node->locknum,
+ header);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_ZONE, ISC_LOG_ERROR,
+ "Unable to reinsert header to "
+ "re-signing heap: %s\n",
+ dns_result_totext(result));
+ }
decrement_reference(rbtdb, header->node, least_serial,
isc_rwlocktype_write, isc_rwlocktype_none,
ISC_FALSE);
@@ -5874,10 +6005,28 @@ resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader) {
return (result);
}
+static void
+resign_delete(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,
+ rdatasetheader_t *header)
+{
+ /*
+ * Remove the old header from the heap
+ */
+ if (header != NULL && header->heap_index != 0) {
+ isc_heap_delete(rbtdb->heaps[header->node->locknum],
+ header->heap_index);
+ header->heap_index = 0;
+ if (version != NULL) {
+ new_reference(rbtdb, header->node);
+ ISC_LIST_APPEND(version->resigned_list, header, link);
+ }
+ }
+}
+
static isc_result_t
-add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
- rdatasetheader_t *newheader, unsigned int options, isc_boolean_t loading,
- dns_rdataset_t *addedrdataset, isc_stdtime_t now)
+add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
+ rdatasetheader_t *newheader, unsigned int options, isc_boolean_t loading,
+ dns_rdataset_t *addedrdataset, isc_stdtime_t now)
{
rbtdb_changed_t *changed = NULL;
rdatasetheader_t *topheader, *topheader_prev, *header, *sigheader;
@@ -6211,6 +6360,19 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
*/
newheader->down = NULL;
free_rdataset(rbtdb, rbtdb->common.mctx, header);
+
+ idx = newheader->node->locknum;
+ if (IS_CACHE(rbtdb)) {
+ ISC_LIST_PREPEND(rbtdb->rdatasets[idx],
+ newheader, link);
+ INSIST(rbtdb->heaps != NULL);
+ (void)isc_heap_insert(rbtdb->heaps[idx],
+ newheader);
+ } else if (RESIGN(newheader)) {
+ result = resign_insert(rbtdb, idx, newheader);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
} else {
newheader->down = topheader;
topheader->next = newheader;
@@ -6238,9 +6400,14 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* will not leak... for long.
*/
INSIST(rbtdb->heaps != NULL);
- isc_heap_insert(rbtdb->heaps[idx], newheader);
- } else if (RESIGN(newheader))
- resign_insert(rbtdb, idx, newheader);
+ (void)isc_heap_insert(rbtdb->heaps[idx],
+ newheader);
+ } else if (RESIGN(newheader)) {
+ resign_delete(rbtdb, rbtversion, header);
+ result = resign_insert(rbtdb, idx, newheader);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
}
} else {
/*
@@ -6292,7 +6459,10 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
newheader, link);
isc_heap_insert(rbtdb->heaps[idx], newheader);
} else if (RESIGN(newheader)) {
- resign_insert(rbtdb, idx, newheader);
+ resign_delete(rbtdb, rbtversion, header);
+ result = resign_insert(rbtdb, idx, newheader);
+ if (result != ISC_R_SUCCESS)
+ return (result);
}
}
@@ -6601,8 +6771,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
}
if (result == ISC_R_SUCCESS)
- result = add(rbtdb, rbtnode, rbtversion, newheader, options,
- ISC_FALSE, addedrdataset, now);
+ result = add32(rbtdb, rbtnode, rbtversion, newheader, options,
+ ISC_FALSE, addedrdataset, now);
if (result == ISC_R_SUCCESS && delegating)
rbtnode->find_callback = 1;
@@ -6778,6 +6948,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
topheader->next = newheader;
rbtnode->dirty = 1;
changed->dirty = ISC_TRUE;
+ resign_delete(rbtdb, rbtversion, header);
} else {
/*
* The rdataset doesn't exist, so we don't need to do anything
@@ -6847,8 +7018,8 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
isc_rwlocktype_write);
- result = add(rbtdb, rbtnode, rbtversion, newheader, DNS_DBADD_FORCE,
- ISC_FALSE, NULL, 0);
+ result = add32(rbtdb, rbtnode, rbtversion, newheader, DNS_DBADD_FORCE,
+ ISC_FALSE, NULL, 0);
NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
isc_rwlocktype_write);
@@ -7042,8 +7213,8 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
} else
newheader->resign = 0;
- result = add(rbtdb, node, rbtdb->current_version, newheader,
- DNS_DBADD_MERGE, ISC_TRUE, NULL, 0);
+ result = add32(rbtdb, node, rbtdb->current_version, newheader,
+ DNS_DBADD_MERGE, ISC_TRUE, NULL, 0);
if (result == ISC_R_SUCCESS &&
delegating_type(rbtdb, node, rdataset->type))
node->find_callback = 1;
@@ -7411,6 +7582,9 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version)
INSIST(header != NULL);
header--;
+ if (header->heap_index == 0)
+ return;
+
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
NODE_LOCK(&rbtdb->node_locks[node->locknum].lock,
isc_rwlocktype_write);
@@ -7418,11 +7592,7 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version)
* Delete from heap and save to re-signed list so that it can
* be restored if we backout of this change.
*/
- new_reference(rbtdb, node);
- isc_heap_delete(rbtdb->heaps[node->locknum], header->heap_index);
- header->heap_index = 0;
- ISC_LIST_APPEND(rbtversion->resigned_list, header, link);
-
+ resign_delete(rbtdb, rbtversion, header);
NODE_UNLOCK(&rbtdb->node_locks[node->locknum].lock,
isc_rwlocktype_write);
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c
index 69007f881efd..2fdb751e6dbf 100644
--- a/lib/dns/rcode.c
+++ b/lib/dns/rcode.c
@@ -212,11 +212,13 @@ maybe_numeric(unsigned int *valuep, isc_textregion_t *source,
return (ISC_R_BADNUMBER);
/*
- * We have a potential number. Try to parse it with
- * isc_parse_uint32(). isc_parse_uint32() requires
+ * We have a potential number. Try to parse it with
+ * isc_parse_uint32(). isc_parse_uint32() requires
* null termination, so we must make a copy.
*/
- strncpy(buffer, source->base, NUMBERSIZE);
+ strncpy(buffer, source->base, sizeof(buffer));
+ buffer[sizeof(buffer) - 1] = '\0';
+
INSIST(buffer[source->length] == '\0');
result = isc_parse_uint32(&n, buffer, 10);
diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c
index 5bdd1255b5f7..08bfa34aa678 100644
--- a/lib/dns/rdata.c
+++ b/lib/dns/rdata.c
@@ -116,7 +116,7 @@ typedef struct dns_rdata_textctx {
} dns_rdata_textctx_t;
static isc_result_t
-txt_totext(isc_region_t *source, isc_buffer_t *target);
+txt_totext(isc_region_t *source, isc_boolean_t quote, isc_buffer_t *target);
static isc_result_t
txt_fromtext(isc_textregion_t *source, isc_buffer_t *target);
@@ -130,9 +130,6 @@ multitxt_totext(isc_region_t *source, isc_buffer_t *target);
static isc_result_t
multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target);
-static isc_result_t
-multitxt_fromwire(isc_buffer_t *source, isc_buffer_t *target);
-
static isc_boolean_t
name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target);
@@ -1131,7 +1128,7 @@ name_length(dns_name_t *name) {
}
static isc_result_t
-txt_totext(isc_region_t *source, isc_buffer_t *target) {
+txt_totext(isc_region_t *source, isc_boolean_t quote, isc_buffer_t *target) {
unsigned int tl;
unsigned int n;
unsigned char *sp;
@@ -1146,13 +1143,20 @@ txt_totext(isc_region_t *source, isc_buffer_t *target) {
n = *sp++;
REQUIRE(n + 1 <= source->length);
+ if (n == 0U)
+ REQUIRE(quote == ISC_TRUE);
- if (tl < 1)
- return (ISC_R_NOSPACE);
- *tp++ = '"';
- tl--;
+ if (quote) {
+ if (tl < 1)
+ return (ISC_R_NOSPACE);
+ *tp++ = '"';
+ tl--;
+ }
while (n--) {
- if (*sp < 0x20 || *sp >= 0x7f) {
+ /*
+ * \DDD space (0x20) if not quoting.
+ */
+ if (*sp < (quote ? 0x20 : 0x21) || *sp >= 0x7f) {
if (tl < 4)
return (ISC_R_NOSPACE);
*tp++ = 0x5c;
@@ -1163,8 +1167,13 @@ txt_totext(isc_region_t *source, isc_buffer_t *target) {
tl -= 4;
continue;
}
- /* double quote, semi-colon, backslash */
- if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c) {
+ /*
+ * Escape double quote, semi-colon, backslash.
+ * If we are not enclosing the string in double
+ * quotes also escape at sign.
+ */
+ if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c ||
+ (!quote && *sp == 0x40)) {
if (tl < 2)
return (ISC_R_NOSPACE);
*tp++ = '\\';
@@ -1175,10 +1184,12 @@ txt_totext(isc_region_t *source, isc_buffer_t *target) {
*tp++ = *sp++;
tl--;
}
- if (tl < 1)
- return (ISC_R_NOSPACE);
- *tp++ = '"';
- tl--;
+ if (quote) {
+ if (tl < 1)
+ return (ISC_R_NOSPACE);
+ *tp++ = '"';
+ tl--;
+ }
isc_buffer_add(target, (unsigned int)(tp - (char *)region.base));
isc_region_consume(source, *source->base + 1);
return (ISC_R_SUCCESS);
@@ -1274,6 +1285,9 @@ txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
return (ISC_R_SUCCESS);
}
+/*
+ * Conversion of TXT-like rdata fields without length limits.
+ */
static isc_result_t
multitxt_totext(isc_region_t *source, isc_buffer_t *target) {
unsigned int tl;
@@ -1292,9 +1306,8 @@ multitxt_totext(isc_region_t *source, isc_buffer_t *target) {
*tp++ = '"';
tl--;
do {
- n0 = n = *sp++;
-
- REQUIRE(n0 + 1 <= source->length);
+ n = source->length;
+ n0 = source->length - 1;
while (n--) {
if (*sp < 0x20 || *sp >= 0x7f) {
@@ -1346,17 +1359,11 @@ multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
do {
isc_buffer_availableregion(target, &tregion);
- t0 = tregion.base;
+ t0 = t = tregion.base;
nrem = tregion.length;
if (nrem < 1)
return (ISC_R_NOSPACE);
- /* length byte */
- t = t0;
- nrem--;
- t++;
- /* 255 byte character-string slice */
- if (nrem > 255)
- nrem = 255;
+
while (n != 0) {
--n;
c = (*s++) & 0xff;
@@ -1390,39 +1397,9 @@ multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
}
if (escape)
return (DNS_R_SYNTAX);
- *t0 = (unsigned char)(t - t0 - 1);
- isc_buffer_add(target, *t0 + 1);
- } while (n != 0);
- return (ISC_R_SUCCESS);
-}
-
-static isc_result_t
-multitxt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
- unsigned int n;
- isc_region_t sregion;
- isc_region_t tregion;
-
- isc_buffer_activeregion(source, &sregion);
- if (sregion.length == 0)
- return(ISC_R_UNEXPECTEDEND);
- n = 256U;
- do {
- if (n != 256U)
- return (DNS_R_SYNTAX);
- n = *sregion.base + 1;
- if (n > sregion.length)
- return (ISC_R_UNEXPECTEDEND);
- isc_buffer_availableregion(target, &tregion);
- if (n > tregion.length)
- return (ISC_R_NOSPACE);
-
- if (tregion.base != sregion.base)
- memmove(tregion.base, sregion.base, n);
- isc_buffer_forward(source, n);
- isc_buffer_add(target, n);
- isc_buffer_activeregion(source, &sregion);
- } while (sregion.length != 0);
+ isc_buffer_add(target, t - t0);
+ } while (n != 0);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/generic/caa_257.c b/lib/dns/rdata/generic/caa_257.c
new file mode 100644
index 000000000000..993e3267e623
--- /dev/null
+++ b/lib/dns/rdata/generic/caa_257.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef GENERIC_CAA_257_C
+#define GENERIC_CAA_257_C 1
+
+#define RRTYPE_CAA_ATTRIBUTES (0)
+
+static unsigned char const alphanumeric[256] = {
+ /* 0x00-0x0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x10-0x1f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x20-0x2f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x30-0x3f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ /* 0x40-0x4f */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 0x50-0x5f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ /* 0x60-0x6f */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 0x70-0x7f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ /* 0x80-0x8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x90-0x9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xa0-0xaf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xb0-0xbf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xc0-0xcf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xd0-0xdf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xe0-0xef */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xf0-0xff */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static inline isc_result_t
+fromtext_caa(ARGS_FROMTEXT) {
+ isc_token_t token;
+ isc_textregion_t tr;
+ isc_uint8_t flags;
+ unsigned int i;
+
+ REQUIRE(type == 257);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* Flags. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 255U)
+ RETTOK(ISC_R_RANGE);
+ flags = token.value.as_ulong;
+ RETERR(uint8_tobuffer(flags, target));
+
+ /*
+ * Tag
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ tr = token.value.as_textregion;
+ for (i = 0; i < tr.length; i++)
+ if (!alphanumeric[(unsigned int) tr.base[i]])
+ RETTOK(DNS_R_SYNTAX);
+ RETERR(uint8_tobuffer(tr.length, target));
+ RETERR(mem_tobuffer(target, tr.base, tr.length));
+
+ /*
+ * Value
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_qstring, ISC_FALSE));
+ if (token.type != isc_tokentype_qstring &&
+ token.type != isc_tokentype_string)
+ RETERR(DNS_R_SYNTAX);
+ RETERR(multitxt_fromtext(&token.value.as_textregion, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_caa(ARGS_TOTEXT) {
+ isc_region_t region;
+ isc_uint8_t flags;
+ char buf[256];
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == 257);
+ REQUIRE(rdata->length >= 3U);
+ REQUIRE(rdata->data != NULL);
+
+ dns_rdata_toregion(rdata, &region);
+
+ /*
+ * Flags
+ */
+ flags = uint8_consume_fromregion(&region);
+ sprintf(buf, "%u ", flags);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Tag
+ */
+ RETERR(txt_totext(&region, ISC_FALSE, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Value
+ */
+ RETERR(multitxt_totext(&region, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_caa(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ unsigned int len, i;
+
+ REQUIRE(type == 257);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ /*
+ * Flags
+ */
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+
+ /*
+ * Flags, tag length
+ */
+ RETERR(mem_tobuffer(target, sr.base, 2));
+ len = sr.base[1];
+ isc_region_consume(&sr, 2);
+ isc_buffer_forward(source, 2);
+
+ /*
+ * Zero length tag fields are illegal.
+ */
+ if (sr.length < len || len == 0)
+ RETERR(DNS_R_FORMERR);
+
+ /* Check the Tag's value */
+ for (i = 0; i < len; i++)
+ if (!alphanumeric[sr.base[i]])
+ RETERR(DNS_R_FORMERR);
+ /*
+ * Tag + Value
+ */
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_caa(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 257);
+ REQUIRE(rdata->length >= 3U);
+ REQUIRE(rdata->data != NULL);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &region);
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static inline int
+compare_caa(ARGS_COMPARE) {
+ isc_region_t r1, r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 257);
+ REQUIRE(rdata1->length >= 3U);
+ REQUIRE(rdata2->length >= 3U);
+ REQUIRE(rdata1->data != NULL);
+ REQUIRE(rdata2->data != NULL);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_caa(ARGS_FROMSTRUCT) {
+ dns_rdata_caa_t *caa = source;
+ isc_region_t region;
+ unsigned int i;
+
+ REQUIRE(type == 257);
+ REQUIRE(source != NULL);
+ REQUIRE(caa->common.rdtype == type);
+ REQUIRE(caa->common.rdclass == rdclass);
+ REQUIRE(caa->tag != NULL && caa->tag_len != 0);
+ REQUIRE(caa->value != NULL);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Flags
+ */
+ RETERR(uint8_tobuffer(caa->flags, target));
+
+ /*
+ * Tag length
+ */
+ RETERR(uint8_tobuffer(caa->tag_len, target));
+
+ /*
+ * Tag
+ */
+ region.base = caa->tag;
+ region.length = caa->tag_len;
+ for (i = 0; i < region.length; i++)
+ if (!alphanumeric[region.base[i]])
+ RETERR(DNS_R_SYNTAX);
+ RETERR(isc_buffer_copyregion(target, &region));
+
+ /*
+ * Value
+ */
+ region.base = caa->value;
+ region.length = caa->value_len;
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_caa(ARGS_TOSTRUCT) {
+ dns_rdata_caa_t *caa = target;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 257);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length >= 3U);
+ REQUIRE(rdata->data != NULL);
+
+ caa->common.rdclass = rdata->rdclass;
+ caa->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&caa->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Flags
+ */
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ caa->flags = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Tag length
+ */
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ caa->tag_len = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Tag
+ */
+ if (sr.length < caa->tag_len)
+ return (ISC_R_UNEXPECTEDEND);
+ caa->tag = mem_maybedup(mctx, sr.base, caa->tag_len);
+ if (caa->tag == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_region_consume(&sr, caa->tag_len);
+
+ /*
+ * Value
+ */
+ caa->value_len = sr.length;
+ caa->value = mem_maybedup(mctx, sr.base, sr.length);
+ if (caa->value == NULL)
+ return (ISC_R_NOMEMORY);
+
+ caa->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_caa(ARGS_FREESTRUCT) {
+ dns_rdata_caa_t *caa = (dns_rdata_caa_t *) source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(caa->common.rdtype == 257);
+
+ if (caa->mctx == NULL)
+ return;
+
+ if (caa->tag != NULL)
+ isc_mem_free(caa->mctx, caa->tag);
+ if (caa->value != NULL)
+ isc_mem_free(caa->mctx, caa->value);
+ caa->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_caa(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 257);
+ REQUIRE(rdata->data != NULL);
+ REQUIRE(rdata->length >= 3U);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_caa(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 257);
+ REQUIRE(rdata->data != NULL);
+ REQUIRE(rdata->length >= 3U);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_caa(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 257);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_caa(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 257);
+ REQUIRE(rdata->data != NULL);
+ REQUIRE(rdata->length >= 3U);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+static inline int
+casecompare_caa(ARGS_COMPARE) {
+ return (compare_caa(rdata1, rdata2));
+}
+
+#endif /* GENERIC_CAA_257_C */
diff --git a/lib/dns/rdata/generic/caa_257.h b/lib/dns/rdata/generic/caa_257.h
new file mode 100644
index 000000000000..9432f0f7f1ad
--- /dev/null
+++ b/lib/dns/rdata/generic/caa_257.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef GENERIC_CAA_257_H
+#define GENERIC_CAA_257_H 1
+
+/* $Id$ */
+
+typedef struct dns_rdata_caa {
+ dns_rdatacommon_t common;
+ isc_mem_t * mctx;
+ isc_uint8_t flags;
+ unsigned char * tag;
+ isc_uint8_t tag_len;
+ unsigned char *value;
+ isc_uint8_t value_len;
+} dns_rdata_caa_t;
+
+#endif /* GENERIC_CAA_257_H */
diff --git a/lib/dns/rdata/generic/cdnskey_60.c b/lib/dns/rdata/generic/cdnskey_60.c
new file mode 100644
index 000000000000..a1e681403b75
--- /dev/null
+++ b/lib/dns/rdata/generic/cdnskey_60.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2014 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$ */
+
+/*
+ * Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley.
+ */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_CDNSKEY_60_C
+#define RDATA_GENERIC_CDNSKEY_60_C
+
+#include <dst/dst.h>
+
+#define RRTYPE_CDNSKEY_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static inline isc_result_t
+fromtext_cdnskey(ARGS_FROMTEXT) {
+ isc_result_t result;
+ isc_token_t token;
+ dns_secalg_t alg;
+ dns_secproto_t proto;
+ dns_keyflags_t flags;
+
+ REQUIRE(type == 60);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* flags */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
+ RETERR(uint16_tobuffer(flags, target));
+
+ /* protocol */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &proto, 1));
+
+ /* algorithm */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &alg, 1));
+
+ /* No Key? */
+ if ((flags & 0xc000) == 0xc000)
+ return (ISC_R_SUCCESS);
+
+ result = isc_base64_tobuffer(lexer, target, -1);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /* Ensure there's at least enough data to compute a key ID for MD5 */
+ if (alg == DST_ALG_RSAMD5 && isc_buffer_usedlength(target) < 7)
+ return (ISC_R_UNEXPECTEDEND);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_cdnskey(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000")];
+ unsigned int flags;
+ unsigned char algorithm;
+ char algbuf[DNS_NAME_FORMATSIZE];
+ const char *keyinfo;
+
+ REQUIRE(rdata->type == 60);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* flags */
+ flags = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%u", flags);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+ if ((flags & DNS_KEYFLAG_KSK) != 0) {
+ if (flags & DNS_KEYFLAG_REVOKE)
+ keyinfo = "revoked KSK";
+ else
+ keyinfo = "KSK";
+ } else
+ keyinfo = "ZSK";
+
+ /* protocol */
+ sprintf(buf, "%u", sr.base[0]);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /* algorithm */
+ algorithm = sr.base[0];
+ sprintf(buf, "%u", algorithm);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+
+ /* No Key? */
+ if ((flags & 0xc000) == 0xc000)
+ return (ISC_R_SUCCESS);
+
+ if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 &&
+ algorithm == DNS_KEYALG_PRIVATEDNS) {
+ dns_name_t name;
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &sr);
+ dns_name_format(&name, algbuf, sizeof(algbuf));
+ } else {
+ dns_secalg_format((dns_secalg_t) algorithm, algbuf,
+ sizeof(algbuf));
+ }
+
+ /* key */
+ 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_base64_totext(&sr, 0, "", target));
+ else
+ RETERR(isc_base64_totext(&sr, tctx->width - 2,
+ tctx->linebreak, target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0)
+ RETERR(str_totext(tctx->linebreak, target));
+ else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" ", target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(")", target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
+ isc_region_t tmpr;
+
+ RETERR(str_totext(" ; ", target));
+ RETERR(str_totext(keyinfo, target));
+ RETERR(str_totext("; alg = ", target));
+ RETERR(str_totext(algbuf, target));
+ RETERR(str_totext("; key id = ", target));
+ dns_rdata_toregion(rdata, &tmpr);
+ sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm));
+ RETERR(str_totext(buf, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_cdnskey(ARGS_FROMWIRE) {
+ unsigned char algorithm;
+ isc_region_t sr;
+
+ REQUIRE(type == 60);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 4)
+ return (ISC_R_UNEXPECTEDEND);
+
+ algorithm = sr.base[3];
+ RETERR(mem_tobuffer(target, sr.base, 4));
+ isc_region_consume(&sr, 4);
+ isc_buffer_forward(source, 4);
+
+ if (algorithm == DNS_KEYALG_PRIVATEDNS) {
+ dns_name_t name;
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+ }
+
+ /*
+ * RSAMD5 computes key ID differently from other
+ * algorithms: we need to ensure there's enough data
+ * present for the computation
+ */
+ if (algorithm == DST_ALG_RSAMD5 && sr.length < 3)
+ return (ISC_R_UNEXPECTEDEND);
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_cdnskey(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 60);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_cdnskey(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 60);
+ 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_cdnskey(ARGS_FROMSTRUCT) {
+ dns_rdata_cdnskey_t *dnskey = source;
+
+ REQUIRE(type == 60);
+ REQUIRE(source != NULL);
+ REQUIRE(dnskey->common.rdtype == type);
+ REQUIRE(dnskey->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /* Flags */
+ RETERR(uint16_tobuffer(dnskey->flags, target));
+
+ /* Protocol */
+ RETERR(uint8_tobuffer(dnskey->protocol, target));
+
+ /* Algorithm */
+ RETERR(uint8_tobuffer(dnskey->algorithm, target));
+
+ /* Data */
+ return (mem_tobuffer(target, dnskey->data, dnskey->datalen));
+}
+
+static inline isc_result_t
+tostruct_cdnskey(ARGS_TOSTRUCT) {
+ dns_rdata_cdnskey_t *dnskey = target;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 60);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ dnskey->common.rdclass = rdata->rdclass;
+ dnskey->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&dnskey->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* Flags */
+ if (sr.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ dnskey->flags = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /* Protocol */
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ dnskey->protocol = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Algorithm */
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ dnskey->algorithm = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Data */
+ dnskey->datalen = sr.length;
+ dnskey->data = mem_maybedup(mctx, sr.base, dnskey->datalen);
+ if (dnskey->data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dnskey->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_cdnskey(ARGS_FREESTRUCT) {
+ dns_rdata_cdnskey_t *dnskey = (dns_rdata_cdnskey_t *) source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(dnskey->common.rdtype == 60);
+
+ if (dnskey->mctx == NULL)
+ return;
+
+ if (dnskey->data != NULL)
+ isc_mem_free(dnskey->mctx, dnskey->data);
+ dnskey->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_cdnskey(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 60);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_cdnskey(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 60);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_cdnskey(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 60);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_cdnskey(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 60);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+static inline int
+casecompare_cdnskey(ARGS_COMPARE) {
+
+ /*
+ * Treat ALG 253 (private DNS) subtype name case sensistively.
+ */
+ return (compare_cdnskey(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_CDNSKEY_60_C */
diff --git a/lib/dns/rdata/generic/cdnskey_60.h b/lib/dns/rdata/generic/cdnskey_60.h
new file mode 100644
index 000000000000..d284177c118d
--- /dev/null
+++ b/lib/dns/rdata/generic/cdnskey_60.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef GENERIC_CDNSKEY_60_H
+#define GENERIC_CDNSKEY_60_H 1
+
+/* CDNSKEY records have the same RDATA fields as DNSKEY records. */
+typedef struct dns_rdata_cdnskey {
+ dns_rdatacommon_t common;
+ isc_mem_t * mctx;
+ isc_uint16_t flags;
+ isc_uint8_t protocol;
+ isc_uint8_t algorithm;
+ isc_uint16_t datalen;
+ unsigned char * data;
+} dns_rdata_cdnskey_t;
+
+
+#endif /* GENERIC_CDNSKEY_60_H */
diff --git a/lib/dns/rdata/generic/cds_59.c b/lib/dns/rdata/generic/cds_59.c
new file mode 100644
index 000000000000..fcf49662c46a
--- /dev/null
+++ b/lib/dns/rdata/generic/cds_59.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2014 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-dnsext-delegation-signer-05.txt */
+
+#ifndef RDATA_GENERIC_CDS_59_C
+#define RDATA_GENERIC_CDS_59_C
+
+#define RRTYPE_CDS_ATTRIBUTES \
+ (DNS_RDATATYPEATTR_DNSSEC|DNS_RDATATYPEATTR_ATPARENT)
+
+#include <isc/sha1.h>
+#include <isc/sha2.h>
+
+#include <dns/ds.h>
+
+static inline isc_result_t
+fromtext_cds(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char c;
+ int length;
+
+ REQUIRE(type == 59);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * Key tag.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Digest 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));
+ c = (unsigned char) token.value.as_ulong;
+
+ /*
+ * Digest.
+ */
+ switch (c) {
+ case DNS_DSDIGEST_SHA1:
+ length = ISC_SHA1_DIGESTLENGTH;
+ break;
+ case DNS_DSDIGEST_SHA256:
+ length = ISC_SHA256_DIGESTLENGTH;
+ break;
+ case DNS_DSDIGEST_GOST:
+ length = ISC_GOST_DIGESTLENGTH;
+ break;
+ case DNS_DSDIGEST_SHA384:
+ length = ISC_SHA384_DIGESTLENGTH;
+ break;
+ default:
+ length = -1;
+ break;
+ }
+ return (isc_hex_tobuffer(lexer, target, length));
+}
+
+static inline isc_result_t
+totext_cds(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000 ")];
+ unsigned int n;
+
+ REQUIRE(rdata->type == 59);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Key tag.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Algorithm.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest type.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest.
+ */
+ 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_cds(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 59);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+
+ /*
+ * Check digest lengths if we know them.
+ */
+ if (sr.length < 4 ||
+ (sr.base[3] == DNS_DSDIGEST_SHA1 &&
+ sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
+ (sr.base[3] == DNS_DSDIGEST_SHA256 &&
+ sr.length < 4 + ISC_SHA256_DIGESTLENGTH) ||
+ (sr.base[3] == DNS_DSDIGEST_GOST &&
+ sr.length < 4 + ISC_GOST_DIGESTLENGTH) ||
+ (sr.base[3] == DNS_DSDIGEST_SHA384 &&
+ sr.length < 4 + ISC_SHA384_DIGESTLENGTH))
+ return (ISC_R_UNEXPECTEDEND);
+
+ /*
+ * Only copy digest lengths if we know them.
+ * If there is extra data dns_rdata_fromwire() will
+ * detect that.
+ */
+ if (sr.base[3] == DNS_DSDIGEST_SHA1)
+ sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
+ else if (sr.base[3] == DNS_DSDIGEST_SHA256)
+ sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
+ else if (sr.base[3] == DNS_DSDIGEST_GOST)
+ sr.length = 4 + ISC_GOST_DIGESTLENGTH;
+ else if (sr.base[3] == DNS_DSDIGEST_SHA384)
+ sr.length = 4 + ISC_SHA384_DIGESTLENGTH;
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_cds(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 59);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_cds(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 59);
+ 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_cds(ARGS_FROMSTRUCT) {
+ dns_rdata_cds_t *ds = source;
+
+ REQUIRE(type == 59);
+ REQUIRE(source != NULL);
+ REQUIRE(ds->common.rdtype == type);
+ REQUIRE(ds->common.rdclass == rdclass);
+ switch (ds->digest_type) {
+ case DNS_DSDIGEST_SHA1:
+ REQUIRE(ds->length == ISC_SHA1_DIGESTLENGTH);
+ break;
+ case DNS_DSDIGEST_SHA256:
+ REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH);
+ break;
+ case DNS_DSDIGEST_GOST:
+ REQUIRE(ds->length == ISC_GOST_DIGESTLENGTH);
+ break;
+ case DNS_DSDIGEST_SHA384:
+ REQUIRE(ds->length == ISC_SHA384_DIGESTLENGTH);
+ break;
+ }
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(ds->key_tag, target));
+ RETERR(uint8_tobuffer(ds->algorithm, target));
+ RETERR(uint8_tobuffer(ds->digest_type, target));
+
+ return (mem_tobuffer(target, ds->digest, ds->length));
+}
+
+static inline isc_result_t
+tostruct_cds(ARGS_TOSTRUCT) {
+ dns_rdata_cds_t *ds = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 59);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ ds->common.rdclass = rdata->rdclass;
+ ds->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&ds->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ ds->key_tag = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ ds->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ ds->digest_type = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ ds->length = region.length;
+
+ ds->digest = mem_maybedup(mctx, region.base, region.length);
+ if (ds->digest == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ds->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_cds(ARGS_FREESTRUCT) {
+ dns_rdata_cds_t *ds = source;
+
+ REQUIRE(ds != NULL);
+ REQUIRE(ds->common.rdtype == 59);
+
+ if (ds->mctx == NULL)
+ return;
+
+ if (ds->digest != NULL)
+ isc_mem_free(ds->mctx, ds->digest);
+ ds->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_cds(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 59);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_cds(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 59);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_cds(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 59);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_cds(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 59);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+static inline int
+casecompare_cds(ARGS_COMPARE) {
+ return (compare_cds(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_CDS_59_C */
diff --git a/lib/dns/rdata/generic/cds_59.h b/lib/dns/rdata/generic/cds_59.h
new file mode 100644
index 000000000000..099cba39468c
--- /dev/null
+++ b/lib/dns/rdata/generic/cds_59.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef GENERIC_CDS_59_H
+#define GENERIC_CDS_59_H 1
+
+/* CDS records have the same RDATA fields as DS records. */
+typedef struct dns_rdata_cds {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t key_tag;
+ isc_uint8_t algorithm;
+ isc_uint8_t digest_type;
+ isc_uint16_t length;
+ unsigned char *digest;
+} dns_rdata_cds_t;
+
+#endif /* GENERIC_CDS_59_H */
diff --git a/lib/dns/rdata/generic/gpos_27.c b/lib/dns/rdata/generic/gpos_27.c
index ce71822b8237..e9ba59eacb6a 100644
--- a/lib/dns/rdata/generic/gpos_27.c
+++ b/lib/dns/rdata/generic/gpos_27.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -61,7 +61,7 @@ totext_gpos(ARGS_TOTEXT) {
dns_rdata_toregion(rdata, &region);
for (i = 0; i < 3; i++) {
- RETERR(txt_totext(&region, target));
+ RETERR(txt_totext(&region, ISC_TRUE, target));
if (i != 2)
RETERR(str_totext(" ", target));
}
diff --git a/lib/dns/rdata/generic/hinfo_13.c b/lib/dns/rdata/generic/hinfo_13.c
index 10b4fec79dea..411d6b56866e 100644
--- a/lib/dns/rdata/generic/hinfo_13.c
+++ b/lib/dns/rdata/generic/hinfo_13.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -58,9 +58,9 @@ totext_hinfo(ARGS_TOTEXT) {
REQUIRE(rdata->length != 0);
dns_rdata_toregion(rdata, &region);
- RETERR(txt_totext(&region, target));
+ RETERR(txt_totext(&region, ISC_TRUE, target));
RETERR(str_totext(" ", target));
- return (txt_totext(&region, target));
+ return (txt_totext(&region, ISC_TRUE, target));
}
static inline isc_result_t
diff --git a/lib/dns/rdata/generic/hip_55.c b/lib/dns/rdata/generic/hip_55.c
index 5198497dcb07..eee581f26a95 100644
--- a/lib/dns/rdata/generic/hip_55.c
+++ b/lib/dns/rdata/generic/hip_55.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009, 2011, 2013, 2014 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
@@ -318,6 +318,8 @@ tostruct_hip(ARGS_TOSTRUCT) {
goto cleanup;
isc_region_consume(&region, hip->hit_len);
+ INSIST(hip->key_len <= region.length);
+
hip->key = mem_maybedup(mctx, region.base, hip->key_len);
if (hip->key == NULL)
goto cleanup;
@@ -466,23 +468,19 @@ casecompare_hip(ARGS_COMPARE) {
INSIST(r1.length > 4);
INSIST(r2.length > 4);
- r1.length = 4;
- r2.length = 4;
- order = isc_region_compare(&r1, &r2);
+ order = memcmp(r1.base, r2.base, 4);
if (order != 0)
return (order);
hit_len = uint8_fromregion(&r1);
isc_region_consume(&r1, 2); /* hit length + algorithm */
key_len = uint16_fromregion(&r1);
-
- dns_rdata_toregion(rdata1, &r1);
- dns_rdata_toregion(rdata2, &r2);
- isc_region_consume(&r1, 4);
+ isc_region_consume(&r1, 2); /* key length */
isc_region_consume(&r2, 4);
+
INSIST(r1.length >= (unsigned) (hit_len + key_len));
INSIST(r2.length >= (unsigned) (hit_len + key_len));
- order = isc_region_compare(&r1, &r2);
+ order = memcmp(r1.base, r2.base, hit_len + key_len);
if (order != 0)
return (order);
isc_region_consume(&r1, hit_len + key_len);
diff --git a/lib/dns/rdata/generic/isdn_20.c b/lib/dns/rdata/generic/isdn_20.c
index 0bf2146013e8..dea36f0f658a 100644
--- a/lib/dns/rdata/generic/isdn_20.c
+++ b/lib/dns/rdata/generic/isdn_20.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -65,11 +65,11 @@ totext_isdn(ARGS_TOTEXT) {
UNUSED(tctx);
dns_rdata_toregion(rdata, &region);
- RETERR(txt_totext(&region, target));
+ RETERR(txt_totext(&region, ISC_TRUE, target));
if (region.length == 0)
return (ISC_R_SUCCESS);
RETERR(str_totext(" ", target));
- return (txt_totext(&region, target));
+ return (txt_totext(&region, ISC_TRUE, target));
}
static inline isc_result_t
diff --git a/lib/dns/rdata/generic/naptr_35.c b/lib/dns/rdata/generic/naptr_35.c
index 83439a59293e..d7452ac176fe 100644
--- a/lib/dns/rdata/generic/naptr_35.c
+++ b/lib/dns/rdata/generic/naptr_35.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -224,19 +224,19 @@ totext_naptr(ARGS_TOTEXT) {
/*
* Flags.
*/
- RETERR(txt_totext(&region, target));
+ RETERR(txt_totext(&region, ISC_TRUE, target));
RETERR(str_totext(" ", target));
/*
* Service.
*/
- RETERR(txt_totext(&region, target));
+ RETERR(txt_totext(&region, ISC_TRUE, target));
RETERR(str_totext(" ", target));
/*
* Regexp.
*/
- RETERR(txt_totext(&region, target));
+ RETERR(txt_totext(&region, ISC_TRUE, target));
RETERR(str_totext(" ", target));
/*
diff --git a/lib/dns/rdata/generic/nsec3_50.c b/lib/dns/rdata/generic/nsec3_50.c
index 19b94efa06dc..35fcf5d58229 100644
--- a/lib/dns/rdata/generic/nsec3_50.c
+++ b/lib/dns/rdata/generic/nsec3_50.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2008, 2009, 2011, 2012, 2014 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
@@ -100,7 +100,7 @@ fromtext_nsec3(ARGS_FROMTEXT) {
RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
ISC_FALSE));
isc_buffer_init(&b, bm, sizeof(bm));
- RETTOK(isc_base32hex_decodestring(DNS_AS_STR(token), &b));
+ RETTOK(isc_base32hexnp_decodestring(DNS_AS_STR(token), &b));
if (isc_buffer_usedlength(&b) > 0xffU)
RETTOK(ISC_R_RANGE);
RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
@@ -191,7 +191,7 @@ totext_nsec3(ARGS_TOTEXT) {
i = sr.length;
sr.length = j;
- RETERR(isc_base32hex_totext(&sr, 1, "", target));
+ RETERR(isc_base32hexnp_totext(&sr, 1, "", target));
sr.length = i - j;
if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0)
@@ -474,15 +474,26 @@ digest_nsec3(ARGS_DIGEST) {
static inline isc_boolean_t
checkowner_nsec3(ARGS_CHECKOWNER) {
+ unsigned char owner[NSEC3_MAX_HASH_LENGTH];
+ isc_buffer_t buffer;
+ dns_label_t label;
- REQUIRE(type == 50);
+ REQUIRE(type == 50);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
- UNUSED(name);
- UNUSED(type);
- UNUSED(rdclass);
- UNUSED(wildcard);
+ /*
+ * First label is a base32hex string without padding.
+ */
+ dns_name_getlabel(name, 0, &label);
+ isc_region_consume(&label, 1);
+ isc_buffer_init(&buffer, owner, sizeof(owner));
+ if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS)
+ return (ISC_TRUE);
- return (ISC_TRUE);
+ return (ISC_FALSE);
}
static inline isc_boolean_t
diff --git a/lib/dns/rdata/generic/opt_41.c b/lib/dns/rdata/generic/opt_41.c
index bd2adb5fe971..ae09abf71e91 100644
--- a/lib/dns/rdata/generic/opt_41.c
+++ b/lib/dns/rdata/generic/opt_41.c
@@ -151,6 +151,14 @@ fromwire_opt(ARGS_FROMWIRE) {
isc_region_consume(&sregion, addrbytes);
break;
}
+ case DNS_OPT_EXPIRE:
+ /*
+ * Request has zero length. Response is 32 bits.
+ */
+ if (length != 0 && length != 4)
+ return (DNS_R_FORMERR);
+ isc_region_consume(&sregion, length);
+ break;
default:
isc_region_consume(&sregion, length);
break;
diff --git a/lib/dns/rdata/generic/spf_99.c b/lib/dns/rdata/generic/spf_99.c
index c7cdfc9fbbad..10e86b888f3a 100644
--- a/lib/dns/rdata/generic/spf_99.c
+++ b/lib/dns/rdata/generic/spf_99.c
@@ -64,7 +64,7 @@ totext_spf(ARGS_TOTEXT) {
dns_rdata_toregion(rdata, &region);
while (region.length > 0) {
- RETERR(txt_totext(&region, target));
+ RETERR(txt_totext(&region, ISC_TRUE, target));
if (region.length > 0)
RETERR(str_totext(" ", target));
}
diff --git a/lib/dns/rdata/generic/tkey_249.c b/lib/dns/rdata/generic/tkey_249.c
index 6f1ec0253881..0c91fd221ed8 100644
--- a/lib/dns/rdata/generic/tkey_249.c
+++ b/lib/dns/rdata/generic/tkey_249.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009, 2011, 2012, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -465,6 +465,7 @@ tostruct_tkey(ARGS_TOSTRUCT) {
/*
* Key.
*/
+ INSIST(tkey->keylen + 2U <= sr.length);
tkey->key = mem_maybedup(mctx, sr.base, tkey->keylen);
if (tkey->key == NULL)
goto cleanup;
@@ -479,6 +480,7 @@ tostruct_tkey(ARGS_TOSTRUCT) {
/*
* Other.
*/
+ INSIST(tkey->otherlen <= sr.length);
tkey->other = mem_maybedup(mctx, sr.base, tkey->otherlen);
if (tkey->other == NULL)
goto cleanup;
diff --git a/lib/dns/rdata/generic/tlsa_52.c b/lib/dns/rdata/generic/tlsa_52.c
index 11c6d7528f98..b46556d35d4e 100644
--- a/lib/dns/rdata/generic/tlsa_52.c
+++ b/lib/dns/rdata/generic/tlsa_52.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2012, 2014 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
@@ -16,7 +16,7 @@
/* $Id$ */
-/* draft-ietf-dane-protocol-19.txt */
+/* rfc6698.txt */
#ifndef RDATA_GENERIC_TLSA_52_C
#define RDATA_GENERIC_TLSA_52_C
diff --git a/lib/dns/rdata/generic/tlsa_52.h b/lib/dns/rdata/generic/tlsa_52.h
index 83ce9529976d..31bbf015c167 100644
--- a/lib/dns/rdata/generic/tlsa_52.h
+++ b/lib/dns/rdata/generic/tlsa_52.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2012, 2014 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
@@ -20,7 +20,7 @@
#define GENERIC_TLSA_52_H 1
/*!
- * \brief per draft-ietf-dane-protocol-19.txt
+ * \brief per rfc6698.txt
*/
typedef struct dns_rdata_tlsa {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c
index 76109251a766..41e270279216 100644
--- a/lib/dns/rdata/generic/txt_16.c
+++ b/lib/dns/rdata/generic/txt_16.c
@@ -71,7 +71,7 @@ totext_txt(ARGS_TOTEXT) {
dns_rdata_toregion(rdata, &region);
while (region.length > 0) {
- RETERR(txt_totext(&region, target));
+ RETERR(txt_totext(&region, ISC_TRUE, target));
if (region.length > 0)
RETERR(str_totext(" ", target));
}
diff --git a/lib/dns/rdata/generic/uri_256.c b/lib/dns/rdata/generic/uri_256.c
index 799eb694e666..3ddd790847ac 100644
--- a/lib/dns/rdata/generic/uri_256.c
+++ b/lib/dns/rdata/generic/uri_256.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2011, 2012, 2014 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
@@ -115,15 +115,12 @@ fromwire_uri(ARGS_FROMWIRE) {
isc_buffer_activeregion(source, &region);
if (region.length < 4)
return (ISC_R_UNEXPECTEDEND);
- RETERR(mem_tobuffer(target, region.base, 4));
- isc_buffer_forward(source, 4);
/*
- * Target URI
+ * Priority, weight and target URI
*/
- RETERR(multitxt_fromwire(source, target));
-
- return (ISC_R_SUCCESS);
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
}
static inline isc_result_t
@@ -178,8 +175,6 @@ compare_uri(ARGS_COMPARE) {
static inline isc_result_t
fromstruct_uri(ARGS_FROMSTRUCT) {
dns_rdata_uri_t *uri = source;
- isc_region_t region;
- isc_uint8_t len;
REQUIRE(type == 256);
REQUIRE(source != NULL);
@@ -203,18 +198,6 @@ fromstruct_uri(ARGS_FROMSTRUCT) {
/*
* Target URI
*/
- len = 255U;
- region.base = uri->target;
- region.length = uri->tgt_len;
- while (region.length > 0) {
- REQUIRE(len == 255U);
- len = uint8_fromregion(&region);
- isc_region_consume(&region, 1);
- if (region.length < len)
- return (ISC_R_UNEXPECTEDEND);
- isc_region_consume(&region, len);
- }
-
return (mem_tobuffer(target, uri->target, uri->tgt_len));
}
diff --git a/lib/dns/rdata/generic/x25_19.c b/lib/dns/rdata/generic/x25_19.c
index 6867fecd86f8..c5fe2d18b08c 100644
--- a/lib/dns/rdata/generic/x25_19.c
+++ b/lib/dns/rdata/generic/x25_19.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -60,7 +60,7 @@ totext_x25(ARGS_TOTEXT) {
REQUIRE(rdata->length != 0);
dns_rdata_toregion(rdata, &region);
- return (txt_totext(&region, target));
+ return (txt_totext(&region, ISC_TRUE, target));
}
static inline isc_result_t
diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c
index 1c02b60201b2..9367127d9eaf 100644
--- a/lib/dns/rdataslab.c
+++ b/lib/dns/rdataslab.c
@@ -148,21 +148,36 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
buflen = reservelen + 2;
- nalloc = dns_rdataset_count(rdataset);
- nitems = nalloc;
- if (nitems == 0 && rdataset->type != 0)
- return (ISC_R_FAILURE);
+ nitems = dns_rdataset_count(rdataset);
- if (nalloc > 0xffff)
- return (ISC_R_NOSPACE);
+ /*
+ * If there are no rdata then we can just need to allocate a header
+ * with zero a record count.
+ */
+ if (nitems == 0) {
+ if (rdataset->type != 0)
+ return (ISC_R_FAILURE);
+ rawbuf = isc_mem_get(mctx, buflen);
+ if (rawbuf == NULL)
+ return (ISC_R_NOMEMORY);
+ region->base = rawbuf;
+ region->length = buflen;
+ rawbuf += reservelen;
+ *rawbuf++ = 0;
+ *rawbuf = 0;
+ return (ISC_R_SUCCESS);
+ }
+ if (nitems > 0xffff)
+ return (ISC_R_NOSPACE);
- if (nalloc != 0) {
- x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata));
- if (x == NULL)
- return (ISC_R_NOMEMORY);
- } else
- x = NULL;
+ /*
+ * Remember the original number of items.
+ */
+ nalloc = nitems;
+ x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata));
+ if (x == NULL)
+ return (ISC_R_NOMEMORY);
/*
* Save all of the rdata members into an array.
@@ -180,12 +195,12 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
#endif
result = dns_rdataset_next(rdataset);
}
- if (result != ISC_R_NOMORE)
- goto free_rdatas;
- if (i != nalloc) {
+ if (i != nalloc || result != ISC_R_NOMORE) {
/*
* Somehow we iterated over fewer rdatas than
- * dns_rdataset_count() said there were!
+ * dns_rdataset_count() said there were or there
+ * were more items than dns_rdataset_count said
+ * there were.
*/
result = ISC_R_FAILURE;
goto free_rdatas;
@@ -194,7 +209,8 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
/*
* Put into DNSSEC order.
*/
- qsort(x, nalloc, sizeof(struct xrdata), compare_rdata);
+ if (nalloc > 1U)
+ qsort(x, nalloc, sizeof(struct xrdata), compare_rdata);
/*
* Remove duplicates and compute the total storage required.
@@ -230,17 +246,15 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
buflen++;
}
}
+
/*
* Don't forget the last item!
*/
- if (nalloc != 0) {
#if DNS_RDATASET_FIXED
- buflen += (8 + x[i-1].rdata.length);
+ buflen += (8 + x[i-1].rdata.length);
#else
- buflen += (2 + x[i-1].rdata.length);
+ buflen += (2 + x[i-1].rdata.length);
#endif
- }
-
/*
* Provide space to store the per RR meta data.
*/
@@ -330,8 +344,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
result = ISC_R_SUCCESS;
free_rdatas:
- if (x != NULL)
- isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata));
+ isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata));
return (result);
}
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index 2e60cd84cca2..befe3cafe0f2 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -21,6 +21,7 @@
#include <config.h>
+#include <isc/counter.h>
#include <isc/log.h>
#include <isc/platform.h>
#include <isc/print.h>
@@ -131,11 +132,20 @@
#define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */
#endif
+/* The default maximum number of recursions to follow before giving up. */
+#ifndef DEFAULT_RECURSION_DEPTH
+#define DEFAULT_RECURSION_DEPTH 7
+#endif
+
+/* The default maximum number of iterative queries to allow before giving up. */
+#ifndef DEFAULT_MAX_QUERIES
+#define DEFAULT_MAX_QUERIES 50
+#endif
+
/*%
* Maximum EDNS0 input packet size.
*/
#define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
-#define EDNSOPTS 2
/*%
* This defines the maximum number of timeouts we will permit before we
@@ -163,6 +173,7 @@ typedef struct query {
isc_buffer_t *tsig;
dns_tsigkey_t *tsigkey;
isc_socketevent_t sendevent;
+ int ednsversion;
unsigned int options;
unsigned int attributes;
unsigned int sends;
@@ -234,12 +245,13 @@ struct fetchctx {
isc_sockaddrlist_t edns;
isc_sockaddrlist_t edns512;
isc_sockaddrlist_t bad_edns;
- dns_validator_t *validator;
+ dns_validator_t * validator;
ISC_LIST(dns_validator_t) validators;
dns_db_t * cache;
dns_adb_t * adb;
isc_boolean_t ns_ttl_ok;
isc_uint32_t ns_ttl;
+ isc_counter_t * qc;
/*%
* The number of events we're waiting for.
@@ -307,6 +319,7 @@ struct fetchctx {
isc_boolean_t timeout;
dns_adbaddrinfo_t *addrinfo;
isc_sockaddr_t *client;
+ unsigned int depth;
};
#define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
@@ -343,6 +356,7 @@ typedef struct {
struct dns_fetch {
unsigned int magic;
+ isc_mem_t * mctx;
fetchctx_t * private;
};
@@ -418,6 +432,8 @@ struct dns_resolver {
isc_timer_t * spillattimer;
isc_boolean_t zero_no_soa_ttl;
unsigned int query_timeout;
+ unsigned int maxdepth;
+ unsigned int maxqueries;
/* Locked by lock. */
unsigned int references;
@@ -449,12 +465,16 @@ struct dns_resolver {
#define FCTX_ADDRINFO_MARK 0x0001
#define FCTX_ADDRINFO_FORWARDER 0x1000
#define FCTX_ADDRINFO_TRIED 0x2000
+#define FCTX_ADDRINFO_EDNSOK 0x4000
+
#define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
== 0)
#define ISFORWARDER(a) (((a)->flags & \
FCTX_ADDRINFO_FORWARDER) != 0)
#define TRIED(a) (((a)->flags & \
FCTX_ADDRINFO_TRIED) != 0)
+#define EDNSOK(a) (((a)->flags & \
+ FCTX_ADDRINFO_EDNSOK) != 0)
#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
@@ -792,6 +812,7 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
dns_adbfind_t *find;
dns_adbaddrinfo_t *addrinfo;
isc_socket_t *socket;
+ isc_stdtime_t now;
query = *queryp;
fctx = query->fctx;
@@ -862,14 +883,13 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
/*
* Age RTTs of servers not tried.
*/
- factor = DNS_ADB_RTTADJAGE;
+ isc_stdtime_get(&now);
if (finish != NULL)
for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
addrinfo != NULL;
addrinfo = ISC_LIST_NEXT(addrinfo, publink))
if (UNMARKED(addrinfo))
- dns_adb_adjustsrtt(fctx->adb, addrinfo,
- 0, factor);
+ dns_adb_agesrtt(fctx->adb, addrinfo, now);
if (finish != NULL && TRIEDFIND(fctx))
for (find = ISC_LIST_HEAD(fctx->finds);
@@ -879,16 +899,15 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
addrinfo != NULL;
addrinfo = ISC_LIST_NEXT(addrinfo, publink))
if (UNMARKED(addrinfo))
- dns_adb_adjustsrtt(fctx->adb, addrinfo,
- 0, factor);
+ dns_adb_agesrtt(fctx->adb, addrinfo,
+ now);
if (finish != NULL && TRIEDALT(fctx)) {
for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
addrinfo != NULL;
addrinfo = ISC_LIST_NEXT(addrinfo, publink))
if (UNMARKED(addrinfo))
- dns_adb_adjustsrtt(fctx->adb, addrinfo,
- 0, factor);
+ dns_adb_agesrtt(fctx->adb, addrinfo, now);
for (find = ISC_LIST_HEAD(fctx->altfinds);
find != NULL;
find = ISC_LIST_NEXT(find, publink))
@@ -896,8 +915,8 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
addrinfo != NULL;
addrinfo = ISC_LIST_NEXT(addrinfo, publink))
if (UNMARKED(addrinfo))
- dns_adb_adjustsrtt(fctx->adb, addrinfo,
- 0, factor);
+ dns_adb_agesrtt(fctx->adb, addrinfo,
+ now);
}
/*
@@ -1533,6 +1552,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
if (result != ISC_R_SUCCESS)
goto cleanup_dispatch;
}
+
fctx->querysent++;
ISC_LIST_APPEND(fctx->queries, query, link);
@@ -1674,7 +1694,7 @@ resquery_send(resquery_t *query) {
isc_boolean_t cleanup_cctx = ISC_FALSE;
isc_boolean_t secure_domain;
isc_boolean_t connecting = ISC_FALSE;
- dns_ednsopt_t ednsopts[EDNSOPTS];
+ dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
unsigned ednsopt = 0;
fctx = query->fctx;
@@ -1821,12 +1841,12 @@ resquery_send(resquery_t *query) {
if (fctx->timeout) {
if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
- (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
- query->options |= DNS_FETCHOPT_NOEDNS0;
- fctx->reason = "disabling EDNS";
+ (query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
+ !EDNSOK(query->addrinfo)) {
} else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
- (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
+ (query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
+ !EDNSOK(query->addrinfo)) {
query->options |= DNS_FETCHOPT_EDNS512;
fctx->reason = "reducing the advertised EDNS UDP "
"packet size to 512 octets";
@@ -1859,12 +1879,13 @@ resquery_send(resquery_t *query) {
if (peer != NULL)
(void) dns_peer_getrequestnsid(peer, &reqnsid);
if (reqnsid) {
- INSIST(ednsopt < EDNSOPTS);
+ INSIST(ednsopt < DNS_EDNSOPTIONS);
ednsopts[ednsopt].code = DNS_OPT_NSID;
ednsopts[ednsopt].length = 0;
ednsopts[ednsopt].value = NULL;
ednsopt++;
}
+ query->ednsversion = version;
result = fctx_addopt(fctx->qmessage, version,
udpsize, ednsopts, ednsopt);
if (reqnsid && result == ISC_R_SUCCESS) {
@@ -1876,6 +1897,7 @@ resquery_send(resquery_t *query) {
* bit.
*/
query->options |= DNS_FETCHOPT_NOEDNS0;
+ query->ednsversion = -1;
}
} else {
/*
@@ -1884,8 +1906,10 @@ resquery_send(resquery_t *query) {
* not using EDNS0.
*/
query->options |= DNS_FETCHOPT_NOEDNS0;
+ query->ednsversion = -1;
}
- }
+ } else
+ query->ednsversion = -1;
/*
* If we need EDNS0 to do this query and aren't using it, we lose.
@@ -2186,9 +2210,9 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
*/
INSIST(!SHUTTINGDOWN(fctx));
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
- if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)
+ if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) {
want_try = ISC_TRUE;
- else {
+ } else {
fctx->findfail++;
if (fctx->pending == 0) {
/*
@@ -2217,7 +2241,7 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
else if (want_done)
fctx_done(fctx, ISC_R_FAILURE, __LINE__);
else if (destroy) {
- fctx_destroy(fctx);
+ fctx_destroy(fctx);
if (bucket_empty)
empty_bucket(res);
}
@@ -2471,12 +2495,13 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
* See what we know about this address.
*/
find = NULL;
- result = dns_adb_createfind(fctx->adb,
- res->buckets[fctx->bucketnum].task,
- fctx_finddone, fctx, name,
- &fctx->name, fctx->type,
- options, now, NULL,
- res->view->dstport, &find);
+ result = dns_adb_createfind2(fctx->adb,
+ res->buckets[fctx->bucketnum].task,
+ fctx_finddone, fctx, name,
+ &fctx->name, fctx->type,
+ options, now, NULL,
+ res->view->dstport,
+ fctx->depth + 1, fctx->qc, &find);
if (result != ISC_R_SUCCESS) {
if (result == DNS_R_ALIAS) {
/*
@@ -2584,6 +2609,14 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
res = fctx->res;
+ if (fctx->depth > res->maxdepth) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
+ "too much NS indirection resolving '%s'",
+ fctx->info);
+ return (DNS_R_SERVFAIL);
+ }
+
/*
* Forwarders.
*/
@@ -3059,6 +3092,16 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
}
}
+ result = isc_counter_increment(fctx->qc);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
+ "exceeded max queries resolving '%s'",
+ fctx->info);
+ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ return;
+ }
+
result = fctx_query(fctx, addrinfo, fctx->options);
if (result != ISC_R_SUCCESS)
fctx_done(fctx, result, __LINE__);
@@ -3157,6 +3200,7 @@ fctx_destroy(fetchctx_t *fctx) {
isc_mem_put(fctx->mctx, sa, sizeof(*sa));
}
+ isc_counter_detach(&fctx->qc);
isc_timer_detach(&fctx->timer);
dns_message_destroy(&fctx->rmessage);
dns_message_destroy(&fctx->qmessage);
@@ -3485,7 +3529,8 @@ log_ns_ttl(fetchctx_t *fctx, const char *where) {
static isc_result_t
fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
dns_name_t *domain, dns_rdataset_t *nameservers,
- unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp)
+ unsigned int options, unsigned int bucketnum, unsigned int depth,
+ isc_counter_t *qc, fetchctx_t **fctxp)
{
fetchctx_t *fctx;
isc_result_t result;
@@ -3507,6 +3552,21 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
fctx = isc_mem_get(mctx, sizeof(*fctx));
if (fctx == NULL)
return (ISC_R_NOMEMORY);
+
+ fctx->qc = NULL;
+ if (qc != NULL) {
+ isc_counter_attach(qc, &fctx->qc);
+ } else {
+ result = isc_counter_create(res->mctx,
+ res->maxqueries, &fctx->qc);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_fetch;
+ }
+
+ /*
+ * Make fctx->info point to a copy of a formatted string
+ * "name/type".
+ */
dns_name_format(name, buf, sizeof(buf));
dns_rdatatype_format(type, typebuf, sizeof(typebuf));
strcat(buf, "/"); /* checked */
@@ -3514,7 +3574,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
fctx->info = isc_mem_strdup(mctx, buf);
if (fctx->info == NULL) {
result = ISC_R_NOMEMORY;
- goto cleanup_fetch;
+ goto cleanup_counter;
}
FCTXTRACE("create");
dns_name_init(&fctx->name, NULL);
@@ -3537,6 +3597,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
fctx->state = fetchstate_init;
fctx->want_shutdown = ISC_FALSE;
fctx->cloned = ISC_FALSE;
+ fctx->depth = depth;
ISC_LIST_INIT(fctx->queries);
ISC_LIST_INIT(fctx->finds);
ISC_LIST_INIT(fctx->altfinds);
@@ -3615,7 +3676,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
*/
if (dns_rdatatype_atparent(fctx->type))
findoptions |= DNS_DBFIND_NOEXACT;
- result = dns_view_findzonecut(res->view, fwdname,
+ result = dns_view_findzonecut(res->view, name,
domain, 0, findoptions,
ISC_TRUE,
&fctx->nameservers,
@@ -3744,6 +3805,9 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
cleanup_info:
isc_mem_free(mctx, fctx->info);
+ cleanup_counter:
+ isc_counter_detach(&fctx->qc);
+
cleanup_fetch:
isc_mem_put(mctx, fctx, sizeof(*fctx));
@@ -4008,6 +4072,7 @@ validated(isc_task_t *task, isc_event_t *event) {
isc_result_t result = ISC_R_SUCCESS;
isc_stdtime_t now;
isc_uint32_t ttl;
+ isc_uint32_t bucketnum;
UNUSED(task); /* for now */
@@ -4024,7 +4089,8 @@ validated(isc_task_t *task, isc_event_t *event) {
FCTXTRACE("received validation completion event");
- LOCK(&res->buckets[fctx->bucketnum].lock);
+ bucketnum = fctx->bucketnum;
+ LOCK(&res->buckets[bucketnum].lock);
ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
fctx->validator = NULL;
@@ -4046,7 +4112,6 @@ validated(isc_task_t *task, isc_event_t *event) {
* so, destroy the fctx.
*/
if (SHUTTINGDOWN(fctx) && !sentresponse) {
- isc_uint32_t bucketnum = fctx->bucketnum;
isc_boolean_t bucket_empty;
bucket_empty = maybe_destroy(fctx, ISC_TRUE);
UNLOCK(&res->buckets[bucketnum].lock);
@@ -4149,7 +4214,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(&res->buckets[fctx->bucketnum].lock);
+ UNLOCK(&res->buckets[bucketnum].lock);
INSIST(fctx->validator == NULL);
fctx->validator = ISC_LIST_HEAD(fctx->validators);
if (fctx->validator != NULL)
@@ -4277,7 +4342,7 @@ validated(isc_task_t *task, isc_event_t *event) {
dns_db_detachnode(fctx->cache, &node);
if (SHUTTINGDOWN(fctx))
bucket_empty = maybe_destroy(fctx, ISC_TRUE);
- UNLOCK(&res->buckets[fctx->bucketnum].lock);
+ UNLOCK(&res->buckets[bucketnum].lock);
if (bucket_empty)
empty_bucket(res);
goto cleanup_event;
@@ -4294,7 +4359,7 @@ validated(isc_task_t *task, isc_event_t *event) {
* be validated.
*/
dns_db_detachnode(fctx->cache, &node);
- UNLOCK(&res->buckets[fctx->bucketnum].lock);
+ UNLOCK(&res->buckets[bucketnum].lock);
dns_validator_send(ISC_LIST_HEAD(fctx->validators));
goto cleanup_event;
}
@@ -4377,7 +4442,7 @@ validated(isc_task_t *task, isc_event_t *event) {
if (node != NULL)
dns_db_detachnode(fctx->cache, &node);
- UNLOCK(&res->buckets[fctx->bucketnum].lock);
+ UNLOCK(&res->buckets[bucketnum].lock);
fctx_done(fctx, result, __LINE__); /* Locks bucket. */
cleanup_event:
@@ -4913,10 +4978,17 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
}
}
- if (valrdataset != NULL)
- result = valcreate(fctx, addrinfo, name, fctx->type,
- valrdataset, valsigrdataset, valoptions,
- task);
+ if (valrdataset != NULL) {
+ dns_rdatatype_t vtype = fctx->type;
+ if (CHAINING(valrdataset)) {
+ if (valrdataset->type == dns_rdatatype_cname)
+ vtype = dns_rdatatype_cname;
+ else
+ vtype = dns_rdatatype_dname;
+ }
+ result = valcreate(fctx, addrinfo, name, vtype, valrdataset,
+ valsigrdataset, valoptions, task);
+ }
if (result == ISC_R_SUCCESS && have_answer) {
fctx->attributes |= FCTX_ATTR_HAVEANSWER;
@@ -5657,7 +5729,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
char qbuf[DNS_NAME_FORMATSIZE];
char nbuf[DNS_NAME_FORMATSIZE];
char tbuf[DNS_RDATATYPE_FORMATSIZE];
- dns_rdatatype_format(fctx->type, tbuf,
+ dns_rdatatype_format(type, tbuf,
sizeof(tbuf));
dns_name_format(name, nbuf,
sizeof(nbuf));
@@ -5666,8 +5738,8 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
log_formerr(fctx,
"unrelated %s %s in "
"%s authority section",
- tbuf, qbuf, nbuf);
- return (DNS_R_FORMERR);
+ tbuf, nbuf, qbuf);
+ goto nextname;
}
if (type == dns_rdatatype_ns) {
/*
@@ -5730,6 +5802,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
}
}
}
+ nextname:
result = dns_message_nextname(message, section);
if (result == ISC_R_NOMORE)
break;
@@ -7015,21 +7088,33 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* EDNS may not be supported so we can now cache the lack of
* EDNS support.
*/
- if (opt == NULL &&
+ if (opt == NULL && !EDNSOK(query->addrinfo) &&
(message->rcode == dns_rcode_noerror ||
message->rcode == dns_rcode_nxdomain ||
message->rcode == dns_rcode_refused ||
message->rcode == dns_rcode_yxdomain) &&
bad_edns(fctx, &query->addrinfo->sockaddr)) {
- char addrbuf[ISC_SOCKADDR_FORMATSIZE];
- isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
- sizeof(addrbuf));
dns_adb_changeflags(fctx->adb, query->addrinfo,
DNS_FETCHOPT_NOEDNS0,
DNS_FETCHOPT_NOEDNS0);
}
/*
+ * If we get a non error EDNS response record the fact so we
+ * won't fallback to plain DNS in the future for this server.
+ */
+ if (opt != NULL && !EDNSOK(query->addrinfo) &&
+ (query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
+ (message->rcode == dns_rcode_noerror ||
+ message->rcode == dns_rcode_nxdomain ||
+ message->rcode == dns_rcode_refused ||
+ message->rcode == dns_rcode_yxdomain)) {
+ dns_adb_changeflags(fctx->adb, query->addrinfo,
+ FCTX_ADDRINFO_EDNSOK,
+ FCTX_ADDRINFO_EDNSOK);
+ }
+
+ /*
* Deal with truncated responses by retrying using TCP.
*/
if ((message->flags & DNS_MESSAGEFLAG_TC) != 0)
@@ -7143,6 +7228,18 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
DNS_FETCHOPT_EDNSVERSIONSET;
mask = DNS_FETCHOPT_EDNSVERSIONMASK |
DNS_FETCHOPT_EDNSVERSIONSET;
+ /*
+ * Record that we got a good EDNS response.
+ */
+ if (query->ednsversion > (int)version &&
+ !EDNSOK(query->addrinfo)) {
+ dns_adb_changeflags(fctx->adb, query->addrinfo,
+ FCTX_ADDRINFO_EDNSOK,
+ FCTX_ADDRINFO_EDNSOK);
+ }
+ /*
+ * Record the supported EDNS version.
+ */
switch (version) {
case 0:
dns_adb_changeflags(fctx->adb, query->addrinfo,
@@ -7731,6 +7828,8 @@ dns_resolver_create(dns_view_t *view,
res->spillattimer = NULL;
res->zero_no_soa_ttl = ISC_FALSE;
res->query_timeout = DEFAULT_QUERY_TIMEOUT;
+ res->maxdepth = DEFAULT_RECURSION_DEPTH;
+ res->maxqueries = DEFAULT_MAX_QUERIES;
res->nbuckets = ntasks;
res->activebuckets = ntasks;
res->buckets = isc_mem_get(view->mctx,
@@ -8169,9 +8268,9 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
dns_rdataset_t *sigrdataset,
dns_fetch_t **fetchp)
{
- return (dns_resolver_createfetch2(res, name, type, domain,
+ return (dns_resolver_createfetch3(res, name, type, domain,
nameservers, forwarders, NULL, 0,
- options, task, action, arg,
+ options, 0, NULL, task, action, arg,
rdataset, sigrdataset, fetchp));
}
@@ -8187,6 +8286,25 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
dns_rdataset_t *sigrdataset,
dns_fetch_t **fetchp)
{
+ return (dns_resolver_createfetch3(res, name, type, domain,
+ nameservers, forwarders, client, id,
+ options, 0, NULL, task, action, arg,
+ rdataset, sigrdataset, fetchp));
+}
+
+isc_result_t
+dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_name_t *domain, dns_rdataset_t *nameservers,
+ dns_forwarders_t *forwarders,
+ isc_sockaddr_t *client, dns_messageid_t id,
+ unsigned int options, unsigned int depth,
+ isc_counter_t *qc, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset,
+ dns_fetch_t **fetchp)
+{
dns_fetch_t *fetch;
fetchctx_t *fctx = NULL;
isc_result_t result = ISC_R_SUCCESS;
@@ -8222,6 +8340,8 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
fetch = isc_mem_get(res->mctx, sizeof(*fetch));
if (fetch == NULL)
return (ISC_R_NOMEMORY);
+ fetch->mctx = NULL;
+ isc_mem_attach(res->mctx, &fetch->mctx);
bucketnum = dns_name_fullhash(name, ISC_FALSE) % res->nbuckets;
@@ -8273,11 +8393,12 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
if (fctx == NULL) {
result = fctx_create(res, name, type, domain, nameservers,
- options, bucketnum, &fctx);
+ options, bucketnum, depth, qc, &fctx);
if (result != ISC_R_SUCCESS)
goto unlock;
new_fctx = ISC_TRUE;
- }
+ } else if (fctx->depth > depth)
+ fctx->depth = depth;
result = fctx_join(fctx, task, client, id, action, arg,
rdataset, sigrdataset, fetch);
@@ -8312,7 +8433,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
FTRACE("created");
*fetchp = fetch;
} else
- isc_mem_put(res->mctx, fetch, sizeof(*fetch));
+ isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch));
return (result);
}
@@ -8403,7 +8524,7 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
UNLOCK(&res->buckets[bucketnum].lock);
- isc_mem_put(res->mctx, fetch, sizeof(*fetch));
+ isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch));
*fetchp = NULL;
if (bucket_empty)
@@ -9049,3 +9170,27 @@ dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds) {
resolver->query_timeout = seconds;
}
+
+void
+dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ resolver->maxdepth = maxdepth;
+}
+
+unsigned int
+dns_resolver_getmaxdepth(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ return (resolver->maxdepth);
+}
+
+void
+dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ resolver->maxqueries = queries;
+}
+
+unsigned int
+dns_resolver_getmaxqueries(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ return (resolver->maxqueries);
+}
diff --git a/lib/dns/rootns.c b/lib/dns/rootns.c
index 34971788dd89..a3d9bd8d6084 100644
--- a/lib/dns/rootns.c
+++ b/lib/dns/rootns.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2008, 2010, 2012, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008, 2010, 2012-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -63,6 +63,7 @@ static char root_ns[] =
"A.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:BA3E::2:30\n"
"B.ROOT-SERVERS.NET. 3600000 IN A 192.228.79.201\n"
"C.ROOT-SERVERS.NET. 3600000 IN A 192.33.4.12\n"
+"C.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2::c\n"
"D.ROOT-SERVERS.NET. 3600000 IN A 199.7.91.13\n"
"D.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2d::d\n"
"E.ROOT-SERVERS.NET. 3600000 IN A 192.203.230.10\n"
diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c
index f617fe7b7c6a..3dd80664c7dc 100644
--- a/lib/dns/rpz.c
+++ b/lib/dns/rpz.c
@@ -496,16 +496,16 @@ ip2name(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *tgt_ip,
}
if (canon_name != NULL) {
- isc__buffer_init(&buffer, str, sizeof(str));
- isc__buffer_add(&buffer, len);
+ isc_buffer_init(&buffer, str, sizeof(str));
+ isc_buffer_add(&buffer, len);
result = dns_name_fromtext(canon_name, &buffer,
dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS)
return (result);
}
if (search_name != NULL) {
- isc__buffer_init(&buffer, str, sizeof(str));
- isc__buffer_add(&buffer, len);
+ isc_buffer_init(&buffer, str, sizeof(str));
+ isc_buffer_add(&buffer, len);
if (type == DNS_RPZ_TYPE_NSIP)
name = &cidr->nsip_name;
else
diff --git a/lib/dns/rrl.c b/lib/dns/rrl.c
index 02554e9a9dfb..08fc8e712ffa 100644
--- a/lib/dns/rrl.c
+++ b/lib/dns/rrl.c
@@ -253,6 +253,7 @@ expand_entries(dns_rrl_t *rrl, int new) {
static inline dns_rrl_bin_t *
get_bin(dns_rrl_hash_t *hash, unsigned int hval) {
+ INSIST(hash != NULL);
return (&hash->bins[hval % hash->length]);
}
diff --git a/lib/dns/time.c b/lib/dns/time.c
index d331ca3bfe10..5dce07281195 100644
--- a/lib/dns/time.c
+++ b/lib/dns/time.c
@@ -35,7 +35,7 @@
#include <dns/result.h>
#include <dns/time.h>
-static int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static const int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
isc_result_t
dns_time64_totext(isc_int64_t t, isc_buffer_t *target) {
@@ -161,6 +161,14 @@ dns_time64_fromtext(const char *source, isc_int64_t *target) {
RANGE(1, 12, month);
RANGE(1, days[month - 1] +
((month == 2 && is_leap(year)) ? 1 : 0), day);
+#ifdef __COVERITY__
+ /*
+ * Use a simplified range to silence Coverity warning (in
+ * arithmetic with day below).
+ */
+ RANGE(1, 31, day);
+#endif /* __COVERITY__ */
+
RANGE(0, 23, hour);
RANGE(0, 59, minute);
RANGE(0, 60, second); /* 60 == leap second. */
diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c
index 00ab570d9e34..1ddca181a4ab 100644
--- a/lib/dns/tsig.c
+++ b/lib/dns/tsig.c
@@ -1317,7 +1317,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) {
isc_uint16_t digestbits = dst_key_getbits(key);
if (tsig.siglen > siglen) {
- tsig_log(msg->tsigkey, 2, "signature length to big");
+ tsig_log(msg->tsigkey, 2, "signature length too big");
return (DNS_R_FORMERR);
}
if (tsig.siglen > 0 &&
diff --git a/lib/dns/validator.c b/lib/dns/validator.c
index d7982caa777a..0b203d882923 100644
--- a/lib/dns/validator.c
+++ b/lib/dns/validator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -343,7 +343,7 @@ isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
dns_name_getlabel(&nsec3name, 0, &hashlabel);
isc_region_consume(&hashlabel, 1);
isc_buffer_init(&buffer, owner, sizeof(owner));
- result = isc_base32hex_decoderegion(&hashlabel, &buffer);
+ result = isc_base32hexnp_decoderegion(&hashlabel, &buffer);
if (result != ISC_R_SUCCESS) {
dns_rdataset_disassociate(&set);
continue;
@@ -918,12 +918,26 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
devent->name;
}
if (!exists) {
+ dns_name_t *closest;
+ unsigned int clabels;
+
val->attributes |= VALATTR_FOUNDNOQNAME;
- val->attributes |= VALATTR_FOUNDCLOSEST;
+
+ closest = dns_fixedname_name(&val->closest);
+ clabels = dns_name_countlabels(closest);
+ /*
+ * If we are validating a wildcard response
+ * clabels will not be zero. We then need
+ * to check if the generated wilcard from
+ * dns_nsec_noexistnodata is consistent with
+ * the wildcard used to generate the response.
+ */
+ if (clabels == 0 ||
+ dns_name_countlabels(wild) == clabels + 1)
+ val->attributes |= VALATTR_FOUNDCLOSEST;
/*
* The NSEC noqname proof also contains
* the closest encloser.
-
*/
if (NEEDNOQNAME(val))
proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
@@ -2803,7 +2817,8 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
if (!FOUNDNOQNAME(val))
findnsec3proofs(val);
- if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val)) {
+ if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
+ !FOUNDOPTOUT(val)) {
validator_log(val, ISC_LOG_DEBUG(3),
"marking as secure, noqname proof found");
marksecure(val->event);
diff --git a/lib/dns/view.c b/lib/dns/view.c
index 142b09edbd74..3730593b9e37 100644
--- a/lib/dns/view.c
+++ b/lib/dns/view.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -182,6 +182,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->updateacl = NULL;
view->upfwdacl = NULL;
view->denyansweracl = NULL;
+ view->nocasecompress = NULL;
view->answeracl_exclude = NULL;
view->denyanswernames = NULL;
view->answernames_exclude = NULL;
@@ -359,6 +360,8 @@ destroy(dns_view_t *view) {
dns_db_detach(&view->cachedb);
if (view->cache != NULL)
dns_cache_detach(&view->cache);
+ if (view->nocasecompress != NULL)
+ dns_acl_detach(&view->nocasecompress);
if (view->matchclients != NULL)
dns_acl_detach(&view->matchclients);
if (view->matchdestinations != NULL)
@@ -621,6 +624,8 @@ resolver_shutdown(isc_task_t *task, isc_event_t *event) {
UNUSED(task);
+ isc_event_free(&event);
+
LOCK(&view->lock);
view->attributes |= DNS_VIEWATTR_RESSHUTDOWN;
@@ -628,8 +633,6 @@ resolver_shutdown(isc_task_t *task, isc_event_t *event) {
UNLOCK(&view->lock);
- isc_event_free(&event);
-
if (done)
destroy(view);
}
@@ -645,6 +648,8 @@ adb_shutdown(isc_task_t *task, isc_event_t *event) {
UNUSED(task);
+ isc_event_free(&event);
+
LOCK(&view->lock);
view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN;
@@ -652,8 +657,6 @@ adb_shutdown(isc_task_t *task, isc_event_t *event) {
UNLOCK(&view->lock);
- isc_event_free(&event);
-
if (done)
destroy(view);
}
@@ -669,6 +672,8 @@ req_shutdown(isc_task_t *task, isc_event_t *event) {
UNUSED(task);
+ isc_event_free(&event);
+
LOCK(&view->lock);
view->attributes |= DNS_VIEWATTR_REQSHUTDOWN;
@@ -676,8 +681,6 @@ req_shutdown(isc_task_t *task, isc_event_t *event) {
UNLOCK(&view->lock);
- isc_event_free(&event);
-
if (done)
destroy(view);
}
@@ -1216,6 +1219,9 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
dns_name_t *zfname;
dns_rdataset_t zrdataset, zsigrdataset;
dns_fixedname_t zfixedname;
+#ifdef BIND9
+ unsigned int ztoptions = 0;
+#endif
#ifndef BIND9
UNUSED(zone);
@@ -1242,9 +1248,12 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
#ifdef BIND9
zone = NULL;
LOCK(&view->lock);
- if (view->zonetable != NULL)
- result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
- else
+ if (view->zonetable != NULL) {
+ if ((options & DNS_DBFIND_NOEXACT) != 0)
+ ztoptions |= DNS_ZTFIND_NOEXACT;
+ result = dns_zt_find(view->zonetable, name, ztoptions,
+ NULL, &zone);
+ } else
result = ISC_R_NOTFOUND;
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
result = dns_zone_getdb(zone, &db);
@@ -1461,7 +1470,7 @@ dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name,
if (zone2 != NULL) {
dns_zone_detach(&zone1);
dns_zone_detach(&zone2);
- return (ISC_R_NOTFOUND);
+ return (ISC_R_MULTIPLE);
}
}
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 01ff97b11dcb..7a9825bd96b0 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -2639,8 +2639,8 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
checkspf:
/*
- * Check if there is a type TXT spf record without a type SPF
- * RRset being present.
+ * Check if there is a type SPF record without an
+ * SPF-formatted type TXT record also being present.
*/
if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
goto next;
@@ -2669,16 +2669,13 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
dns_rdataset_disassociate(&rdataset);
notxt:
- if (have_spf != have_txt) {
+ if (have_spf && !have_txt) {
char namebuf[DNS_NAME_FORMATSIZE];
- const char *found = have_txt ? "TXT" : "SPF";
- const char *need = have_txt ? "SPF" : "TXT";
dns_name_format(name, namebuf, sizeof(namebuf));
- dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found SPF/%s "
- "record but no SPF/%s record found, add "
- "matching type %s record", namebuf, found,
- need, need);
+ dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type "
+ "SPF record but no SPF TXT record found, "
+ "add matching type TXT record", namebuf);
}
next:
@@ -4567,6 +4564,21 @@ zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
dns_db_currentversion(db, &version);
+ if (nscount != NULL)
+ *nscount = 0;
+ if (soacount != NULL)
+ *soacount = 0;
+ if (serial != NULL)
+ *serial = 0;
+ if (refresh != NULL)
+ *refresh = 0;
+ if (retry != NULL)
+ *retry = 0;
+ if (expire != NULL)
+ *expire = 0;
+ if (errors != NULL)
+ *errors = 0;
+
node = NULL;
result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
if (result != ISC_R_SUCCESS) {
@@ -8544,8 +8556,10 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
trust_key(zone, keyname, &dnskey, mctx);
}
- if (!deletekey)
+ if (!deletekey) {
+ INSIST(newkey || updatekey);
set_refreshkeytimer(zone, &keydata, now);
+ }
}
/*
@@ -10933,70 +10947,25 @@ create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
static isc_result_t
add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
- dns_rdataset_t *rdataset = NULL;
- dns_rdatalist_t *rdatalist = NULL;
- dns_rdata_t *rdata = NULL;
isc_result_t result;
-
- result = dns_message_gettemprdatalist(message, &rdatalist);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
- result = dns_message_gettemprdata(message, &rdata);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
- result = dns_message_gettemprdataset(message, &rdataset);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
- dns_rdataset_init(rdataset);
-
- rdatalist->type = dns_rdatatype_opt;
- rdatalist->covers = 0;
-
- /*
- * Set Maximum UDP buffer size.
- */
- rdatalist->rdclass = udpsize;
-
- /*
- * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
- */
- rdatalist->ttl = 0;
+ dns_rdataset_t *rdataset = NULL;
+ dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
+ int count = 0;
/* Set EDNS options if applicable */
if (reqnsid) {
- unsigned char data[4];
- isc_buffer_t buf;
-
- isc_buffer_init(&buf, data, sizeof(data));
- isc_buffer_putuint16(&buf, DNS_OPT_NSID);
- isc_buffer_putuint16(&buf, 0);
- rdata->data = data;
- rdata->length = sizeof(data);
- } else {
- rdata->data = NULL;
- rdata->length = 0;
+ INSIST(count < DNS_EDNSOPTIONS);
+ ednsopts[count].code = DNS_OPT_NSID;
+ ednsopts[count].length = 0;
+ ednsopts[count].value = NULL;
+ count++;
}
-
- rdata->rdclass = rdatalist->rdclass;
- rdata->type = rdatalist->type;
- rdata->flags = 0;
-
- ISC_LIST_INIT(rdatalist->rdata);
- ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
- RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
- == ISC_R_SUCCESS);
+ result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
+ ednsopts, count);
+ if (result != ISC_R_SUCCESS)
+ return (result);
return (dns_message_setopt(message, rdataset));
-
- cleanup:
- if (rdatalist != NULL)
- dns_message_puttemprdatalist(message, &rdatalist);
- if (rdataset != NULL)
- dns_message_puttemprdataset(message, &rdataset);
- if (rdata != NULL)
- dns_message_puttemprdata(message, &rdata);
-
- return (result);
}
static void
@@ -11846,6 +11815,8 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
int match = 0;
isc_netaddr_t netaddr;
isc_sockaddr_t local, remote;
+ dns_tsigkey_t *tsigkey;
+ dns_name_t *tsig;
REQUIRE(DNS_ZONE_VALID(zone));
@@ -11930,8 +11901,10 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
* Accept notify requests from non masters if they are on
* 'zone->notify_acl'.
*/
+ tsigkey = dns_message_gettsigkey(msg);
+ tsig = dns_tsigkey_identity(tsigkey);
if (i >= zone->masterscnt && zone->notify_acl != NULL &&
- dns_acl_match(&netaddr, NULL, zone->notify_acl,
+ dns_acl_match(&netaddr, tsig, zone->notify_acl,
&zone->view->aclenv,
&match, NULL) == ISC_R_SUCCESS &&
match > 0)
@@ -13048,7 +13021,6 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
isc_result_t result;
dns_dbnode_t *node = NULL;
dns_rdataset_t rdataset, prdataset;
- dns_rdata_t rdata_in, prdata_in, prdata_out;
dns_dbversion_t *version = NULL;
nsec3param_t *nsec3param = NULL;
nsec3param_t *nsec3p = NULL;
@@ -13060,10 +13032,12 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
REQUIRE(nsec3list != NULL);
REQUIRE(ISC_LIST_EMPTY(*nsec3list));
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&prdataset);
+
dns_db_attach(zone->db, &db);
CHECK(dns_db_getoriginnode(db, &node));
- dns_rdataset_init(&rdataset);
dns_db_currentversion(db, &version);
result = dns_db_findrdataset(db, node, version,
dns_rdatatype_nsec3param,
@@ -13082,8 +13056,10 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset))
{
- dns_rdata_init(&rdata_in);
- dns_rdataset_current(&rdataset, &rdata_in);
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_t private = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&rdataset, &rdata);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
"looping through nsec3param data");
@@ -13096,16 +13072,14 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
* now transfer the data from the rdata to
* the nsec3param
*/
- dns_rdata_init(&prdata_out);
- dns_nsec3param_toprivate(&rdata_in, &prdata_out,
+ dns_nsec3param_toprivate(&rdata, &private,
zone->privatetype, nsec3param->data,
sizeof(nsec3param->data));
- nsec3param->length = prdata_out.length;
+ nsec3param->length = private.length;
ISC_LIST_APPEND(*nsec3list, nsec3param, link);
}
getprivate:
- dns_rdataset_init(&prdataset);
result = dns_db_findrdataset(db, node, version, zone->privatetype,
dns_rdatatype_none, 0, &prdataset, NULL);
if (result != ISC_R_SUCCESS)
@@ -13120,26 +13094,39 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&prdataset))
{
- dns_rdata_init(&prdata_in);
- dns_rdataset_current(&prdataset, &prdata_in);
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_t private = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&prdataset, &private);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
"looping through nsec3param private data");
- if (!dns_nsec3param_fromprivate(&prdata_in, &prdata_out,
+ /*
+ * Do we have a valid private record?
+ */
+ if (!dns_nsec3param_fromprivate(&private, &rdata,
buf, sizeof(buf)))
continue;
- if ((prdata_out.data[1] & DNS_NSEC3FLAG_REMOVE) !=0) {
- prdata_out.data[1] = 0;
+ /*
+ * Remove any NSEC3PARAM records scheduled to be removed.
+ */
+ if (NSEC3REMOVE(rdata.data[1])) {
+ /*
+ * Zero out the flags.
+ */
+ rdata.data[1] = 0;
for (nsec3p = ISC_LIST_HEAD(*nsec3list);
nsec3p != NULL;
nsec3p = next)
{
next = ISC_LIST_NEXT(nsec3p, link);
- if (memcmp(prdata_out.data, nsec3p->data,
- sizeof(nsec3p->data)) == 0) {
+
+ if (nsec3p->length == rdata.length + 1 &&
+ memcmp(rdata.data, nsec3p->data + 1,
+ nsec3p->length - 1) == 0) {
ISC_LIST_UNLINK(*nsec3list,
nsec3p, link);
isc_mem_put(zone->mctx, nsec3p,
@@ -13154,11 +13141,13 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
CHECK(ISC_R_NOMEMORY);
ISC_LINK_INIT(nsec3param, link);
- dns_rdata_init(&prdata_out);
- dns_nsec3param_toprivate(&prdata_in, &prdata_out,
- zone->privatetype, nsec3param->data,
- sizeof(nsec3param->data));
- nsec3param->length = prdata_out.length;
+ /*
+ * Copy the remaining private records so the nsec/nsec3
+ * chain gets created.
+ */
+ INSIST(private.length <= sizeof(nsec3param->data));
+ memmove(nsec3param->data, private.data, private.length);
+ nsec3param->length = private.length;
ISC_LIST_APPEND(*nsec3list, nsec3param, link);
}
@@ -13374,6 +13363,12 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) {
dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
dns_result_totext(result));
+ while (!ISC_LIST_EMPTY(nsec3list)) {
+ nsec3param_t *nsec3p;
+ nsec3p = ISC_LIST_HEAD(nsec3list);
+ ISC_LIST_UNLINK(nsec3list, nsec3p, link);
+ isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
+ }
if (dns_rdataset_isassociated(&rdataset))
dns_rdataset_disassociate(&rdataset);
if (db != NULL) {
@@ -13493,7 +13488,6 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
{
isc_uint32_t serial, oldserial;
- unsigned int soacount;
dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
@@ -15691,10 +15685,12 @@ dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
REQUIRE(DNS_ZONE_VALID(zone));
- if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
+ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
+ rdata->type != dns_rdatatype_nsec3)
return (ISC_R_SUCCESS);
- if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
+ rdata->type == dns_rdatatype_nsec3) {
level = ISC_LOG_ERROR;
fail = ISC_TRUE;
}