summaryrefslogtreecommitdiff
path: root/lib/dns
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns')
-rw-r--r--lib/dns/Makefile.in12
-rw-r--r--lib/dns/acache.c3
-rw-r--r--lib/dns/acl.c6
-rw-r--r--lib/dns/adb.c6
-rw-r--r--lib/dns/api6
-rw-r--r--lib/dns/client.c80
-rw-r--r--lib/dns/diff.c15
-rw-r--r--lib/dns/dispatch.c47
-rw-r--r--lib/dns/dns64.c16
-rw-r--r--lib/dns/dnssec.c117
-rw-r--r--lib/dns/dst_api.c27
-rw-r--r--lib/dns/dst_internal.h5
-rw-r--r--lib/dns/dst_parse.c64
-rw-r--r--lib/dns/dst_result.c4
-rw-r--r--lib/dns/gen.c13
-rw-r--r--lib/dns/gssapi_link.c14
-rw-r--r--lib/dns/gssapictx.c40
-rw-r--r--lib/dns/hmac_link.c45
-rw-r--r--lib/dns/include/dns/Makefile.in7
-rw-r--r--lib/dns/include/dns/client.h15
-rw-r--r--lib/dns/include/dns/dnssec.h17
-rw-r--r--lib/dns/include/dns/log.h3
-rw-r--r--lib/dns/include/dns/master.h3
-rw-r--r--lib/dns/include/dns/masterdump.h7
-rw-r--r--lib/dns/include/dns/message.h1
-rw-r--r--lib/dns/include/dns/nsec3.h4
-rw-r--r--lib/dns/include/dns/rdata.h5
-rw-r--r--lib/dns/include/dns/rrl.h278
-rw-r--r--lib/dns/include/dns/view.h2
-rw-r--r--lib/dns/include/dns/zone.h6
-rw-r--r--lib/dns/include/dst/dst.h25
-rw-r--r--lib/dns/include/dst/gssapi.h4
-rw-r--r--lib/dns/journal.c47
-rw-r--r--lib/dns/keydata.c6
-rw-r--r--lib/dns/log.c3
-rw-r--r--lib/dns/master.c10
-rw-r--r--lib/dns/masterdump.c44
-rw-r--r--lib/dns/message.c10
-rw-r--r--lib/dns/name.c49
-rw-r--r--lib/dns/nsec.c8
-rw-r--r--lib/dns/nsec3.c44
-rw-r--r--lib/dns/openssldh_link.c6
-rw-r--r--lib/dns/openssldsa_link.c21
-rw-r--r--lib/dns/opensslecdsa_link.c57
-rw-r--r--lib/dns/opensslgost_link.c35
-rw-r--r--lib/dns/opensslrsa_link.c22
-rw-r--r--lib/dns/portlist.c14
-rw-r--r--lib/dns/rbt.c8
-rw-r--r--lib/dns/rbtdb.c141
-rw-r--r--lib/dns/rcode.c8
-rw-r--r--lib/dns/rdata.c40
-rw-r--r--lib/dns/rdata/ch_3/a_1.c6
-rw-r--r--lib/dns/rdata/generic/afsdb_18.c6
-rw-r--r--lib/dns/rdata/generic/dnskey_48.c22
-rw-r--r--lib/dns/rdata/generic/eui48_108.c4
-rw-r--r--lib/dns/rdata/generic/eui64_109.c4
-rw-r--r--lib/dns/rdata/generic/hip_55.c8
-rw-r--r--lib/dns/rdata/generic/ipseckey_45.c8
-rw-r--r--lib/dns/rdata/generic/isdn_20.c20
-rw-r--r--lib/dns/rdata/generic/key_25.c22
-rw-r--r--lib/dns/rdata/generic/keydata_65533.c26
-rw-r--r--lib/dns/rdata/generic/l32_105.c4
-rw-r--r--lib/dns/rdata/generic/l64_106.c4
-rw-r--r--lib/dns/rdata/generic/nid_104.c4
-rw-r--r--lib/dns/rdata/generic/opt_41.c46
-rw-r--r--lib/dns/rdata/generic/rrsig_46.c32
-rw-r--r--lib/dns/rdata/generic/rt_21.c6
-rw-r--r--lib/dns/rdata/generic/soa_6.c6
-rw-r--r--lib/dns/rdata/generic/spf_99.c4
-rw-r--r--lib/dns/rdata/generic/txt_16.c4
-rw-r--r--lib/dns/rdata/hs_4/a_1.c8
-rw-r--r--lib/dns/rdata/in_1/a6_38.c6
-rw-r--r--lib/dns/rdata/in_1/a_1.c8
-rw-r--r--lib/dns/rdata/in_1/aaaa_28.c10
-rw-r--r--lib/dns/rdata/in_1/apl_42.c6
-rw-r--r--lib/dns/rdata/in_1/wks_11.c12
-rw-r--r--lib/dns/rdataslab.c19
-rw-r--r--lib/dns/resolver.c33
-rw-r--r--lib/dns/rootns.c2
-rw-r--r--lib/dns/rpz.c4
-rw-r--r--lib/dns/rrl.c1324
-rw-r--r--lib/dns/spnego.c26
-rw-r--r--lib/dns/spnego_asn1.c20
-rw-r--r--lib/dns/ssu.c4
-rw-r--r--lib/dns/ssu_external.c4
-rw-r--r--lib/dns/time.c4
-rw-r--r--lib/dns/tkey.c12
-rw-r--r--lib/dns/tsig.c18
-rw-r--r--lib/dns/ttl.c6
-rw-r--r--lib/dns/update.c8
-rw-r--r--lib/dns/validator.c6
-rw-r--r--lib/dns/view.c45
-rw-r--r--lib/dns/xfrin.c97
-rw-r--r--lib/dns/zone.c927
94 files changed, 3460 insertions, 855 deletions
diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in
index b712ab1cd874e..a3e3e9a4e86ac 100644
--- a/lib/dns/Makefile.in
+++ b/lib/dns/Makefile.in
@@ -55,6 +55,8 @@ DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ \
dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
gssapi_link.@O@ gssapictx.@O@ hmac_link.@O@ key.@O@
+RRLOBJS = rrl.@O@
+
# Alphabetically
DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
cache.@O@ callbacks.@O@ clientinfo.@O@ compress.@O@ \
@@ -67,14 +69,14 @@ DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
portlist.@O@ private.@O@ \
rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rcode.@O@ rdata.@O@ \
rdatalist.@O@ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ \
- request.@O@ resolver.@O@ result.@O@ rootns.@O@ rpz.@O@ \
- rriterator.@O@ sdb.@O@ \
+ request.@O@ resolver.@O@ result.@O@ rootns.@O@ \
+ rpz.@O@ rriterator.@O@ sdb.@O@ \
sdlz.@O@ soa.@O@ ssu.@O@ ssu_external.@O@ \
stats.@O@ tcpmsg.@O@ time.@O@ timer.@O@ tkey.@O@ \
tsec.@O@ tsig.@O@ ttl.@O@ update.@O@ validator.@O@ \
version.@O@ view.@O@ xfrin.@O@ zone.@O@ zonekey.@O@ zt.@O@
-OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS}
+OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} @RRLLINKOBJS@
# Alphabetically
OPENSSLGOSTLINKSRCS = opensslgost_link.c
@@ -101,7 +103,9 @@ DNSSRCS = acache.c acl.c adb.c byaddr.c \
tsec.c tsig.c ttl.c update.c validator.c \
version.c view.c xfrin.c zone.c zonekey.c zt.c ${OTHERSRCS}
-SRCS = ${DSTSRCS} ${DNSSRCS}
+RRLSRCS = rrl.c
+
+SRCS = ${DSTSRCS} ${DNSSRCS} @RRLLINKSRCS@
SUBDIRS = include
TARGETS = include/dns/enumtype.h include/dns/enumclass.h \
diff --git a/lib/dns/acache.c b/lib/dns/acache.c
index 6df9b98386353..d3d28f8561710 100644
--- a/lib/dns/acache.c
+++ b/lib/dns/acache.c
@@ -1669,13 +1669,14 @@ dns_acache_cancelentry(dns_acacheentry_t *entry) {
REQUIRE(DNS_ACACHEENTRY_VALID(entry));
acache = entry->acache;
- callback_active = ISC_TF(entry->cbarg != NULL);
INSIST(DNS_ACACHE_VALID(entry->acache));
LOCK(&acache->lock);
ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write);
+ callback_active = ISC_TF(entry->cbarg != NULL);
+
/*
* Release dependencies stored in this entry as much as possible.
* The main link cannot be released, since the acache object has
diff --git a/lib/dns/acl.c b/lib/dns/acl.c
index 3221d30c2b52a..dbc6f9cb4f3af 100644
--- a/lib/dns/acl.c
+++ b/lib/dns/acl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011, 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
@@ -291,8 +291,8 @@ dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
return (ISC_R_NOMEMORY);
/* Copy in the original elements */
- memcpy(newmem, dest->elements,
- dest->length * sizeof(dns_aclelement_t));
+ memmove(newmem, dest->elements,
+ dest->length * sizeof(dns_aclelement_t));
/* Release the memory for the old elements array */
isc_mem_put(dest->mctx, dest->elements,
diff --git a/lib/dns/adb.c b/lib/dns/adb.c
index ef7875dcb46ba..10d51bc441433 100644
--- a/lib/dns/adb.c
+++ b/lib/dns/adb.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
@@ -852,12 +852,12 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
dns_rdataset_current(rdataset, &rdata);
if (rdtype == dns_rdatatype_a) {
INSIST(rdata.length == 4);
- memcpy(&ina.s_addr, rdata.data, 4);
+ memmove(&ina.s_addr, rdata.data, 4);
isc_sockaddr_fromin(&sockaddr, &ina, 0);
hookhead = &adbname->v4;
} else {
INSIST(rdata.length == 16);
- memcpy(in6a.s6_addr, rdata.data, 16);
+ memmove(in6a.s6_addr, rdata.data, 16);
isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
hookhead = &adbname->v6;
}
diff --git a/lib/dns/api b/lib/dns/api
index a8881101f4e1a..cc5437d0be7b5 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 = 99
-LIBREVISION = 1
-LIBAGE = 0
+LIBINTERFACE = 102
+LIBREVISION = 2
+LIBAGE = 2
diff --git a/lib/dns/client.c b/lib/dns/client.c
index fc551cf9dfe57..cee4fb268d71a 100644
--- a/lib/dns/client.c
+++ b/lib/dns/client.c
@@ -249,13 +249,14 @@ static isc_result_t send_update(updatectx_t *uctx);
static isc_result_t
getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr,
isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr,
- isc_boolean_t is_shared, dns_dispatch_t **dispp)
+ isc_boolean_t is_shared, dns_dispatch_t **dispp,
+ isc_sockaddr_t *localaddr)
{
unsigned int attrs, attrmask;
- isc_sockaddr_t sa;
dns_dispatch_t *disp;
unsigned buffersize, maxbuffers, maxrequests, buckets, increment;
isc_result_t result;
+ isc_sockaddr_t anyaddr;
attrs = 0;
attrs |= DNS_DISPATCHATTR_UDP;
@@ -275,7 +276,10 @@ getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr,
attrmask |= DNS_DISPATCHATTR_IPV4;
attrmask |= DNS_DISPATCHATTR_IPV6;
- isc_sockaddr_anyofpf(&sa, family);
+ if (localaddr == NULL) {
+ localaddr = &anyaddr;
+ isc_sockaddr_anyofpf(localaddr, family);
+ }
buffersize = 4096;
maxbuffers = is_shared ? 1000 : 8;
@@ -285,7 +289,7 @@ getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr,
disp = NULL;
result = dns_dispatch_getudp(dispatchmgr, socketmgr,
- taskmgr, &sa,
+ taskmgr, localaddr,
buffersize, maxbuffers, maxrequests,
buckets, increment,
attrs, attrmask, &disp);
@@ -422,6 +426,19 @@ dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr,
unsigned int options, dns_client_t **clientp)
{
+ isc_result_t result;
+ result = dns_client_createx2(mctx, actx, taskmgr, socketmgr, timermgr,
+ options, clientp, NULL, NULL);
+ return (result);
+}
+
+isc_result_t
+dns_client_createx2(isc_mem_t *mctx, isc_appctx_t *actx,
+ isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr,
+ isc_timermgr_t *timermgr, unsigned int options,
+ dns_client_t **clientp, isc_sockaddr_t *localaddr4,
+ isc_sockaddr_t *localaddr6)
+{
dns_client_t *client;
isc_result_t result;
dns_dispatchmgr_t *dispatchmgr = NULL;
@@ -460,17 +477,27 @@ dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
goto cleanup;
client->dispatchmgr = dispatchmgr;
- /* TODO: whether to use dispatch v4 or v6 should be configurable */
+ /*
+ * If only one address family is specified, use it.
+ * If neither family is specified, or if both are, use both.
+ */
client->dispatchv4 = NULL;
+ if (localaddr4 != NULL || localaddr6 == NULL) {
+ result = getudpdispatch(AF_INET, dispatchmgr, socketmgr,
+ taskmgr, ISC_TRUE,
+ &dispatchv4, localaddr4);
+ if (result == ISC_R_SUCCESS)
+ client->dispatchv4 = dispatchv4;
+ }
+
client->dispatchv6 = NULL;
- result = getudpdispatch(AF_INET, dispatchmgr, socketmgr,
- taskmgr, ISC_TRUE, &dispatchv4);
- if (result == ISC_R_SUCCESS)
- client->dispatchv4 = dispatchv4;
- result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr,
- taskmgr, ISC_TRUE, &dispatchv6);
- if (result == ISC_R_SUCCESS)
- client->dispatchv6 = dispatchv6;
+ if (localaddr6 != NULL || localaddr4 == NULL) {
+ result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr,
+ taskmgr, ISC_TRUE,
+ &dispatchv6, localaddr6);
+ if (result == ISC_R_SUCCESS)
+ client->dispatchv6 = dispatchv6;
+ }
/* We need at least one of the dispatchers */
if (dispatchv4 == NULL && dispatchv6 == NULL) {
@@ -1094,11 +1121,23 @@ client_resfind(resctx_t *rctx, dns_fetchevent_t *event) {
UNLOCK(&rctx->lock);
}
+
+static void
+suspend(isc_task_t *task, isc_event_t *event) {
+ isc_appctx_t *actx = event->ev_arg;
+
+ UNUSED(task);
+
+ isc_app_ctxsuspend(actx);
+ isc_event_free(&event);
+}
+
static void
resolve_done(isc_task_t *task, isc_event_t *event) {
resarg_t *resarg = event->ev_arg;
dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
dns_name_t *name;
+ isc_result_t result;
UNUSED(task);
@@ -1117,8 +1156,16 @@ resolve_done(isc_task_t *task, isc_event_t *event) {
if (!resarg->canceled) {
UNLOCK(&resarg->lock);
- /* Exit from the internal event loop */
- isc_app_ctxsuspend(resarg->actx);
+ /*
+ * We may or may not be running. isc__appctx_onrun will
+ * fail if we are currently running otherwise we post a
+ * action to call isc_app_ctxsuspend when we do start
+ * running.
+ */
+ result = isc_app_ctxonrun(resarg->actx, resarg->client->mctx,
+ task, suspend, resarg->actx);
+ if (result == ISC_R_ALREADYRUNNING)
+ isc_app_ctxsuspend(resarg->actx);
} else {
/*
* We have already exited from the loop (due to some
@@ -1310,9 +1357,8 @@ dns_client_startresolve(dns_client_t *client, dns_name_t *name,
ISC_LIST_APPEND(client->resctxs, rctx, link);
UNLOCK(&client->lock);
- client_resfind(rctx, NULL);
-
*transp = (dns_clientrestrans_t *)rctx;
+ client_resfind(rctx, NULL);
return (ISC_R_SUCCESS);
diff --git a/lib/dns/diff.c b/lib/dns/diff.c
index ff60d462f3727..4517dade38dc8 100644
--- a/lib/dns/diff.c
+++ b/lib/dns/diff.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, 2013, 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
@@ -79,7 +79,7 @@ dns_difftuple_create(isc_mem_t *mctx,
datap = (unsigned char *)(t + 1);
- memcpy(datap, name->ndata, name->length);
+ memmove(datap, name->ndata, name->length);
dns_name_init(&t->name, NULL);
dns_name_clone(name, &t->name);
t->name.ndata = datap;
@@ -87,7 +87,7 @@ dns_difftuple_create(isc_mem_t *mctx,
t->ttl = ttl;
- memcpy(datap, rdata->data, rdata->length);
+ memmove(datap, rdata->data, rdata->length);
dns_rdata_init(&t->rdata);
dns_rdata_clone(rdata, &t->rdata);
t->rdata.data = datap;
@@ -379,15 +379,6 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
diff->resign);
dns_db_setsigningtime(db, modified,
resign);
- if (diff->resign == 0 &&
- (op == DNS_DIFFOP_ADDRESIGN ||
- op == DNS_DIFFOP_DELRESIGN))
- isc_log_write(
- DIFF_COMMON_LOGARGS,
- ISC_LOG_WARNING,
- "resign requested "
- "with 0 resign "
- "interval");
}
} else if (result == DNS_R_UNCHANGED) {
/*
diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c
index 5063914a9b296..7af8e644b1971 100644
--- a/lib/dns/dispatch.c
+++ b/lib/dns/dispatch.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
@@ -706,8 +706,8 @@ destroy_disp_ok(dns_dispatch_t *disp)
/*
* Called when refcount reaches 0 (and safe to destroy).
*
- * The dispatcher must not be locked.
- * The manager must be locked.
+ * The dispatcher must be locked.
+ * The manager must not be locked.
*/
static void
destroy_disp(isc_task_t *task, isc_event_t *event) {
@@ -778,6 +778,7 @@ port_search(dns_dispatch_t *disp, in_port_t port) {
static dispportentry_t *
new_portentry(dns_dispatch_t *disp, in_port_t port) {
dispportentry_t *portentry;
+ dns_qid_t *qid;
REQUIRE(disp->port_table != NULL);
@@ -786,10 +787,13 @@ new_portentry(dns_dispatch_t *disp, in_port_t port) {
return (portentry);
portentry->port = port;
- portentry->refs = 0;
+ portentry->refs = 1;
ISC_LINK_INIT(portentry, link);
+ qid = DNS_QID(disp);
+ LOCK(&qid->lock);
ISC_LIST_APPEND(disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE],
portentry, link);
+ UNLOCK(&qid->lock);
return (portentry);
}
@@ -800,7 +804,6 @@ new_portentry(dns_dispatch_t *disp, in_port_t port) {
static void
deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
dispportentry_t *portentry = *portentryp;
- isc_boolean_t unlink = ISC_FALSE;
dns_qid_t *qid;
REQUIRE(disp->port_table != NULL);
@@ -809,15 +812,14 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
qid = DNS_QID(disp);
LOCK(&qid->lock);
portentry->refs--;
- unlink = ISC_TF(portentry->refs == 0);
- UNLOCK(&qid->lock);
- if (unlink) {
+ if (portentry->refs == 0) {
ISC_LIST_UNLINK(disp->port_table[portentry->port %
DNS_DISPATCH_PORTTABLESIZE],
portentry, link);
isc_mempool_put(disp->portpool, portentry);
}
+ UNLOCK(&qid->lock);
*portentryp = NULL;
}
@@ -832,6 +834,7 @@ socket_search(dns_qid_t *qid, isc_sockaddr_t *dest, in_port_t port,
{
dispsocket_t *dispsock;
+ REQUIRE(VALID_QID(qid));
REQUIRE(bucket < qid->qid_nbuckets);
dispsock = ISC_LIST_HEAD(qid->sock_table[bucket]);
@@ -938,8 +941,11 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
result = ISC_R_NOMEMORY;
break;
}
+ } else {
+ LOCK(&qid->lock);
+ portentry->refs++;
+ UNLOCK(&qid->lock);
}
- portentry->refs++;
break;
} else if (result == ISC_R_NOPERM) {
char buf[ISC_SOCKADDR_FORMATSIZE];
@@ -1076,6 +1082,7 @@ entry_search(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id,
{
dns_dispentry_t *res;
+ REQUIRE(VALID_QID(qid));
REQUIRE(bucket < qid->qid_nbuckets);
res = ISC_LIST_HEAD(qid->qid_table[bucket]);
@@ -1428,8 +1435,8 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) {
}
/*
- * If both dispatches are bound to an address then fail as
- * the addresses can't be equal (enforced by the IP stack).
+ * If each dispatch is bound to a different address
+ * then fail.
*
* Note under Linux a packet can be sent out via IPv4 socket
* and the response be received via a IPv6 socket.
@@ -1444,7 +1451,8 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) {
}
isc_sockaddr_anyofpf(&a1, isc_sockaddr_pf(&resp->disp->local));
isc_sockaddr_anyofpf(&a2, isc_sockaddr_pf(&disp->local));
- if (!isc_sockaddr_eqaddr(&a1, &resp->disp->local) &&
+ if (!isc_sockaddr_eqaddr(&disp->local, &resp->disp->local) &&
+ !isc_sockaddr_eqaddr(&a1, &resp->disp->local) &&
!isc_sockaddr_eqaddr(&a2, &disp->local)) {
free_buffer(disp, ev->region.base, ev->region.length);
goto unlock;
@@ -2647,8 +2655,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
* MUST be unlocked, and not used by anything.
*/
static void
-dispatch_free(dns_dispatch_t **dispp)
-{
+dispatch_free(dns_dispatch_t **dispp) {
dns_dispatch_t *disp;
dns_dispatchmgr_t *mgr;
int i;
@@ -3311,17 +3318,17 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
*/
LOCK(&qid->lock);
id = (dns_messageid_t)dispatch_random(DISP_ARC4CTX(disp));
- bucket = dns_hash(qid, dest, id, localport);
ok = ISC_FALSE;
- for (i = 0; i < 64; i++) {
+ i = 0;
+ do {
+ bucket = dns_hash(qid, dest, id, localport);
if (entry_search(qid, dest, id, localport, bucket) == NULL) {
ok = ISC_TRUE;
break;
}
id += qid->qid_increment;
id &= 0x0000ffff;
- bucket = dns_hash(qid, dest, id, localport);
- }
+ } while (i++ < 64);
UNLOCK(&qid->lock);
if (!ok) {
@@ -3331,9 +3338,9 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
res = isc_mempool_get(disp->mgr->rpool);
if (res == NULL) {
- UNLOCK(&disp->lock);
if (dispsocket != NULL)
destroy_dispsocket(disp, &dispsocket);
+ UNLOCK(&disp->lock);
return (ISC_R_NOMEMORY);
}
@@ -3708,7 +3715,7 @@ dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event) {
isc_event_free(ISC_EVENT_PTR(&newsevent));
return;
}
- memcpy(buf, sevent->region.base, sevent->n);
+ memmove(buf, sevent->region.base, sevent->n);
newsevent->region.base = buf;
newsevent->region.length = disp->mgr->buffersize;
newsevent->n = sevent->n;
diff --git a/lib/dns/dns64.c b/lib/dns/dns64.c
index 78eff579a2bac..7d47c66933b54 100644
--- a/lib/dns/dns64.c
+++ b/lib/dns/dns64.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010, 2011 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2010, 2011, 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
@@ -83,10 +83,10 @@ dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix,
if (new == NULL)
return (ISC_R_NOMEMORY);
memset(new->bits, 0, sizeof(new->bits));
- memcpy(new->bits, prefix->type.in6.s6_addr, prefixlen / 8);
+ memmove(new->bits, prefix->type.in6.s6_addr, prefixlen / 8);
if (suffix != NULL)
- memcpy(new->bits + nbytes, suffix->type.in6.s6_addr + nbytes,
- 16 - nbytes);
+ memmove(new->bits + nbytes, suffix->type.in6.s6_addr + nbytes,
+ 16 - nbytes);
new->clients = NULL;
if (clients != NULL)
dns_acl_attach(clients, &new->clients);
@@ -155,7 +155,7 @@ dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
struct in_addr ina;
isc_netaddr_t netaddr;
- memcpy(&ina.s_addr, a, 4);
+ memmove(&ina.s_addr, a, 4);
isc_netaddr_fromin(&netaddr, &ina);
result = dns_acl_match(&netaddr, NULL, dns64->mapped, env,
&match, NULL);
@@ -168,7 +168,7 @@ dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
nbytes = dns64->prefixlen / 8;
INSIST(nbytes <= 12);
/* Copy prefix. */
- memcpy(aaaa, dns64->bits, nbytes);
+ memmove(aaaa, dns64->bits, nbytes);
/* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */
if (nbytes == 8)
aaaa[nbytes++] = 0;
@@ -180,7 +180,7 @@ dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
aaaa[nbytes++] = 0;
}
/* Copy suffix. */
- memcpy(aaaa + nbytes, dns64->bits + nbytes, 16 - nbytes);
+ memmove(aaaa + nbytes, dns64->bits + nbytes, 16 - nbytes);
return (ISC_R_SUCCESS);
}
@@ -268,7 +268,7 @@ dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
if (aaaaok == NULL || !aaaaok[i]) {
dns_rdataset_current(rdataset, &rdata);
- memcpy(&in6.s6_addr, rdata.data, 16);
+ memmove(&in6.s6_addr, rdata.data, 16);
isc_netaddr_fromin6(&netaddr, &in6);
result = dns_acl_match(&netaddr, NULL,
diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c
index d00c99b4124c0..d7addc681430a 100644
--- a/lib/dns/dnssec.c
+++ b/lib/dns/dnssec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 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
@@ -295,7 +295,7 @@ dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
* Create an envelope for each rdata: <name|type|class|ttl>.
*/
isc_buffer_init(&envbuf, data, sizeof(data));
- memcpy(data, r.base, r.length);
+ memmove(data, r.base, r.length);
isc_buffer_add(&envbuf, r.length);
isc_buffer_putuint16(&envbuf, set->type);
isc_buffer_putuint16(&envbuf, set->rdclass);
@@ -501,10 +501,10 @@ dns_dnssec_verify3(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
if (labels - sig.labels > 0) {
isc_buffer_putuint8(&envbuf, 1);
isc_buffer_putuint8(&envbuf, '*');
- memcpy(data + 2, r.base, r.length);
+ memmove(data + 2, r.base, r.length);
}
else
- memcpy(data, r.base, r.length);
+ memmove(data, r.base, r.length);
isc_buffer_add(&envbuf, r.length);
isc_buffer_putuint16(&envbuf, set->type);
isc_buffer_putuint16(&envbuf, set->rdclass);
@@ -609,8 +609,8 @@ dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
return (result);
}
-static isc_boolean_t
-key_active(dst_key_t *key, isc_stdtime_t now) {
+isc_boolean_t
+dns_dnssec_keyactive(dst_key_t *key, isc_stdtime_t now) {
isc_result_t result;
isc_stdtime_t publish, active, revoke, inactive, delete;
isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE;
@@ -684,6 +684,7 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
isc_stdtime_get(&now);
*nkeys = 0;
+ memset(keys, 0, sizeof(*keys) * maxkeys);
dns_rdataset_init(&rdataset);
RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
&rdataset, NULL));
@@ -763,7 +764,8 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
/*
* If a key is marked inactive, skip it
*/
- if (!key_active(keys[count], now)) {
+ if (!dns_dnssec_keyactive(keys[count], now)) {
+ dst_key_setinactive(pubkey, ISC_TRUE);
dst_key_free(&keys[count]);
keys[count] = pubkey;
pubkey = NULL;
@@ -1038,14 +1040,14 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
/*
* Extract the header.
*/
- memcpy(header, source_r.base, DNS_MESSAGE_HEADERLEN);
+ memmove(header, source_r.base, DNS_MESSAGE_HEADERLEN);
/*
* Decrement the additional field counter.
*/
- memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
+ memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
- memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
+ memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
/*
* Digest the modified header.
@@ -1311,9 +1313,9 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory,
isc_dir_t dir;
dns_dnsseckey_t *key = NULL;
dst_key_t *dstkey = NULL;
- char namebuf[DNS_NAME_FORMATSIZE], *p;
+ char namebuf[DNS_NAME_FORMATSIZE];
isc_buffer_t b;
- unsigned int len;
+ unsigned int len, i;
isc_stdtime_t now;
REQUIRE(keylist != NULL);
@@ -1333,49 +1335,62 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory,
isc_stdtime_get(&now);
while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
- if (dir.entry.name[0] == 'K' &&
- dir.entry.length > len + 1 &&
- dir.entry.name[len + 1] == '+' &&
- strncasecmp(dir.entry.name + 1, namebuf, len) == 0) {
- p = strrchr(dir.entry.name, '.');
- if (p != NULL && strcmp(p, ".private") != 0)
- continue;
+ if (dir.entry.name[0] != 'K' ||
+ dir.entry.length < len + 1 ||
+ dir.entry.name[len + 1] != '+' ||
+ strncasecmp(dir.entry.name + 1, namebuf, len) != 0)
+ continue;
- dstkey = NULL;
- result = dst_key_fromnamedfile(dir.entry.name,
- directory,
- DST_TYPE_PUBLIC |
- DST_TYPE_PRIVATE,
- mctx, &dstkey);
-
- if (result != ISC_R_SUCCESS) {
- isc_log_write(dns_lctx,
- DNS_LOGCATEGORY_GENERAL,
- DNS_LOGMODULE_DNSSEC,
- ISC_LOG_WARNING,
- "dns_dnssec_findmatchingkeys: "
- "error reading key file %s: %s",
- dir.entry.name,
- isc_result_totext(result));
+ for (i = len + 1 + 1; i < dir.entry.length ; i++)
+ if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9')
+ break;
+
+ if (i == len + 1 + 1 || i >= dir.entry.length ||
+ dir.entry.name[i] != '+')
+ continue;
+
+ for (i++ ; i < dir.entry.length ; i++)
+ if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9')
+ break;
+
+ if (strcmp(dir.entry.name + i, ".private") != 0)
continue;
- }
- RETERR(dns_dnsseckey_create(mctx, &dstkey, &key));
- key->source = dns_keysource_repository;
- get_hints(key, now);
+ dstkey = NULL;
+ result = dst_key_fromnamedfile(dir.entry.name,
+ directory,
+ DST_TYPE_PUBLIC |
+ DST_TYPE_PRIVATE,
+ mctx, &dstkey);
- if (key->legacy) {
- dns_dnsseckey_destroy(mctx, &key);
- } else {
- ISC_LIST_APPEND(list, key, link);
- key = NULL;
- }
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DNSSEC,
+ ISC_LOG_WARNING,
+ "dns_dnssec_findmatchingkeys: "
+ "error reading key file %s: %s",
+ dir.entry.name,
+ isc_result_totext(result));
+ continue;
+ }
+
+ RETERR(dns_dnsseckey_create(mctx, &dstkey, &key));
+ key->source = dns_keysource_repository;
+ get_hints(key, now);
+
+ if (key->legacy) {
+ dns_dnsseckey_destroy(mctx, &key);
+ } else {
+ ISC_LIST_APPEND(list, key, link);
+ key = NULL;
}
}
- if (!ISC_LIST_EMPTY(list))
+ if (!ISC_LIST_EMPTY(list)) {
+ result = ISC_R_SUCCESS;
ISC_LIST_APPENDLIST(*keylist, list, link);
- else
+ } else
result = ISC_R_NOTFOUND;
failure:
@@ -1793,7 +1808,13 @@ dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
for (key2 = ISC_LIST_HEAD(*keys);
key2 != NULL;
key2 = ISC_LIST_NEXT(key2, link)) {
- if (dst_key_pubcompare(key1->key, key2->key,
+ int f1 = dst_key_flags(key1->key);
+ int f2 = dst_key_flags(key2->key);
+ int nr1 = f1 & ~DNS_KEYFLAG_REVOKE;
+ int nr2 = f2 & ~DNS_KEYFLAG_REVOKE;
+ if (nr1 == nr2 &&
+ dst_key_alg(key1->key) == dst_key_alg(key2->key) &&
+ dst_key_pubcompare(key1->key, key2->key,
ISC_TRUE)) {
int r1, r2;
r1 = dst_key_flags(key1->key) &
diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c
index 98607246effcf..6416273760470 100644
--- a/lib/dns/dst_api.c
+++ b/lib/dns/dst_api.c
@@ -443,6 +443,16 @@ dst_key_tofile(const dst_key_t *key, int type, const char *directory) {
return (ISC_R_SUCCESS);
}
+void
+dst_key_setexternal(dst_key_t *key, isc_boolean_t value) {
+ key->external = value;
+}
+
+isc_boolean_t
+dst_key_isexternal(dst_key_t *key) {
+ return (key->external);
+}
+
isc_result_t
dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
unsigned int alg, int type, const char *directory,
@@ -1349,10 +1359,27 @@ get_key_struct(dns_name_t *name, unsigned int alg,
key->times[i] = 0;
key->timeset[i] = ISC_FALSE;
}
+ key->inactive = ISC_FALSE;
key->magic = KEY_MAGIC;
return (key);
}
+isc_boolean_t
+dst_key_inactive(const dst_key_t *key) {
+
+ REQUIRE(VALID_KEY(key));
+
+ return (key->inactive);
+}
+
+void
+dst_key_setinactive(dst_key_t *key, isc_boolean_t inactive) {
+
+ REQUIRE(VALID_KEY(key));
+
+ key->inactive = inactive;
+}
+
/*%
* Reads a public key from disk
*/
diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h
index c3e8e29a46e8e..49ca424e5b990 100644
--- a/lib/dns/dst_internal.h
+++ b/lib/dns/dst_internal.h
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 2000-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -126,6 +126,9 @@ struct dst_key {
isc_boolean_t timeset[DST_MAX_TIMES + 1]; /*%< data set? */
isc_stdtime_t nums[DST_MAX_NUMERIC + 1]; /*%< numeric metadata */
isc_boolean_t numset[DST_MAX_NUMERIC + 1]; /*%< data set? */
+ isc_boolean_t inactive; /*%< private key not present as it is
+ inactive */
+ isc_boolean_t external; /*%< external key */
int fmt_major; /*%< private key format, major version */
int fmt_minor; /*%< private key format, minor version */
diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c
index ca43cb3d12414..2b950d5a3b9cf 100644
--- a/lib/dns/dst_parse.c
+++ b/lib/dns/dst_parse.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -178,14 +178,18 @@ find_numericdata(const char *s) {
}
static int
-check_rsa(const dst_private_t *priv) {
+check_rsa(const dst_private_t *priv, isc_boolean_t external) {
int i, j;
isc_boolean_t have[RSA_NTAGS];
isc_boolean_t ok;
unsigned int mask;
+ if (external)
+ return ((priv->nelements == 0) ? 0 : -1);
+
for (i = 0; i < RSA_NTAGS; i++)
have[i] = ISC_FALSE;
+
for (j = 0; j < priv->nelements; j++) {
for (i = 0; i < RSA_NTAGS; i++)
if (priv->elements[j].tag == TAG(DST_ALG_RSAMD5, i))
@@ -231,10 +235,15 @@ check_dh(const dst_private_t *priv) {
}
static int
-check_dsa(const dst_private_t *priv) {
+check_dsa(const dst_private_t *priv, isc_boolean_t external) {
int i, j;
+
+ if (external)
+ return ((priv->nelements == 0)? 0 : -1);
+
if (priv->nelements != DSA_NTAGS)
return (-1);
+
for (i = 0; i < DSA_NTAGS; i++) {
for (j = 0; j < priv->nelements; j++)
if (priv->elements[j].tag == TAG(DST_ALG_DSA, i))
@@ -246,7 +255,11 @@ check_dsa(const dst_private_t *priv) {
}
static int
-check_gost(const dst_private_t *priv) {
+check_gost(const dst_private_t *priv, isc_boolean_t external) {
+
+ if (external)
+ return ((priv->nelements == 0)? 0 : -1);
+
if (priv->nelements != GOST_NTAGS)
return (-1);
if (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0))
@@ -255,7 +268,11 @@ check_gost(const dst_private_t *priv) {
}
static int
-check_ecdsa(const dst_private_t *priv) {
+check_ecdsa(const dst_private_t *priv, isc_boolean_t external) {
+
+ if (external)
+ return ((priv->nelements == 0) ? 0 : -1);
+
if (priv->nelements != ECDSA_NTAGS)
return (-1);
if (priv->elements[0].tag != TAG(DST_ALG_ECDSA256, 0))
@@ -309,7 +326,7 @@ check_hmac_sha(const dst_private_t *priv, unsigned int ntags,
static int
check_data(const dst_private_t *priv, const unsigned int alg,
- isc_boolean_t old)
+ isc_boolean_t old, isc_boolean_t external)
{
/* XXXVIX this switch statement is too sparse to gen a jump table. */
switch (alg) {
@@ -318,17 +335,17 @@ check_data(const dst_private_t *priv, const unsigned int alg,
case DST_ALG_NSEC3RSASHA1:
case DST_ALG_RSASHA256:
case DST_ALG_RSASHA512:
- return (check_rsa(priv));
+ return (check_rsa(priv, external));
case DST_ALG_DH:
return (check_dh(priv));
case DST_ALG_DSA:
case DST_ALG_NSEC3DSA:
- return (check_dsa(priv));
+ return (check_dsa(priv, external));
case DST_ALG_ECCGOST:
- return (check_gost(priv));
+ return (check_gost(priv, external));
case DST_ALG_ECDSA256:
case DST_ALG_ECDSA384:
- return (check_ecdsa(priv));
+ return (check_ecdsa(priv, external));
case DST_ALG_HMACMD5:
return (check_hmac_md5(priv, old));
case DST_ALG_HMACSHA1:
@@ -372,6 +389,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
unsigned int opt = ISC_LEXOPT_EOL;
isc_stdtime_t when;
isc_result_t ret;
+ isc_boolean_t external = ISC_FALSE;
REQUIRE(priv != NULL);
@@ -470,6 +488,11 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
goto fail;
}
+ if (strcmp(DST_AS_STR(token), "External:") == 0) {
+ external = ISC_TRUE;
+ goto next;
+ }
+
/* Numeric metadata */
tag = find_numericdata(DST_AS_STR(token));
if (tag >= 0) {
@@ -534,8 +557,14 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
READLINE(lex, opt, &token);
data = NULL;
}
+
done:
- check = check_data(priv, alg, ISC_TRUE);
+ if (external && priv->nelements != 0) {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+
+ check = check_data(priv, alg, ISC_TRUE, external);
if (check < 0) {
ret = DST_R_INVALIDPRIVATEKEY;
goto fail;
@@ -544,6 +573,8 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
goto fail;
}
+ key->external = external;
+
return (ISC_R_SUCCESS);
fail:
@@ -573,7 +604,7 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
REQUIRE(priv != NULL);
- ret = check_data(priv, dst_key_alg(key), ISC_FALSE);
+ ret = check_data(priv, dst_key_alg(key), ISC_FALSE, key->external);
if (ret < 0)
return (DST_R_INVALIDPRIVATEKEY);
else if (ret != ISC_R_SUCCESS)
@@ -691,6 +722,9 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
fprintf(fp, "%s %.*s\n", s, (int)r.length, r.base);
}
+ if (key->external)
+ fprintf(fp, "External:\n");
+
/* Add the metadata tags */
if (major > 1 || (major == 1 && minor >= 3)) {
for (i = 0; i < NUMERIC_NTAGS; i++) {
@@ -706,14 +740,14 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
isc_buffer_init(&b, buffer, sizeof(buffer));
result = dns_time32_totext(when, &b);
- if (result != ISC_R_SUCCESS) {
+ if (result != ISC_R_SUCCESS) {
fclose(fp);
return (DST_R_INVALIDPRIVATEKEY);
- }
+ }
isc_buffer_usedregion(&b, &r);
- fprintf(fp, "%s %.*s\n", timetags[i], (int)r.length,
+ fprintf(fp, "%s %.*s\n", timetags[i], (int)r.length,
r.base);
}
}
diff --git a/lib/dns/dst_result.c b/lib/dns/dst_result.c
index 297e809cc9453..e9f7b06ab2521 100644
--- a/lib/dns/dst_result.c
+++ b/lib/dns/dst_result.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2008, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008, 2012, 2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -35,7 +35,7 @@ static const char *text[DST_R_NRESULTS] = {
"illegal operation for a null key", /*%< 3 */
"public key is invalid", /*%< 4 */
"private key is invalid", /*%< 5 */
- "UNUSED6", /*%< 6 */
+ "external key", /*%< 6 */
"error occurred writing key to disk", /*%< 7 */
"invalid algorithm specific parameter", /*%< 8 */
"UNUSED9", /*%< 9 */
diff --git a/lib/dns/gen.c b/lib/dns/gen.c
index 6b533dd23f9c7..b934c9990fb3f 100644
--- a/lib/dns/gen.c
+++ b/lib/dns/gen.c
@@ -309,7 +309,8 @@ find_typename(int type) {
static void
insert_into_typenames(int type, const char *typename, const char *attr) {
struct ttnam *ttn = NULL;
- int c, i, n;
+ size_t c;
+ int i, n;
char tmp[256];
INSIST(strlen(typename) < TYPECLASSBUF);
@@ -485,7 +486,7 @@ sd(int rdclass, const char *classname, const char *dirname, char filetype) {
static unsigned int
HASH(char *string) {
- unsigned int n;
+ size_t n;
unsigned char a, b;
n = strlen(string);
@@ -779,6 +780,14 @@ main(int argc, char **argv) {
ttn = find_typename(i);
if (ttn == NULL)
continue;
+ /*
+ * Remove KEYDATA (65533) from the type to memonic
+ * translation as it is internal use only. This
+ * stops the tools from displaying KEYDATA instead
+ * of TYPE65533.
+ */
+ if (i == 65533U)
+ continue;
fprintf(stdout, "\tcase %u: return "
"(str_totext(\"%s\", target)); \\\n",
i, upper(ttn->typename));
diff --git a/lib/dns/gssapi_link.c b/lib/dns/gssapi_link.c
index 5ad81cd80ced3..2927b676d3665 100644
--- a/lib/dns/gssapi_link.c
+++ b/lib/dns/gssapi_link.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -47,7 +47,7 @@
#define GBUFFER_TO_REGION(gb, r) \
do { \
- (r).length = (gb).length; \
+ (r).length = (unsigned int)(gb).length; \
(r).base = (gb).value; \
} while (0)
@@ -180,7 +180,7 @@ gssapi_sign(dst_context_t *dctx, isc_buffer_t *sig) {
* Copy the output into our buffer space, and release the gssapi
* allocated space.
*/
- isc_buffer_putmem(sig, gsig.value, gsig.length);
+ isc_buffer_putmem(sig, gsig.value, (unsigned int)gsig.length);
if (gsig.length != 0U)
gss_release_buffer(&minor, &gsig);
@@ -216,7 +216,7 @@ gssapi_verify(dst_context_t *dctx, const isc_region_t *sig) {
buf = isc_mem_allocate(dst__memory_pool, sig->length);
if (buf == NULL)
return (ISC_R_FAILURE);
- memcpy(buf, sig->base, sig->length);
+ memmove(buf, sig->base, sig->length);
r.base = buf;
r.length = sig->length;
REGION_TO_GBUFFER(r, gsig);
@@ -286,7 +286,7 @@ gssapi_destroy(dst_key_t *key) {
static isc_result_t
gssapi_restore(dst_key_t *key, const char *keystr) {
OM_uint32 major, minor;
- size_t len;
+ unsigned int len;
isc_buffer_t *b = NULL;
isc_region_t r;
gss_buffer_desc gssbuffer;
@@ -346,13 +346,13 @@ gssapi_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
gss_release_buffer(&minor, &gssbuffer);
return (ISC_R_NOMEMORY);
}
- isc_buffer_init(&b, buf, len);
+ isc_buffer_init(&b, buf, (unsigned int)len);
GBUFFER_TO_REGION(gssbuffer, r);
result = isc_base64_totext(&r, 0, "", &b);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
gss_release_buffer(&minor, &gssbuffer);
*buffer = buf;
- *length = len;
+ *length = (int)len;
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c
index a8c5900e6d14a..d4209d378a76e 100644
--- a/lib/dns/gssapictx.c
+++ b/lib/dns/gssapictx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -68,8 +68,12 @@
* always use one. If we're not using our own SPNEGO implementation,
* we include SPNEGO's OID.
*/
-#if defined(GSSAPI)
+#ifdef GSSAPI
+#ifdef WIN32
+#include <krb5/krb5.h>
+#else
#include ISC_PLATFORM_KRB5HEADER
+#endif
static unsigned char krb5_mech_oid_bytes[] = {
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02
@@ -103,7 +107,7 @@ static gss_OID_set_desc mech_oid_set = {
#define GBUFFER_TO_REGION(gb, r) \
do { \
- (r).length = (gb).length; \
+ (r).length = (unsigned int)(gb).length; \
(r).base = (gb).value; \
} while (0)
@@ -252,12 +256,12 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
gss_cred_id_t *cred)
{
#ifdef GSSAPI
+ isc_result_t result;
isc_buffer_t namebuf;
gss_name_t gname;
gss_buffer_desc gnamebuf;
unsigned char array[DNS_NAME_MAXTEXT + 1];
OM_uint32 gret, minor;
- gss_OID_set mechs;
OM_uint32 lifetime;
gss_cred_usage_t usage;
char buf[1024];
@@ -304,16 +308,17 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
usage = GSS_C_ACCEPT;
gret = gss_acquire_cred(&minor, gname, GSS_C_INDEFINITE,
- &mech_oid_set,
- usage, cred, &mechs, &lifetime);
+ &mech_oid_set, usage, cred, NULL, &lifetime);
if (gret != GSS_S_COMPLETE) {
gss_log(3, "failed to acquire %s credentials for %s: %s",
initiate ? "initiate" : "accept",
(gname != NULL) ? (char *)gnamebuf.value : "?",
gss_error_tostring(gret, minor, buf, sizeof(buf)));
- check_config((char *)array);
- return (ISC_R_FAILURE);
+ if (gname != NULL)
+ check_config((char *)array);
+ result = ISC_R_FAILURE;
+ goto cleanup;
}
gss_log(4, "acquired %s credentials for %s",
@@ -321,8 +326,18 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
(gname != NULL) ? (char *)gnamebuf.value : "?");
log_cred(*cred);
+ result = ISC_R_SUCCESS;
- return (ISC_R_SUCCESS);
+cleanup:
+ if (gname != NULL) {
+ gret = gss_release_name(&minor, &gname);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_name: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ }
+
+ return (result);
#else
REQUIRE(cred != NULL && *cred == NULL);
@@ -620,7 +635,6 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
RETERR(isc_buffer_copyregion(outtoken, &r));
(void)gss_release_buffer(&minor, &gouttoken);
}
- (void)gss_release_name(&minor, &gname);
if (gret == GSS_S_COMPLETE)
result = ISC_R_SUCCESS;
@@ -628,6 +642,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
result = DNS_R_CONTINUE;
out:
+ (void)gss_release_name(&minor, &gname);
return (result);
#else
UNUSED(name);
@@ -669,7 +684,7 @@ dst_gssapi_acceptctx(gss_cred_id_t cred,
context = *ctxout;
if (gssapi_keytab != NULL) {
-#ifdef ISC_PLATFORM_GSSAPI_KRB5_HEADER
+#if defined(ISC_PLATFORM_GSSAPI_KRB5_HEADER) || defined(WIN32)
gret = gsskrb5_register_acceptor_identity(gssapi_keytab);
if (gret != GSS_S_COMPLETE) {
gss_log(3, "failed "
@@ -730,7 +745,8 @@ dst_gssapi_acceptctx(gss_cred_id_t cred,
}
if (gouttoken.length > 0U) {
- RETERR(isc_buffer_allocate(mctx, outtoken, gouttoken.length));
+ RETERR(isc_buffer_allocate(mctx, outtoken,
+ (unsigned int)gouttoken.length));
GBUFFER_TO_REGION(gouttoken, r);
RETERR(isc_buffer_copyregion(*outtoken, &r));
(void)gss_release_buffer(&minor, &gouttoken);
diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c
index 256abb6eb475e..d99c5fb00f42c 100644
--- a/lib/dns/hmac_link.c
+++ b/lib/dns/hmac_link.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -42,6 +42,7 @@
#include <isc/md5.h>
#include <isc/sha1.h>
#include <isc/mem.h>
+#include <isc/safe.h>
#include <isc/string.h>
#include <isc/util.h>
@@ -138,7 +139,7 @@ hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH) == 0)
+ if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH))
return (ISC_TRUE);
else
return (ISC_FALSE);
@@ -227,9 +228,8 @@ hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
isc_md5_update(&md5ctx, r.base, r.length);
isc_md5_final(&md5ctx, hkey->key);
keylen = ISC_MD5_DIGESTLENGTH;
- }
- else {
- memcpy(hkey->key, r.base, r.length);
+ } else {
+ memmove(hkey->key, r.base, r.length);
keylen = r.length;
}
@@ -415,7 +415,7 @@ hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH) == 0)
+ if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH))
return (ISC_TRUE);
else
return (ISC_FALSE);
@@ -504,9 +504,8 @@ hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
isc_sha1_update(&sha1ctx, r.base, r.length);
isc_sha1_final(&sha1ctx, hkey->key);
keylen = ISC_SHA1_DIGESTLENGTH;
- }
- else {
- memcpy(hkey->key, r.base, r.length);
+ } else {
+ memmove(hkey->key, r.base, r.length);
keylen = r.length;
}
@@ -692,7 +691,7 @@ hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH) == 0)
+ if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH))
return (ISC_TRUE);
else
return (ISC_FALSE);
@@ -783,9 +782,8 @@ hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
isc_sha224_update(&sha224ctx, r.base, r.length);
isc_sha224_final(hkey->key, &sha224ctx);
keylen = ISC_SHA224_DIGESTLENGTH;
- }
- else {
- memcpy(hkey->key, r.base, r.length);
+ } else {
+ memmove(hkey->key, r.base, r.length);
keylen = r.length;
}
@@ -971,7 +969,7 @@ hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH) == 0)
+ if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH))
return (ISC_TRUE);
else
return (ISC_FALSE);
@@ -1062,9 +1060,8 @@ hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
isc_sha256_update(&sha256ctx, r.base, r.length);
isc_sha256_final(hkey->key, &sha256ctx);
keylen = ISC_SHA256_DIGESTLENGTH;
- }
- else {
- memcpy(hkey->key, r.base, r.length);
+ } else {
+ memmove(hkey->key, r.base, r.length);
keylen = r.length;
}
@@ -1250,7 +1247,7 @@ hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH) == 0)
+ if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH))
return (ISC_TRUE);
else
return (ISC_FALSE);
@@ -1341,9 +1338,8 @@ hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
isc_sha384_update(&sha384ctx, r.base, r.length);
isc_sha384_final(hkey->key, &sha384ctx);
keylen = ISC_SHA384_DIGESTLENGTH;
- }
- else {
- memcpy(hkey->key, r.base, r.length);
+ } else {
+ memmove(hkey->key, r.base, r.length);
keylen = r.length;
}
@@ -1529,7 +1525,7 @@ hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH) == 0)
+ if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH))
return (ISC_TRUE);
else
return (ISC_FALSE);
@@ -1620,9 +1616,8 @@ hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
isc_sha512_update(&sha512ctx, r.base, r.length);
isc_sha512_final(hkey->key, &sha512ctx);
keylen = ISC_SHA512_DIGESTLENGTH;
- }
- else {
- memcpy(hkey->key, r.base, r.length);
+ } else {
+ memmove(hkey->key, r.base, r.length);
keylen = r.length;
}
diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in
index 1a69f2c814f42..6ff682f70d372 100644
--- a/lib/dns/include/dns/Makefile.in
+++ b/lib/dns/include/dns/Makefile.in
@@ -1,4 +1,4 @@
-# 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) 1998-2003 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -22,7 +22,8 @@ top_srcdir = @top_srcdir@
@BIND9_VERSION@
HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.h \
- clientinfo.h db.h dbiterator.h dbtable.h diff.h dispatch.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 \
@@ -30,7 +31,7 @@ HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.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 tsig.h ttl.h types.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
GENHEADERS = enumclass.h enumtype.h rdatastruct.h
diff --git a/lib/dns/include/dns/client.h b/lib/dns/include/dns/client.h
index d21dff788ddea..41baa0d6b9d35 100644
--- a/lib/dns/include/dns/client.h
+++ b/lib/dns/include/dns/client.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009, 2013 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
@@ -149,6 +149,13 @@ isc_result_t
dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr,
unsigned int options, dns_client_t **clientp);
+
+isc_result_t
+dns_client_createx2(isc_mem_t *mctx, isc_appctx_t *actx,
+ isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr,
+ isc_timermgr_t *timermgr, unsigned int options,
+ dns_client_t **clientp,
+ isc_sockaddr_t *localaddr4, isc_sockaddr_t *localaddr6);
/*%<
* Create a DNS client. These functions create a new client object with
* minimal internal resources such as the default 'view' for the IN class and
@@ -161,6 +168,12 @@ dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
* dns_client_create() is expected to be used by an application that only needs
* simple synchronous services or by a thread-based application.
*
+ * dns_client_createx2 takes two additional parameters, 'localaddr4' and
+ * 'localaddr6', to specify the local address to use for each family. If
+ * both are set to NULL, then wildcard addresses will be used for both
+ * families. If only one is NULL, then the other address will be used
+ * as the local address, and the other protocol family will not be used.
+ *
* If the DNS_CLIENTCREATEOPT_USECACHE flag is set in 'options',
* dns_client_create(x) will create a cache database with the view.
*
diff --git a/lib/dns/include/dns/dnssec.h b/lib/dns/include/dns/dnssec.h
index e443f91b635b8..7202d99b5da94 100644
--- a/lib/dns/include/dns/dnssec.h
+++ b/lib/dns/include/dns/dnssec.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009-2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -174,6 +174,7 @@ dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
dns_name_t *name, isc_mem_t *mctx,
unsigned int maxkeys, dst_key_t **keys,
unsigned int *nkeys);
+
isc_result_t
dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
dns_dbnode_t *node, dns_name_t *name,
@@ -186,6 +187,20 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
*/
/*@}*/
+isc_boolean_t
+dns_dnssec_keyactive(dst_key_t *key, isc_stdtime_t now);
+/*%<
+ *
+ * Returns ISC_TRUE if 'key' is active as of the time specified
+ * in 'now' (i.e., if the activation date has passed, inactivation or
+ * deletion date has not yet been reached, and the key is not revoked
+ * -- or if it is a legacy key without metadata). Otherwise returns
+ * ISC_FALSE.
+ *
+ * Requires:
+ *\li 'key' is a valid key
+ */
+
isc_result_t
dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key);
/*%<
diff --git a/lib/dns/include/dns/log.h b/lib/dns/include/dns/log.h
index 3c4df8a45003a..e8c8c105473e9 100644
--- a/lib/dns/include/dns/log.h
+++ b/lib/dns/include/dns/log.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2011-2013 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
@@ -43,6 +43,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[];
#define DNS_LOGCATEGORY_DELEGATION_ONLY (&dns_categories[10])
#define DNS_LOGCATEGORY_EDNS_DISABLED (&dns_categories[11])
#define DNS_LOGCATEGORY_RPZ (&dns_categories[12])
+#define DNS_LOGCATEGORY_RRL (&dns_categories[13])
/* Backwards compatibility. */
#define DNS_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL
diff --git a/lib/dns/include/dns/master.h b/lib/dns/include/dns/master.h
index 896c6e95ecd31..4362789c3e0fc 100644
--- a/lib/dns/include/dns/master.h
+++ b/lib/dns/include/dns/master.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -57,6 +57,7 @@
#define DNS_MASTER_RESIGN 0x00002000
#define DNS_MASTER_KEY 0x00004000 /*%< Loading a key zone master file. */
+#define DNS_MASTER_NOTTL 0x00008000 /*%< Don't require ttl. */
ISC_LANG_BEGINDECLS
diff --git a/lib/dns/include/dns/masterdump.h b/lib/dns/include/dns/masterdump.h
index 8631248cc2eee..092c61b974bff 100644
--- a/lib/dns/include/dns/masterdump.h
+++ b/lib/dns/include/dns/masterdump.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2011 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2011, 2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -148,6 +148,11 @@ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_simple;
*/
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_debug;
+/*%
+ * The style used for dumping "key" zones.
+ */
+LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_keyzone;
+
/***
*** Functions
***/
diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h
index a6862faab633a..6b2f39fc95835 100644
--- a/lib/dns/include/dns/message.h
+++ b/lib/dns/include/dns/message.h
@@ -105,6 +105,7 @@
/*%< EDNS0 extended OPT codes */
#define DNS_OPT_NSID 0x0003 /*%< NSID opt code */
+#define DNS_OPT_CLIENT_SUBNET 0x0008 /*%< client subnet opt code */
#define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD|DNS_MESSAGEFLAG_CD)
#define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)
diff --git a/lib/dns/include/dns/nsec3.h b/lib/dns/include/dns/nsec3.h
index e4a22868a2db7..a4be9687dca1a 100644
--- a/lib/dns/include/dns/nsec3.h
+++ b/lib/dns/include/dns/nsec3.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2008-2013 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
@@ -43,7 +43,7 @@
/*
* Test "unknown" algorithm. Is mapped to dns_hash_sha1.
*/
-#define DNS_NSEC3_UNKNOWNALG 245U
+#define DNS_NSEC3_UNKNOWNALG ((dns_hash_t)245U)
ISC_LANG_BEGINDECLS
diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h
index 89ecaf8006966..b9531a579284a 100644
--- a/lib/dns/include/dns/rdata.h
+++ b/lib/dns/include/dns/rdata.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -171,6 +171,9 @@ struct dns_rdata {
#define DNS_STYLEFLAG_COMMENT 0x00000002U
#define DNS_STYLEFLAG_RRCOMMENT 0x00000004U
+/*% Output KEYDATA in human readable format. */
+#define DNS_STYLEFLAG_KEYDATA 0x00000008U
+
#define DNS_RDATA_DOWNCASE DNS_NAME_DOWNCASE
#define DNS_RDATA_CHECKNAMES DNS_NAME_CHECKNAMES
#define DNS_RDATA_CHECKNAMESFAIL DNS_NAME_CHECKNAMESFAIL
diff --git a/lib/dns/include/dns/rrl.h b/lib/dns/include/dns/rrl.h
new file mode 100644
index 0000000000000..ef6b72b4280d2
--- /dev/null
+++ b/lib/dns/include/dns/rrl.h
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2013 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 DNS_RRL_H
+#define DNS_RRL_H 1
+
+/*
+ * Rate limit DNS responses.
+ */
+
+#include <isc/lang.h>
+
+#include <dns/fixedname.h>
+#include <dns/rdata.h>
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+
+/*
+ * Memory allocation or other failures.
+ */
+#define DNS_RRL_LOG_FAIL ISC_LOG_WARNING
+/*
+ * dropped or slipped responses.
+ */
+#define DNS_RRL_LOG_DROP ISC_LOG_INFO
+/*
+ * Major events in dropping or slipping.
+ */
+#define DNS_RRL_LOG_DEBUG1 ISC_LOG_DEBUG(3)
+/*
+ * Limit computations.
+ */
+#define DNS_RRL_LOG_DEBUG2 ISC_LOG_DEBUG(4)
+/*
+ * Even less interesting.
+ */
+#define DNS_RRL_LOG_DEBUG3 ISC_LOG_DEBUG(9)
+
+
+#define DNS_RRL_LOG_ERR_LEN 64
+#define DNS_RRL_LOG_BUF_LEN (sizeof("would continue limiting") + \
+ DNS_RRL_LOG_ERR_LEN + \
+ sizeof(" responses to ") + \
+ ISC_NETADDR_FORMATSIZE + \
+ sizeof("/128 for IN ") + \
+ DNS_RDATATYPE_FORMATSIZE + \
+ DNS_NAME_FORMATSIZE)
+
+
+typedef struct dns_rrl_hash dns_rrl_hash_t;
+
+/*
+ * Response types.
+ */
+typedef enum {
+ DNS_RRL_RTYPE_FREE = 0,
+ DNS_RRL_RTYPE_QUERY,
+ DNS_RRL_RTYPE_REFERRAL,
+ DNS_RRL_RTYPE_NODATA,
+ DNS_RRL_RTYPE_NXDOMAIN,
+ DNS_RRL_RTYPE_ERROR,
+ DNS_RRL_RTYPE_ALL,
+ DNS_RRL_RTYPE_TCP,
+} dns_rrl_rtype_t;
+
+/*
+ * A rate limit bucket key.
+ * This should be small to limit the total size of the database.
+ * The hash of the qname should be wide enough to make the probability
+ * of collisions among requests from a single IP address block less than 50%.
+ * We need a 32-bit hash value for 10000 qps (e.g. random qnames forged
+ * by attacker) to collide with legitimate qnames from the target with
+ * probability at most 1%.
+ */
+#define DNS_RRL_MAX_PREFIX 64
+typedef union dns_rrl_key dns_rrl_key_t;
+union dns_rrl_key {
+ struct {
+ isc_uint32_t ip[DNS_RRL_MAX_PREFIX/32];
+ isc_uint32_t qname_hash;
+ dns_rdatatype_t qtype;
+ isc_uint8_t qclass;
+ dns_rrl_rtype_t rtype :4; /* 3 bits + sign bit */
+ isc_boolean_t ipv6 :1;
+ } s;
+ isc_uint16_t w[1];
+};
+
+/*
+ * A rate-limit entry.
+ * This should be small to limit the total size of the table of entries.
+ */
+typedef struct dns_rrl_entry dns_rrl_entry_t;
+typedef ISC_LIST(dns_rrl_entry_t) dns_rrl_bin_t;
+struct dns_rrl_entry {
+ ISC_LINK(dns_rrl_entry_t) lru;
+ ISC_LINK(dns_rrl_entry_t) hlink;
+ dns_rrl_key_t key;
+# define DNS_RRL_RESPONSE_BITS 24
+ signed int responses :DNS_RRL_RESPONSE_BITS;
+# define DNS_RRL_QNAMES_BITS 8
+ unsigned int log_qname :DNS_RRL_QNAMES_BITS;
+
+# define DNS_RRL_TS_GEN_BITS 2
+ unsigned int ts_gen :DNS_RRL_TS_GEN_BITS;
+ isc_boolean_t ts_valid :1;
+# define DNS_RRL_HASH_GEN_BITS 1
+ unsigned int hash_gen :DNS_RRL_HASH_GEN_BITS;
+ isc_boolean_t logged :1;
+# define DNS_RRL_LOG_BITS 11
+ unsigned int log_secs :DNS_RRL_LOG_BITS;
+
+# define DNS_RRL_TS_BITS 12
+ unsigned int ts :DNS_RRL_TS_BITS;
+
+# define DNS_RRL_MAX_SLIP 10
+ unsigned int slip_cnt :4;
+};
+
+#define DNS_RRL_MAX_TIME_TRAVEL 5
+#define DNS_RRL_FOREVER (1<<DNS_RRL_TS_BITS)
+#define DNS_RRL_MAX_TS (DNS_RRL_FOREVER - 1)
+
+#define DNS_RRL_MAX_RESPONSES ((1<<(DNS_RRL_RESPONSE_BITS-1))-1)
+#define DNS_RRL_MAX_WINDOW 3600
+#if DNS_RRL_MAX_WINDOW >= DNS_RRL_MAX_TS
+#error "DNS_RRL_MAX_WINDOW is too large"
+#endif
+#define DNS_RRL_MAX_RATE 1000
+#if DNS_RRL_MAX_RATE >= (DNS_RRL_MAX_RESPONSES / DNS_RRL_MAX_WINDOW)
+#error "DNS_RRL_MAX_rate is too large"
+#endif
+
+#if (1<<DNS_RRL_LOG_BITS) >= DNS_RRL_FOREVER
+#error DNS_RRL_LOG_BITS is too big
+#endif
+#define DNS_RRL_MAX_LOG_SECS 1800
+#if DNS_RRL_MAX_LOG_SECS >= (1<<DNS_RRL_LOG_BITS)
+#error "DNS_RRL_MAX_LOG_SECS is too large"
+#endif
+#define DNS_RRL_STOP_LOG_SECS 60
+#if DNS_RRL_STOP_LOG_SECS >= (1<<DNS_RRL_LOG_BITS)
+#error "DNS_RRL_STOP_LOG_SECS is too large"
+#endif
+
+
+/*
+ * A hash table of rate-limit entries.
+ */
+struct dns_rrl_hash {
+ isc_stdtime_t check_time;
+ unsigned int gen :DNS_RRL_HASH_GEN_BITS;
+ int length;
+ dns_rrl_bin_t bins[1];
+};
+
+/*
+ * A block of rate-limit entries.
+ */
+typedef struct dns_rrl_block dns_rrl_block_t;
+struct dns_rrl_block {
+ ISC_LINK(dns_rrl_block_t) link;
+ int size;
+ dns_rrl_entry_t entries[1];
+};
+
+/*
+ * A rate limited qname buffer.
+ */
+typedef struct dns_rrl_qname_buf dns_rrl_qname_buf_t;
+struct dns_rrl_qname_buf {
+ ISC_LINK(dns_rrl_qname_buf_t) link;
+ const dns_rrl_entry_t *e;
+ unsigned int index;
+ dns_fixedname_t qname;
+};
+
+typedef struct dns_rrl_rate dns_rrl_rate_t;
+struct dns_rrl_rate {
+ int r;
+ int scaled;
+ const char *str;
+};
+
+/*
+ * Per-view query rate limit parameters and a pointer to database.
+ */
+typedef struct dns_rrl dns_rrl_t;
+struct dns_rrl {
+ isc_mutex_t lock;
+ isc_mem_t *mctx;
+
+ isc_boolean_t log_only;
+ dns_rrl_rate_t responses_per_second;
+ dns_rrl_rate_t referrals_per_second;
+ dns_rrl_rate_t nodata_per_second;
+ dns_rrl_rate_t nxdomains_per_second;
+ dns_rrl_rate_t errors_per_second;
+ dns_rrl_rate_t all_per_second;
+ dns_rrl_rate_t slip;
+ int window;
+ double qps_scale;
+ int max_entries;
+
+ dns_acl_t *exempt;
+
+ int num_entries;
+
+ int qps_responses;
+ isc_stdtime_t qps_time;
+ double qps;
+
+ unsigned int probes;
+ unsigned int searches;
+
+ ISC_LIST(dns_rrl_block_t) blocks;
+ ISC_LIST(dns_rrl_entry_t) lru;
+
+ dns_rrl_hash_t *hash;
+ dns_rrl_hash_t *old_hash;
+ unsigned int hash_gen;
+
+ unsigned int ts_gen;
+# define DNS_RRL_TS_BASES (1<<DNS_RRL_TS_GEN_BITS)
+ isc_stdtime_t ts_bases[DNS_RRL_TS_BASES];
+
+ int ipv4_prefixlen;
+ isc_uint32_t ipv4_mask;
+ int ipv6_prefixlen;
+ isc_uint32_t ipv6_mask[4];
+
+ isc_stdtime_t log_stops_time;
+ dns_rrl_entry_t *last_logged;
+ int num_logged;
+ int num_qnames;
+ ISC_LIST(dns_rrl_qname_buf_t) qname_free;
+# define DNS_RRL_QNAMES (1<<DNS_RRL_QNAMES_BITS)
+ dns_rrl_qname_buf_t *qnames[DNS_RRL_QNAMES];
+};
+
+typedef enum {
+ DNS_RRL_RESULT_OK,
+ DNS_RRL_RESULT_DROP,
+ DNS_RRL_RESULT_SLIP,
+} dns_rrl_result_t;
+
+dns_rrl_result_t
+dns_rrl(dns_view_t *view,
+ const isc_sockaddr_t *client_addr, isc_boolean_t is_tcp,
+ dns_rdataclass_t rdclass, dns_rdatatype_t qtype,
+ dns_name_t *qname, isc_result_t resp_result, isc_stdtime_t now,
+ isc_boolean_t wouldlog, char *log_buf, unsigned int log_buf_len);
+
+void
+dns_rrl_view_destroy(dns_view_t *view);
+
+isc_result_t
+dns_rrl_init(dns_rrl_t **rrlp, dns_view_t *view, int min_entries);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RRL_H */
diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h
index d0c1931d27bed..704e5fe3e9993 100644
--- a/lib/dns/include/dns/view.h
+++ b/lib/dns/include/dns/view.h
@@ -73,6 +73,7 @@
#include <dns/acl.h>
#include <dns/fixedname.h>
+#include <dns/rrl.h>
#include <dns/rdatastruct.h>
#include <dns/rpz.h>
#include <dns/types.h>
@@ -142,6 +143,7 @@ struct dns_view {
dns_rbt_t * answeracl_exclude;
dns_rbt_t * denyanswernames;
dns_rbt_t * answernames_exclude;
+ dns_rrl_t * rrl;
isc_boolean_t provideixfr;
isc_boolean_t requestnsid;
dns_ttl_t maxcachettl;
diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h
index f91801f6fe3f5..9efa1e729767d 100644
--- a/lib/dns/include/dns/zone.h
+++ b/lib/dns/include/dns/zone.h
@@ -2086,6 +2086,12 @@ dns_zone_rpz_enable(dns_zone_t *zone);
* Set the response policy associated with a zone.
*/
+isc_result_t
+dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db);
+/*%
+ * If a zone is a response policy zone, mark its new database.
+ */
+
isc_boolean_t
dns_zone_get_rpz(dns_zone_t *zone);
diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h
index 4724fc64c95e2..1fdce4cc44d76 100644
--- a/lib/dns/include/dst/dst.h
+++ b/lib/dns/include/dst/dst.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -923,6 +923,29 @@ dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags,
unsigned int protocol, dns_rdataclass_t rdclass,
isc_mem_t *mctx, const char *keystr, dst_key_t **keyp);
+isc_boolean_t
+dst_key_inactive(const dst_key_t *key);
+/*%<
+ * Determines if the private key is missing due the key being deemed inactive.
+ *
+ * Requires:
+ * 'key' to be valid.
+ */
+
+void
+dst_key_setinactive(dst_key_t *key, isc_boolean_t inactive);
+/*%<
+ * Set key inactive state.
+ *
+ * Requires:
+ * 'key' to be valid.
+ */
+
+void
+dst_key_setexternal(dst_key_t *key, isc_boolean_t value);
+
+isc_boolean_t
+dst_key_isexternal(dst_key_t *key);
ISC_LANG_ENDDECLS
diff --git a/lib/dns/include/dst/gssapi.h b/lib/dns/include/dst/gssapi.h
index 1e81a55b97180..53c594e6b2379 100644
--- a/lib/dns/include/dst/gssapi.h
+++ b/lib/dns/include/dst/gssapi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009-2011, 2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -29,7 +29,7 @@
#include <dns/types.h>
#ifdef GSSAPI
-#ifdef _WINDOWS
+#ifdef WIN32
/*
* MSVC does not like macros in #include lines.
*/
diff --git a/lib/dns/journal.c b/lib/dns/journal.c
index 022a3e280f832..2d0b3f5f7494f 100644
--- a/lib/dns/journal.c
+++ b/lib/dns/journal.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007-2011, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2011, 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
@@ -307,7 +307,7 @@ struct dns_journal {
unsigned int magic; /*%< JOUR */
isc_mem_t *mctx; /*%< Memory context */
journal_state_t state;
- const char *filename; /*%< Journal file name */
+ char *filename; /*%< Journal file name */
FILE * fp; /*%< File handle */
isc_offset_t offset; /*%< Current file offset */
journal_header_t header; /*%< In-core journal header */
@@ -357,7 +357,7 @@ journal_pos_encode(journal_rawpos_t *raw, journal_pos_t *cooked) {
static void
journal_header_decode(journal_rawheader_t *raw, journal_header_t *cooked) {
INSIST(sizeof(cooked->format) == sizeof(raw->h.format));
- memcpy(cooked->format, raw->h.format, sizeof(cooked->format));
+ memmove(cooked->format, raw->h.format, sizeof(cooked->format));
journal_pos_decode(&raw->h.begin, &cooked->begin);
journal_pos_decode(&raw->h.end, &cooked->end);
cooked->index_size = decode_uint32(raw->h.index_size);
@@ -371,7 +371,7 @@ journal_header_encode(journal_header_t *cooked, journal_rawheader_t *raw) {
INSIST(sizeof(cooked->format) == sizeof(raw->h.format));
memset(raw->pad, 0, sizeof(raw->pad));
- memcpy(raw->h.format, cooked->format, sizeof(raw->h.format));
+ memmove(raw->h.format, cooked->format, sizeof(raw->h.format));
journal_pos_encode(&raw->h.begin, &cooked->begin);
journal_pos_encode(&raw->h.end, &cooked->end);
encode_uint32(cooked->index_size, raw->h.index_size);
@@ -411,7 +411,7 @@ journal_read(dns_journal_t *j, void *mem, size_t nbytes) {
j->filename, isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
- j->offset += nbytes;
+ j->offset += (isc_offset_t)nbytes;
return (ISC_R_SUCCESS);
}
@@ -426,7 +426,7 @@ journal_write(dns_journal_t *j, void *mem, size_t nbytes) {
j->filename, isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
- j->offset += nbytes;
+ j->offset += (isc_offset_t)nbytes;
return (ISC_R_SUCCESS);
}
@@ -528,7 +528,7 @@ journal_file_create(isc_mem_t *mctx, const char *filename) {
return (ISC_R_NOMEMORY);
}
memset(mem, 0, size);
- memcpy(mem, &rawheader, sizeof(rawheader));
+ memmove(mem, &rawheader, sizeof(rawheader));
result = isc_stdio_write(mem, 1, (size_t) size, fp, NULL);
if (result != ISC_R_SUCCESS) {
@@ -572,10 +572,13 @@ journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write,
isc_mem_attach(mctx, &j->mctx);
j->state = JOURNAL_STATE_INVALID;
j->fp = NULL;
- j->filename = filename;
+ j->filename = isc_mem_strdup(mctx, filename);
j->index = NULL;
j->rawindex = NULL;
+ if (j->filename == NULL)
+ FAIL(ISC_R_NOMEMORY);
+
result = isc_stdio_open(j->filename, write ? "rb+" : "rb", &fp);
if (result == ISC_R_FILENOTFOUND) {
@@ -678,6 +681,8 @@ journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write,
sizeof(journal_rawpos_t));
j->index = NULL;
}
+ if (j->filename != NULL)
+ isc_mem_free(j->mctx, j->filename);
if (j->fp != NULL)
(void)isc_stdio_close(j->fp);
isc_mem_putanddetach(&j->mctx, j, sizeof(*j));
@@ -689,7 +694,7 @@ dns_journal_open(isc_mem_t *mctx, const char *filename, unsigned int mode,
dns_journal_t **journalp)
{
isc_result_t result;
- int namelen;
+ size_t namelen;
char backup[1024];
isc_boolean_t write, create;
@@ -699,11 +704,11 @@ dns_journal_open(isc_mem_t *mctx, const char *filename, unsigned int mode,
result = journal_open(mctx, filename, write, create, journalp);
if (result == ISC_R_NOTFOUND) {
namelen = strlen(filename);
- if (namelen > 4 && strcmp(filename + namelen - 4, ".jnl") == 0)
+ if (namelen > 4U && strcmp(filename + namelen - 4, ".jnl") == 0)
namelen -= 4;
result = isc_string_printf(backup, sizeof(backup), "%.*s.jbk",
- namelen, filename);
+ (int)namelen, filename);
if (result != ISC_R_SUCCESS)
return (result);
result = journal_open(mctx, backup, write, write, journalp);
@@ -1241,7 +1246,8 @@ dns_journal_destroy(dns_journal_t **journalp) {
isc_mem_put(j->mctx, j->it.target.base, j->it.target.length);
if (j->it.source.base != NULL)
isc_mem_put(j->mctx, j->it.source.base, j->it.source.length);
-
+ if (j->filename != NULL)
+ isc_mem_free(j->mctx, j->filename);
if (j->fp != NULL)
(void)isc_stdio_close(j->fp);
j->magic = 0;
@@ -1257,9 +1263,7 @@ dns_journal_destroy(dns_journal_t **journalp) {
/* XXX Share code with incoming IXFR? */
static isc_result_t
-roll_forward(dns_journal_t *j, dns_db_t *db, unsigned int options,
- isc_uint32_t resign)
-{
+roll_forward(dns_journal_t *j, dns_db_t *db, unsigned int options) {
isc_buffer_t source; /* Transaction data from disk */
isc_buffer_t target; /* Ditto after _fromwire check */
isc_uint32_t db_serial; /* Database SOA serial */
@@ -1276,7 +1280,6 @@ roll_forward(dns_journal_t *j, dns_db_t *db, unsigned int options,
REQUIRE(DNS_DB_VALID(db));
dns_diff_init(j->mctx, &diff);
- diff.resign = resign;
/*
* Set up empty initial buffers for unchecked and checked
@@ -1409,6 +1412,8 @@ dns_journal_rollforward2(isc_mem_t *mctx, dns_db_t *db, unsigned int options,
REQUIRE(DNS_DB_VALID(db));
REQUIRE(filename != NULL);
+ UNUSED(resign);
+
j = NULL;
result = dns_journal_open(mctx, filename, DNS_JOURNAL_READ, &j);
if (result == ISC_R_NOTFOUND) {
@@ -1421,7 +1426,7 @@ dns_journal_rollforward2(isc_mem_t *mctx, dns_db_t *db, unsigned int options,
if (JOURNAL_EMPTY(&j->header))
result = DNS_R_UPTODATE;
else
- result = roll_forward(j, db, options, resign);
+ result = roll_forward(j, db, options);
dns_journal_destroy(&j);
@@ -2094,7 +2099,7 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial,
dns_journal_t *new = NULL;
journal_rawheader_t rawheader;
unsigned int copy_length;
- int namelen;
+ size_t namelen;
char *buf = NULL;
unsigned int size = 0;
isc_result_t result;
@@ -2104,16 +2109,16 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial,
isc_boolean_t is_backup = ISC_FALSE;
namelen = strlen(filename);
- if (namelen > 4 && strcmp(filename + namelen - 4, ".jnl") == 0)
+ if (namelen > 4U && strcmp(filename + namelen - 4, ".jnl") == 0)
namelen -= 4;
result = isc_string_printf(newname, sizeof(newname), "%.*s.jnw",
- namelen, filename);
+ (int)namelen, filename);
if (result != ISC_R_SUCCESS)
return (result);
result = isc_string_printf(backup, sizeof(backup), "%.*s.jbk",
- namelen, filename);
+ (int)namelen, filename);
if (result != ISC_R_SUCCESS)
return (result);
diff --git a/lib/dns/keydata.c b/lib/dns/keydata.c
index 822bd467dc55b..cb1ed38dd7e3c 100644
--- a/lib/dns/keydata.c
+++ b/lib/dns/keydata.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009, 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
@@ -51,7 +51,7 @@ dns_keydata_todnskey(dns_rdata_keydata_t *keydata,
dnskey->data = isc_mem_allocate(mctx, dnskey->datalen);
if (dnskey->data == NULL)
return (ISC_R_NOMEMORY);
- memcpy(dnskey->data, keydata->data, dnskey->datalen);
+ memmove(dnskey->data, keydata->data, dnskey->datalen);
}
return (ISC_R_SUCCESS);
@@ -82,7 +82,7 @@ dns_keydata_fromdnskey(dns_rdata_keydata_t *keydata,
keydata->data = isc_mem_allocate(mctx, keydata->datalen);
if (keydata->data == NULL)
return (ISC_R_NOMEMORY);
- memcpy(keydata->data, dnskey->data, keydata->datalen);
+ memmove(keydata->data, dnskey->data, keydata->datalen);
}
return (ISC_R_SUCCESS);
diff --git a/lib/dns/log.c b/lib/dns/log.c
index c4d644e3899f6..75e0d79ba34bd 100644
--- a/lib/dns/log.c
+++ b/lib/dns/log.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2011-2013 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
@@ -45,6 +45,7 @@ LIBDNS_EXTERNAL_DATA isc_logcategory_t dns_categories[] = {
{ "delegation-only", 0 },
{ "edns-disabled", 0 },
{ "rpz", 0 },
+ { "rate-limit", 0 },
{ NULL, 0 }
};
diff --git a/lib/dns/master.c b/lib/dns/master.c
index d0c175876f5cb..9e796e6e0ac73 100644
--- a/lib/dns/master.c
+++ b/lib/dns/master.c
@@ -578,9 +578,9 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
}
- lctx->ttl_known = ISC_FALSE;
+ lctx->ttl_known = ISC_TF((options & DNS_MASTER_NOTTL) != 0);
lctx->ttl = 0;
- lctx->default_ttl_known = ISC_FALSE;
+ lctx->default_ttl_known = lctx->ttl_known;
lctx->default_ttl = 0;
lctx->warn_1035 = ISC_TRUE; /* XXX Argument? */
lctx->warn_tcr = ISC_TRUE; /* XXX Argument? */
@@ -686,7 +686,7 @@ genname(char *name, int it, char *buffer, size_t length) {
isc_boolean_t nibblemode;
r.base = buffer;
- r.length = length;
+ r.length = (unsigned int)length;
while (*name != '\0') {
if (*name == '$') {
@@ -2083,7 +2083,7 @@ read_and_check(isc_boolean_t do_read, isc_buffer_t *buffer,
f, NULL);
if (result != ISC_R_SUCCESS)
return (result);
- isc_buffer_add(buffer, len);
+ isc_buffer_add(buffer, (unsigned int)len);
} else if (isc_buffer_remaininglength(buffer) < len)
return (ISC_R_RANGE);
@@ -2267,7 +2267,7 @@ load_raw(dns_loadctx_t *lctx) {
lctx->f, NULL);
if (result != ISC_R_SUCCESS)
goto cleanup;
- isc_buffer_add(&target, readlen);
+ isc_buffer_add(&target, (unsigned int)readlen);
/* Construct RRset headers */
rdatalist.rdclass = isc_buffer_getuint16(&target);
diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c
index 2717658e691ad..01f797cb99ed0 100644
--- a/lib/dns/masterdump.c
+++ b/lib/dns/masterdump.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009, 2011, 2012 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
@@ -101,6 +101,21 @@ typedef struct dns_totext_ctx {
} dns_totext_ctx_t;
LIBDNS_EXTERNAL_DATA const dns_master_style_t
+dns_master_style_keyzone = {
+ DNS_STYLEFLAG_OMIT_OWNER |
+ DNS_STYLEFLAG_OMIT_CLASS |
+ DNS_STYLEFLAG_REL_OWNER |
+ DNS_STYLEFLAG_REL_DATA |
+ DNS_STYLEFLAG_OMIT_TTL |
+ DNS_STYLEFLAG_TTL |
+ DNS_STYLEFLAG_COMMENT |
+ DNS_STYLEFLAG_RRCOMMENT |
+ DNS_STYLEFLAG_MULTILINE |
+ DNS_STYLEFLAG_KEYDATA,
+ 24, 24, 24, 32, 80, 8, UINT_MAX
+};
+
+LIBDNS_EXTERNAL_DATA const dns_master_style_t
dns_master_style_default = {
DNS_STYLEFLAG_OMIT_OWNER |
DNS_STYLEFLAG_OMIT_CLASS |
@@ -232,7 +247,7 @@ indent(unsigned int *current, unsigned int to, int tabwidth,
int n = t;
if (n > N_TABS)
n = N_TABS;
- memcpy(p, tabs, n);
+ memmove(p, tabs, n);
p += n;
t -= n;
}
@@ -253,7 +268,7 @@ indent(unsigned int *current, unsigned int to, int tabwidth,
int n = t;
if (n > N_SPACES)
n = N_SPACES;
- memcpy(p, spaces, n);
+ memmove(p, spaces, n);
p += n;
t -= n;
}
@@ -343,7 +358,7 @@ str_totext(const char *source, isc_buffer_t *target) {
if (l > region.length)
return (ISC_R_NOSPACE);
- memcpy(region.base, source, l);
+ memmove(region.base, source, l);
isc_buffer_add(target, l);
return (ISC_R_SUCCESS);
}
@@ -460,7 +475,7 @@ rdataset_totext(dns_rdataset_t *rdataset,
isc_buffer_availableregion(target, &r);
if (r.length < length)
return (ISC_R_NOSPACE);
- memcpy(r.base, ttlbuf, length);
+ memmove(r.base, ttlbuf, length);
isc_buffer_add(target, length);
column += length;
@@ -505,9 +520,22 @@ rdataset_totext(dns_rdataset_t *rdataset,
type_start = target->used;
if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
RETERR(str_totext("\\-", target));
- result = dns_rdatatype_totext(type, target);
- if (result != ISC_R_SUCCESS)
- return (result);
+ switch (type) {
+ case dns_rdatatype_keydata:
+#define KEYDATA "KEYDATA"
+ if ((ctx->style.flags & DNS_STYLEFLAG_KEYDATA) != 0) {
+ if (isc_buffer_availablelength(target) <
+ (sizeof(KEYDATA) - 1))
+ return (ISC_R_NOSPACE);
+ isc_buffer_putstr(target, KEYDATA);
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ result = dns_rdatatype_totext(type, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
column += (target->used - type_start);
/*
diff --git a/lib/dns/message.c b/lib/dns/message.c
index 53efc5a1beb5f..901c6b6d991dd 100644
--- a/lib/dns/message.c
+++ b/lib/dns/message.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
@@ -1675,8 +1675,8 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length);
if (msg->saved.base == NULL)
return (ISC_R_NOMEMORY);
- memcpy(msg->saved.base, isc_buffer_base(&origsource),
- msg->saved.length);
+ memmove(msg->saved.base, isc_buffer_base(&origsource),
+ msg->saved.length);
msg->free_saved = 1;
}
@@ -1748,7 +1748,7 @@ dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
* Copy the contents from the old to the new buffer.
*/
isc_buffer_add(buffer, r.length);
- memcpy(rn.base, r.base, r.length);
+ memmove(rn.base, r.base, r.length);
msg->buffer = buffer;
@@ -3468,7 +3468,7 @@ dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp,
dns_rdatalist_t *rdatalist = NULL;
dns_rdata_t *rdata = NULL;
isc_result_t result;
- size_t len = 0, i;
+ unsigned int len = 0, i;
REQUIRE(DNS_MESSAGE_VALID(message));
REQUIRE(rdatasetp != NULL && *rdatasetp == NULL);
diff --git a/lib/dns/name.c b/lib/dns/name.c
index 7fb21e138c3c8..9b24ed3638042 100644
--- a/lib/dns/name.c
+++ b/lib/dns/name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 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
@@ -578,6 +578,11 @@ dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
+ if (name1 == name2) {
+ *orderp = 0;
+ return (dns_namereln_equal);
+ }
+
SETUP_OFFSETS(name1, offsets1, odata1);
SETUP_OFFSETS(name2, offsets2, odata2);
@@ -691,6 +696,9 @@ dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
+ if (name1 == name2)
+ return (ISC_TRUE);
+
if (name1->length != name2->length)
return (ISC_FALSE);
@@ -963,8 +971,8 @@ dns_name_clone(const dns_name_t *source, dns_name_t *target) {
DNS_NAMEATTR_DYNOFFSETS);
if (target->offsets != NULL && source->labels > 0) {
if (source->offsets != NULL)
- memcpy(target->offsets, source->offsets,
- source->labels);
+ memmove(target->offsets, source->offsets,
+ source->labels);
else
set_offsets(target, target->offsets, NULL);
}
@@ -993,7 +1001,7 @@ dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
len = (r->length < r2.length) ? r->length : r2.length;
if (len > DNS_NAME_MAXWIRE)
len = DNS_NAME_MAXWIRE;
- memcpy(r2.base, r->base, len);
+ memmove(r2.base, r->base, len);
name->ndata = r2.base;
name->length = len;
} else {
@@ -1977,8 +1985,8 @@ dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
if (gf) {
if (target->length - target->used < gp.length)
return (ISC_R_NOSPACE);
- (void)memcpy((unsigned char *)target->base + target->used,
- gp.ndata, (size_t)gp.length);
+ (void)memmove((unsigned char *)target->base + target->used,
+ gp.ndata, (size_t)gp.length);
isc_buffer_add(target, gp.length);
go |= 0xc000;
if (target->length - target->used < 2)
@@ -1989,8 +1997,8 @@ dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
} else {
if (target->length - target->used < name->length)
return (ISC_R_NOSPACE);
- (void)memcpy((unsigned char *)target->base + target->used,
- name->ndata, (size_t)name->length);
+ (void)memmove((unsigned char *)target->base + target->used,
+ name->ndata, (size_t)name->length);
isc_buffer_add(target, name->length);
dns_compress_add(cctx, name, name, offset);
}
@@ -2070,12 +2078,7 @@ dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
if (copy_suffix) {
if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
absolute = ISC_TRUE;
- if (suffix == name && suffix->buffer == target)
- memmove(ndata + prefix_length, suffix->ndata,
- suffix->length);
- else
- memcpy(ndata + prefix_length, suffix->ndata,
- suffix->length);
+ memmove(ndata + prefix_length, suffix->ndata, suffix->length);
}
/*
@@ -2084,7 +2087,7 @@ dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
* copy anything.
*/
if (copy_prefix && (prefix != name || prefix->buffer != target))
- memcpy(ndata, prefix->ndata, prefix_length);
+ memmove(ndata, prefix->ndata, prefix_length);
name->ndata = ndata;
name->labels = labels;
@@ -2158,7 +2161,7 @@ dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
if (target->ndata == NULL)
return (ISC_R_NOMEMORY);
- memcpy(target->ndata, source->ndata, source->length);
+ memmove(target->ndata, source->ndata, source->length);
target->length = source->length;
target->labels = source->labels;
@@ -2167,8 +2170,8 @@ dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
if (target->offsets != NULL) {
if (source->offsets != NULL)
- memcpy(target->offsets, source->offsets,
- source->labels);
+ memmove(target->offsets, source->offsets,
+ source->labels);
else
set_offsets(target, target->offsets, NULL);
}
@@ -2200,7 +2203,7 @@ dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
if (target->ndata == NULL)
return (ISC_R_NOMEMORY);
- memcpy(target->ndata, source->ndata, source->length);
+ memmove(target->ndata, source->ndata, source->length);
target->length = source->length;
target->labels = source->labels;
@@ -2210,7 +2213,7 @@ dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
target->offsets = target->ndata + source->length;
if (source->offsets != NULL)
- memcpy(target->offsets, source->offsets, source->labels);
+ memmove(target->offsets, source->offsets, source->labels);
else
set_offsets(target, target->offsets, NULL);
@@ -2390,7 +2393,7 @@ dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
isc_buffer_usedregion(&buf, &reg);
p = isc_mem_allocate(mctx, reg.length + 1);
- memcpy(p, (char *) reg.base, (int) reg.length);
+ memmove(p, (char *) reg.base, (int) reg.length);
p[reg.length] = '\0';
*target = p;
@@ -2466,7 +2469,7 @@ dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
ndata = (unsigned char *)target->base + target->used;
dest->ndata = target->base;
- memcpy(ndata, source->ndata, source->length);
+ memmove(ndata, source->ndata, source->length);
dest->ndata = ndata;
dest->labels = source->labels;
@@ -2478,7 +2481,7 @@ dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
if (dest->labels > 0 && dest->offsets != NULL) {
if (source->offsets != NULL)
- memcpy(dest->offsets, source->offsets, source->labels);
+ memmove(dest->offsets, source->offsets, source->labels);
else
set_offsets(dest, dest->offsets, NULL);
}
diff --git a/lib/dns/nsec.c b/lib/dns/nsec.c
index e446806b4e6a5..5d1197d093b09 100644
--- a/lib/dns/nsec.c
+++ b/lib/dns/nsec.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
@@ -96,7 +96,7 @@ dns_nsec_compressbitmap(unsigned char *map, const unsigned char *raw,
map += octet + 1;
raw += 32;
}
- return (map - start);
+ return (unsigned int)(map - start);
}
isc_result_t
@@ -115,7 +115,7 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
memset(buffer, 0, DNS_NSEC_BUFFERSIZE);
dns_name_toregion(target, &r);
- memcpy(buffer, r.base, r.length);
+ memmove(buffer, r.base, r.length);
r.base = buffer;
/*
* Use the end of the space for a raw bitmap leaving enough
@@ -164,7 +164,7 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
nsec_bits += dns_nsec_compressbitmap(nsec_bits, bm, max_type);
- r.length = nsec_bits - r.base;
+ r.length = (unsigned int)(nsec_bits - r.base);
INSIST(r.length <= DNS_NSEC_BUFFERSIZE);
dns_rdata_fromregion(rdata,
dns_db_class(db),
diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c
index 935f515d23ed8..3724118cb3fe9 100644
--- a/lib/dns/nsec3.c
+++ b/lib/dns/nsec3.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2008-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2006, 2008-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
@@ -97,15 +97,15 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
*p++ = iterations >> 8;
*p++ = iterations;
- *p++ = salt_length;
- memcpy(p, salt, salt_length);
+ *p++ = (unsigned char)salt_length;
+ memmove(p, salt, salt_length);
p += salt_length;
- *p++ = hash_length;
- memcpy(p, nexthash, hash_length);
+ *p++ = (unsigned char)hash_length;
+ memmove(p, nexthash, hash_length);
p += hash_length;
- r.length = p - buffer;
+ r.length = (unsigned int)(p - buffer);
r.base = buffer;
/*
@@ -177,7 +177,7 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
collapse_bitmap:
nsec_bits += dns_nsec_compressbitmap(nsec_bits, bm, max_type);
- r.length = nsec_bits - r.base;
+ r.length = (unsigned int)(nsec_bits - r.base);
INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);
@@ -244,7 +244,8 @@ dns_nsec3_hashname(dns_fixedname_t *result,
dns_name_downcase(name, downcased, NULL);
/* hash the node name */
- len = isc_iterated_hash(rethash, hashalg, iterations, salt, saltlength,
+ len = isc_iterated_hash(rethash, hashalg, iterations,
+ salt, (int)saltlength,
downcased->ndata, downcased->length);
if (len == 0U)
return (DNS_R_BADALG);
@@ -254,7 +255,7 @@ dns_nsec3_hashname(dns_fixedname_t *result,
/* convert the hash to base32hex */
region.base = rethash;
- region.length = len;
+ region.length = (unsigned int)len;
isc_buffer_init(&namebuffer, nametext, sizeof nametext);
isc_base32hex_totext(&region, 1, "", &namebuffer);
@@ -300,7 +301,6 @@ do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
* Create a singleton diff.
*/
dns_diff_init(diff->mctx, &temp_diff);
- temp_diff.resign = diff->resign;
ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
/*
@@ -591,7 +591,7 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
flags = nsec3.flags;
next_length = nsec3.next_length;
INSIST(next_length <= sizeof(nexthash));
- memcpy(nexthash, nsec3.next, next_length);
+ memmove(nexthash, nsec3.next, next_length);
dns_rdataset_disassociate(&rdataset);
/*
* If the NSEC3 is not for a unsecure delegation then
@@ -679,7 +679,7 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
* Fixup the previous NSEC3.
*/
nsec3.next = nexthash;
- nsec3.next_length = next_length;
+ nsec3.next_length = (unsigned char)next_length;
isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
dns_rdatatype_nsec3, &nsec3,
@@ -688,7 +688,7 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
rdataset.ttl, &rdata, &tuple));
CHECK(do_one_tuple(&tuple, db, version, diff));
INSIST(old_length <= sizeof(nexthash));
- memcpy(nexthash, old_next, old_length);
+ memmove(nexthash, old_next, old_length);
if (!CREATE(nsec3param->flags))
flags = nsec3.flags;
dns_rdata_reset(&rdata);
@@ -798,7 +798,7 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
* Fixup the previous NSEC3.
*/
nsec3.next = nexthash;
- nsec3.next_length = next_length;
+ nsec3.next_length = (unsigned char)next_length;
isc_buffer_init(&buffer, nsec3buf,
sizeof(nsec3buf));
CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
@@ -809,7 +809,7 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
&tuple));
CHECK(do_one_tuple(&tuple, db, version, diff));
INSIST(old_length <= sizeof(nexthash));
- memcpy(nexthash, old_next, old_length);
+ memmove(nexthash, old_next, old_length);
if (!CREATE(nsec3param->flags))
flags = nsec3.flags;
dns_rdata_reset(&rdata);
@@ -939,7 +939,7 @@ dns_nsec3param_fromprivate(dns_rdata_t *src, dns_rdata_t *target,
isc_buffer_init(&buf1, src->data + 1, src->length - 1);
isc_buffer_add(&buf1, src->length - 1);
isc_buffer_setactive(&buf1, src->length - 1);
- isc_buffer_init(&buf2, buf, buflen);
+ isc_buffer_init(&buf2, buf, (unsigned int)buflen);
dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
result = dns_rdata_fromwire(target, src->rdclass,
dns_rdatatype_nsec3param,
@@ -958,7 +958,7 @@ dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target,
REQUIRE(DNS_RDATA_INITIALIZED(target));
- memcpy(buf + 1, src->data, src->length);
+ memmove(buf + 1, src->data, src->length);
buf[0] = 0;
target->data = buf;
target->length = src->length + 1;
@@ -1097,7 +1097,7 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
dns_rdata_reset(&rdata);
dns_rdataset_current(&rdataset, &rdata);
INSIST(rdata.length <= sizeof(buf));
- memcpy(buf, rdata.data, rdata.length);
+ memmove(buf, rdata.data, rdata.length);
/*
* Private NSEC3 record length >= 6.
@@ -1361,7 +1361,7 @@ dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
if (result == ISC_R_SUCCESS) {
next_length = nsec3.next_length;
INSIST(next_length <= sizeof(nexthash));
- memcpy(nexthash, nsec3.next, next_length);
+ memmove(nexthash, nsec3.next, next_length);
}
dns_rdataset_disassociate(&rdataset);
if (result == ISC_R_NOMORE)
@@ -1405,7 +1405,7 @@ dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
* Fixup the previous NSEC3.
*/
nsec3.next = nexthash;
- nsec3.next_length = next_length;
+ nsec3.next_length = (unsigned char)next_length;
if (CREATE(nsec3param->flags))
nsec3.flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
@@ -1464,7 +1464,7 @@ dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
if (result == ISC_R_SUCCESS) {
next_length = nsec3.next_length;
INSIST(next_length <= sizeof(nexthash));
- memcpy(nexthash, nsec3.next, next_length);
+ memmove(nexthash, nsec3.next, next_length);
}
dns_rdataset_disassociate(&rdataset);
if (result == ISC_R_NOMORE)
@@ -1505,7 +1505,7 @@ dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
* Fixup the previous NSEC3.
*/
nsec3.next = nexthash;
- nsec3.next_length = next_length;
+ nsec3.next_length = (unsigned char)next_length;
isc_buffer_init(&buffer, nsec3buf,
sizeof(nsec3buf));
CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
diff --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c
index 36b8a412a3eed..cb9fb77d42198 100644
--- a/lib/dns/openssldh_link.c
+++ b/lib/dns/openssldh_link.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -608,11 +608,11 @@ BN_fromhex(BIGNUM *b, const char *str) {
s = strchr(hexdigits, tolower((unsigned char)str[i]));
RUNTIME_CHECK(s != NULL);
- high = s - hexdigits;
+ high = (unsigned int)(s - hexdigits);
s = strchr(hexdigits, tolower((unsigned char)str[i + 1]));
RUNTIME_CHECK(s != NULL);
- low = s - hexdigits;
+ low = (unsigned int)(s - hexdigits);
data[i/2] = (unsigned char)((high << 4) + low);
}
diff --git a/lib/dns/openssldsa_link.c b/lib/dns/openssldsa_link.c
index 8bea1c09e05e8..61e64db0d4a5a 100644
--- a/lib/dns/openssldsa_link.c
+++ b/lib/dns/openssldsa_link.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -523,6 +523,11 @@ openssldsa_tofile(const dst_key_t *key, const char *directory) {
if (key->keydata.dsa == NULL)
return (DST_R_NULLKEY);
+ if (key->external) {
+ priv.nelements = 0;
+ return (dst__privstruct_writefile(key, &priv, directory));
+ }
+
dsa = key->keydata.dsa;
priv.elements[cnt].tag = TAG_DSA_PRIME;
@@ -569,6 +574,7 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
#define DST_RET(a) {ret = a; goto err;}
UNUSED(pub);
+
/* read private key file */
ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv);
if (ret != ISC_R_SUCCESS)
@@ -607,6 +613,19 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
}
dst__privstruct_free(&priv, mctx);
+ if (key->external) {
+ if (pub == NULL)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ dsa->q = pub->keydata.dsa->q;
+ pub->keydata.dsa->q = NULL;
+ dsa->p = pub->keydata.dsa->p;
+ pub->keydata.dsa->p = NULL;
+ dsa->g = pub->keydata.dsa->g;
+ pub->keydata.dsa->g = NULL;
+ dsa->pub_key = pub->keydata.dsa->pub_key;
+ pub->keydata.dsa->pub_key = NULL;
+ }
+
key->key_size = BN_num_bits(dsa->p);
return (ISC_R_SUCCESS);
diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c
index c3f5061b75467..40081c2df856e 100644
--- a/lib/dns/opensslecdsa_link.c
+++ b/lib/dns/opensslecdsa_link.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013 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
@@ -371,7 +371,7 @@ opensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) {
cp = buf;
if (!i2o_ECPublicKey(eckey, &cp))
DST_RET (dst__openssl_toresult(ISC_R_FAILURE));
- memcpy(r.base, buf + 1, len);
+ memmove(r.base, buf + 1, len);
isc_buffer_add(data, len);
ret = ISC_R_SUCCESS;
@@ -414,7 +414,7 @@ opensslecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
buf[0] = POINT_CONVERSION_UNCOMPRESSED;
- memcpy(buf + 1, r.base, len);
+ memmove(buf + 1, r.base, len);
cp = buf;
if (o2i_ECPublicKey(&eckey,
(const unsigned char **) &cp,
@@ -453,6 +453,11 @@ opensslecdsa_tofile(const dst_key_t *key, const char *directory) {
if (key->keydata.pkey == NULL)
return (DST_R_NULLKEY);
+ if (key->external) {
+ priv.nelements = 0;
+ return (dst__privstruct_writefile(key, &priv, directory));
+ }
+
pkey = key->keydata.pkey;
eckey = EVP_PKEY_get1_EC_KEY(pkey);
if (eckey == NULL)
@@ -514,8 +519,9 @@ static isc_result_t
opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
dst_private_t priv;
isc_result_t ret;
- EVP_PKEY *pkey;
- EC_KEY *eckey = NULL;
+ EVP_PKEY *pkey, *pubpkey;
+ EC_KEY *eckey = NULL, *pubeckey = NULL;
+ const EC_POINT *pubkey;
BIGNUM *privkey;
int group_nid;
isc_mem_t *mctx = key->mctx;
@@ -537,16 +543,35 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
if (ret != ISC_R_SUCCESS)
goto err;
- privkey = BN_bin2bn(priv.elements[0].data,
- priv.elements[0].length, NULL);
- if (privkey == NULL)
- DST_RET(ISC_R_NOMEMORY);
- if (!EC_KEY_set_private_key(eckey, privkey))
- DST_RET(ISC_R_NOMEMORY);
- if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS)
- DST_RET(DST_R_INVALIDPRIVATEKEY);
- dst__privstruct_free(&priv, mctx);
- memset(&priv, 0, sizeof(priv));
+ if (key->external) {
+ /*
+ * Copy the public key to this new key.
+ */
+ if (pub == NULL)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ pubpkey = pub->keydata.pkey;
+ pubeckey = EVP_PKEY_get1_EC_KEY(pubpkey);
+ if (pubeckey == NULL)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ pubkey = EC_KEY_get0_public_key(pubeckey);
+ if (pubkey == NULL)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ if (EC_KEY_set_public_key(eckey, pubkey) != 1)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ if (EC_KEY_check_key(eckey) != 1)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ } else {
+ privkey = BN_bin2bn(priv.elements[0].data,
+ priv.elements[0].length, NULL);
+ if (privkey == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ if (!EC_KEY_set_private_key(eckey, privkey))
+ DST_RET(ISC_R_NOMEMORY);
+ if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ }
pkey = EVP_PKEY_new();
if (pkey == NULL)
@@ -561,6 +586,8 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
err:
if (eckey != NULL)
EC_KEY_free(eckey);
+ if (pubeckey != NULL)
+ EC_KEY_free(pubeckey);
dst__privstruct_free(&priv, mctx);
memset(&priv, 0, sizeof(priv));
return (ret);
diff --git a/lib/dns/opensslgost_link.c b/lib/dns/opensslgost_link.c
index 1ce4405eb21d1..b0578661f97f2 100644
--- a/lib/dns/opensslgost_link.c
+++ b/lib/dns/opensslgost_link.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 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
@@ -253,7 +253,7 @@ opensslgost_todns(const dst_key_t *key, isc_buffer_t *data) {
len = i2d_PUBKEY(pkey, &p);
INSIST(len == sizeof(der));
INSIST(memcmp(gost_prefix, der, 37) == 0);
- memcpy(r.base, der + 37, 64);
+ memmove(r.base, der + 37, 64);
isc_buffer_add(data, 64);
return (ISC_R_SUCCESS);
@@ -272,8 +272,8 @@ opensslgost_fromdns(dst_key_t *key, isc_buffer_t *data) {
if (r.length != 64)
return (DST_R_INVALIDPUBLICKEY);
- memcpy(der, gost_prefix, 37);
- memcpy(der + 37, r.base, 64);
+ memmove(der, gost_prefix, 37);
+ memmove(der + 37, r.base, 64);
isc_buffer_forward(data, 64);
p = der;
@@ -296,6 +296,11 @@ opensslgost_tofile(const dst_key_t *key, const char *directory) {
if (key->keydata.pkey == NULL)
return (DST_R_NULLKEY);
+ if (key->external) {
+ priv.nelements = 0;
+ return (dst__privstruct_writefile(key, &priv, directory));
+ }
+
pkey = key->keydata.pkey;
len = i2d_PrivateKey(pkey, NULL);
@@ -337,13 +342,21 @@ opensslgost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
if (ret != ISC_R_SUCCESS)
return (ret);
- INSIST(priv.elements[0].tag == TAG_GOST_PRIVASN1);
- p = priv.elements[0].data;
- if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p,
- (long) priv.elements[0].length) == NULL)
- DST_RET(dst__openssl_toresult2("d2i_PrivateKey",
- DST_R_INVALIDPRIVATEKEY));
- key->keydata.pkey = pkey;
+ if (key->external) {
+ INSIST(priv.nelements == 0);
+ if (pub == NULL)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ key->keydata.pkey = pub->keydata.pkey;
+ pub->keydata.pkey = NULL;
+ } else {
+ INSIST(priv.elements[0].tag == TAG_GOST_PRIVASN1);
+ p = priv.elements[0].data;
+ if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p,
+ (long) priv.elements[0].length) == NULL)
+ DST_RET(dst__openssl_toresult2("d2i_PrivateKey",
+ DST_R_INVALIDPRIVATEKEY));
+ key->keydata.pkey = pkey;
+ }
key->key_size = EVP_PKEY_bits(pkey);
dst__privstruct_free(&priv, mctx);
memset(&priv, 0, sizeof(priv));
diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c
index fa7412cbddbd7..8421c640708a7 100644
--- a/lib/dns/opensslrsa_link.c
+++ b/lib/dns/opensslrsa_link.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011-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
@@ -481,7 +481,7 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
INSIST(prefixlen + digestlen <= sizeof(digest));
memmove(digest + prefixlen, digest, digestlen);
- memcpy(digest, prefix, prefixlen);
+ memmove(digest, prefix, prefixlen);
status = RSA_private_encrypt(digestlen + prefixlen,
digest, r.base, rsa,
RSA_PKCS1_PADDING);
@@ -1048,8 +1048,14 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) {
return (DST_R_NULLKEY);
rsa = key->keydata.rsa;
#endif
-
memset(bufs, 0, sizeof(bufs));
+
+ if (key->external) {
+ priv.nelements = 0;
+ result = dst__privstruct_writefile(key, &priv, directory);
+ goto fail;
+ }
+
for (i = 0; i < 8; i++) {
bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(rsa->n));
if (bufs[i] == NULL) {
@@ -1205,6 +1211,9 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
if (ret != ISC_R_SUCCESS)
goto err;
+ if (key->external && priv.nelements != 0)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+
for (i = 0; i < priv.nelements; i++) {
switch (priv.elements[i].tag) {
case TAG_RSA_ENGINE:
@@ -1217,6 +1226,7 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
break;
}
}
+
/*
* Is this key is stored in a HSM?
* See if we can fetch it.
@@ -1328,8 +1338,10 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
DST_RET(DST_R_INVALIDPRIVATEKEY);
- if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS)
- DST_RET(ISC_R_RANGE);
+ if (!key->external) {
+ if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS)
+ DST_RET(ISC_R_RANGE);
+ }
key->key_size = BN_num_bits(rsa->n);
if (pubrsa != NULL)
RSA_free(pubrsa);
diff --git a/lib/dns/portlist.c b/lib/dns/portlist.c
index 5bc89f4829840..754eef6687922 100644
--- a/lib/dns/portlist.c
+++ b/lib/dns/portlist.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -80,7 +80,7 @@ dns_portlist_create(isc_mem_t *mctx, dns_portlist_t **portlistp) {
portlist = isc_mem_get(mctx, sizeof(*portlist));
if (portlist == NULL)
return (ISC_R_NOMEMORY);
- result = isc_mutex_init(&portlist->lock);
+ result = isc_mutex_init(&portlist->lock);
if (result != ISC_R_SUCCESS) {
isc_mem_put(mctx, portlist, sizeof(*portlist));
return (result);
@@ -111,7 +111,7 @@ find_port(dns_element_t *list, unsigned int len, in_port_t port) {
for (;;) {
if (list[xtry].port == port)
return (&list[xtry]);
- if (port > list[xtry].port) {
+ if (port > list[xtry].port) {
if (xtry == max)
break;
min = xtry;
@@ -164,8 +164,8 @@ dns_portlist_add(dns_portlist_t *portlist, int af, in_port_t port) {
goto unlock;
}
if (portlist->list != NULL) {
- memcpy(el, portlist->list,
- portlist->allocated * sizeof(*el));
+ memmove(el, portlist->list,
+ portlist->allocated * sizeof(*el));
isc_mem_put(portlist->mctx, portlist->list,
portlist->allocated * sizeof(*el));
}
@@ -215,7 +215,7 @@ isc_boolean_t
dns_portlist_match(dns_portlist_t *portlist, int af, in_port_t port) {
dns_element_t *el;
isc_boolean_t result = ISC_FALSE;
-
+
REQUIRE(DNS_VALID_PORTLIST(portlist));
REQUIRE(af == AF_INET || af == AF_INET6);
LOCK(&portlist->lock);
@@ -227,7 +227,7 @@ dns_portlist_match(dns_portlist_t *portlist, int af, in_port_t port) {
if (af == AF_INET6 && (el->flags & DNS_PL_INET6) != 0)
result = ISC_TRUE;
}
- }
+ }
UNLOCK(&portlist->lock);
return (result);
}
diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c
index 7381b4a325b35..d97fcce28eb9b 100644
--- a/lib/dns/rbt.c
+++ b/lib/dns/rbt.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-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -1479,8 +1479,8 @@ create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
OLDOFFSETLEN(node) = OFFSETLEN(node) = labels;
ATTRS(node) = name->attributes;
- memcpy(NAME(node), region.base, region.length);
- memcpy(OFFSETS(node), name->offsets, labels);
+ memmove(NAME(node), region.base, region.length);
+ memmove(OFFSETS(node), name->offsets, labels);
#if DNS_RBT_USEMAGIC
node->magic = DNS_RBTNODE_MAGIC;
@@ -1841,7 +1841,7 @@ dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp) {
* information, which will be needed when linking up
* delete to the successor's old location.
*/
- memcpy(tmp, successor, sizeof(dns_rbtnode_t));
+ memmove(tmp, successor, sizeof(dns_rbtnode_t));
if (IS_ROOT(delete)) {
*rootp = successor;
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index bff52b87ef9d2..013bf34a0a09c 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.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
@@ -1121,8 +1121,8 @@ newversion(dns_db_t *db, dns_dbversion_t **versionp) {
version->hash = rbtdb->current_version->hash;
version->salt_length =
rbtdb->current_version->salt_length;
- memcpy(version->salt, rbtdb->current_version->salt,
- version->salt_length);
+ memmove(version->salt, rbtdb->current_version->salt,
+ version->salt_length);
} else {
version->flags = 0;
version->iterations = 0;
@@ -1706,8 +1706,11 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
nodelock = &rbtdb->node_locks[bucket];
+#define KEEP_NODE(n, r) \
+ ((n)->data != NULL || (n)->down != NULL || (n) == (r)->origin_node)
+
/* Handle easy and typical case first. */
- if (!node->dirty && (node->data != NULL || node->down != NULL)) {
+ if (!node->dirty && KEEP_NODE(node, rbtdb)) {
dns_rbtnode_refdecrement(node, &nrefs);
INSIST((int)nrefs >= 0);
if (nrefs == 0) {
@@ -1776,12 +1779,11 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
isc_refcount_decrement(&nodelock->references, &refs);
INSIST((int)refs >= 0);
- /*
- * XXXDCL should this only be done for cache zones?
- */
- if (node->data != NULL || node->down != NULL)
+ if (KEEP_NODE(node, rbtdb))
goto restore_locks;
+#undef KEEP_NODE
+
if (write_locked) {
/*
* We can now delete the node.
@@ -2127,8 +2129,8 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version) {
if (nsec3param.flags != 0)
continue;
- memcpy(version->salt, nsec3param.salt,
- nsec3param.salt_length);
+ memmove(version->salt, nsec3param.salt,
+ nsec3param.salt_length);
version->hash = nsec3param.hash;
version->salt_length = nsec3param.salt_length;
version->iterations = nsec3param.iterations;
@@ -4168,7 +4170,7 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
header_prev = NULL;
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
- if (header->rdh_ttl <= search->now) {
+ if (header->rdh_ttl < search->now) {
/*
* This rdataset is stale. If no one else is
* using the node, we can clean it up right
@@ -4176,7 +4178,7 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
* the node as dirty, so it will get cleaned
* up later.
*/
- if ((header->rdh_ttl <= search->now - RBTDB_VIRTUAL) &&
+ if ((header->rdh_ttl < search->now - RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
/*
@@ -4292,7 +4294,7 @@ find_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node,
header != NULL;
header = header_next) {
header_next = header->next;
- if (header->rdh_ttl <= search->now) {
+ if (header->rdh_ttl < search->now) {
/*
* This rdataset is stale. If no one else is
* using the node, we can clean it up right
@@ -4300,7 +4302,7 @@ find_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node,
* the node as dirty, so it will get cleaned
* up later.
*/
- if ((header->rdh_ttl <= search->now -
+ if ((header->rdh_ttl < search->now -
RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
@@ -4469,7 +4471,7 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
header != NULL;
header = header_next) {
header_next = header->next;
- if (header->rdh_ttl <= now) {
+ if (header->rdh_ttl < now) {
/*
* This rdataset is stale. If no one else is
* using the node, we can clean it up right
@@ -4477,7 +4479,7 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
* node as dirty, so it will get cleaned up
* later.
*/
- if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
+ if ((header->rdh_ttl < now - RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
/*
@@ -4626,12 +4628,12 @@ rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
switch (rdata.type) {
case dns_rdatatype_a:
INSIST(rdata.length == 4);
- memcpy(&ina.s_addr, rdata.data, 4);
+ memmove(&ina.s_addr, rdata.data, 4);
isc_netaddr_fromin(&netaddr, &ina);
break;
case dns_rdatatype_aaaa:
INSIST(rdata.length == 16);
- memcpy(in6a.s6_addr, rdata.data, 16);
+ memmove(in6a.s6_addr, rdata.data, 16);
isc_netaddr_fromin6(&netaddr, &in6a);
break;
default:
@@ -4876,14 +4878,14 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
header_prev = NULL;
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
- if (header->rdh_ttl <= now) {
+ if (header->rdh_ttl < now) {
/*
* This rdataset is stale. If no one else is using the
* node, we can clean it up right now, otherwise we
* mark it as stale, and the node as dirty, so it will
* get cleaned up later.
*/
- if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
+ if ((header->rdh_ttl < now - RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
/*
@@ -5183,14 +5185,14 @@ cache_findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
header_prev = NULL;
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
- if (header->rdh_ttl <= now) {
+ if (header->rdh_ttl < now) {
/*
* This rdataset is stale. If no one else is using the
* node, we can clean it up right now, otherwise we
* mark it as stale, and the node as dirty, so it will
* get cleaned up later.
*/
- if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
+ if ((header->rdh_ttl < now - RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
/*
@@ -5672,8 +5674,8 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
for (header = rbtnode->data; header != NULL; header = header_next) {
header_next = header->next;
- if (header->rdh_ttl <= now) {
- if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
+ if (header->rdh_ttl < now) {
+ if ((header->rdh_ttl < now - RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
/*
@@ -5981,7 +5983,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
}
}
if (topheader != NULL && EXISTS(topheader) &&
- topheader->rdh_ttl > now) {
+ topheader->rdh_ttl >= now) {
/*
* Found one.
*/
@@ -6047,7 +6049,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* has no effect, provided that the cache data isn't stale.
*/
if (rbtversion == NULL && trust < header->trust &&
- (header->rdh_ttl > now || header_nx)) {
+ (header->rdh_ttl >= now || header_nx)) {
free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
if (addedrdataset != NULL)
bind_rdataset(rbtdb, rbtnode, header, now,
@@ -6117,7 +6119,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* Don't lower trust of existing record if the
* update is forced.
*/
- if (IS_CACHE(rbtdb) && header->rdh_ttl > now &&
+ if (IS_CACHE(rbtdb) && header->rdh_ttl >= now &&
header->type == dns_rdatatype_ns &&
!header_nx && !newheader_nx &&
header->trust >= newheader->trust &&
@@ -6153,7 +6155,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* to be no more than the current NS RRset's TTL. This
* ensures the delegations that are withdrawn are honoured.
*/
- if (IS_CACHE(rbtdb) && header->rdh_ttl > now &&
+ if (IS_CACHE(rbtdb) && header->rdh_ttl >= now &&
header->type == dns_rdatatype_ns &&
!header_nx && !newheader_nx &&
header->trust <= newheader->trust) {
@@ -6161,7 +6163,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
newheader->rdh_ttl = header->rdh_ttl;
}
}
- if (IS_CACHE(rbtdb) && header->rdh_ttl > now &&
+ if (IS_CACHE(rbtdb) && header->rdh_ttl >= now &&
(header->type == dns_rdatatype_a ||
header->type == dns_rdatatype_aaaa ||
header->type == dns_rdatatype_ds ||
@@ -6564,7 +6566,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
cleanup_dead_nodes(rbtdb, rbtnode->locknum);
header = isc_heap_element(rbtdb->heaps[rbtnode->locknum], 1);
- if (header && header->rdh_ttl <= now - RBTDB_VIRTUAL)
+ if (header && header->rdh_ttl < now - RBTDB_VIRTUAL)
expire_header(rbtdb, header, tree_locked);
/*
@@ -6868,28 +6870,21 @@ static isc_result_t
loadnode(dns_rbtdb_t *rbtdb, dns_name_t *name, dns_rbtnode_t **nodep,
isc_boolean_t hasnsec)
{
- isc_result_t noderesult, nsecresult;
- dns_rbtnode_t *nsecnode;
-
- noderesult = dns_rbt_addnode(rbtdb->tree, name, nodep);
-
-#ifdef BIND9
- if (noderesult == ISC_R_SUCCESS && rbtdb->rpz_cidr != NULL)
- dns_rpz_cidr_addip(rbtdb->rpz_cidr, name);
-#endif
+ isc_result_t noderesult, nsecresult, tmpresult;
+ dns_rbtnode_t *nsecnode = NULL, *node = NULL;
+ noderesult = dns_rbt_addnode(rbtdb->tree, name, &node);
if (!hasnsec)
- return (noderesult);
+ goto done;
if (noderesult == ISC_R_EXISTS) {
/*
* Add a node to the auxiliary NSEC tree for an old node
* just now getting an NSEC record.
*/
- if ((*nodep)->nsec == DNS_RBT_NSEC_HAS_NSEC)
- return (noderesult);
- } else if (noderesult != ISC_R_SUCCESS) {
- return (noderesult);
- }
+ if (node->nsec == DNS_RBT_NSEC_HAS_NSEC)
+ goto done;
+ } else if (noderesult != ISC_R_SUCCESS)
+ goto done;
/*
* Build the auxiliary tree for NSECs as we go.
@@ -6899,12 +6894,11 @@ loadnode(dns_rbtdb_t *rbtdb, dns_name_t *name, dns_rbtnode_t **nodep,
* Add nodes to the auxiliary tree after corresponding nodes have
* been added to the main tree.
*/
- nsecnode = NULL;
nsecresult = dns_rbt_addnode(rbtdb->nsec, name, &nsecnode);
if (nsecresult == ISC_R_SUCCESS) {
nsecnode->nsec = DNS_RBT_NSEC_NSEC;
- (*nodep)->nsec = DNS_RBT_NSEC_HAS_NSEC;
- return (noderesult);
+ node->nsec = DNS_RBT_NSEC_HAS_NSEC;
+ goto done;
}
if (nsecresult == ISC_R_EXISTS) {
@@ -6915,21 +6909,41 @@ loadnode(dns_rbtdb_t *rbtdb, dns_name_t *name, dns_rbtnode_t **nodep,
ISC_LOG_WARNING,
"addnode: NSEC node already exists");
#endif
- (*nodep)->nsec = DNS_RBT_NSEC_HAS_NSEC;
- return (noderesult);
+ node->nsec = DNS_RBT_NSEC_HAS_NSEC;
+ goto done;
}
- nsecresult = dns_rbt_deletenode(rbtdb->tree, *nodep, ISC_FALSE);
- if (nsecresult != ISC_R_SUCCESS)
- isc_log_write(dns_lctx,
- DNS_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_CACHE,
- ISC_LOG_WARNING,
- "loading_addrdataset: "
- "dns_rbt_deletenode: %s after "
- "dns_rbt_addnode(NSEC): %s",
- isc_result_totext(nsecresult),
- isc_result_totext(noderesult));
+ if (noderesult == ISC_R_SUCCESS) {
+ /*
+ * Remove the node we just added above.
+ */
+ tmpresult = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);
+ if (tmpresult != ISC_R_SUCCESS)
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE,
+ ISC_LOG_WARNING,
+ "loading_addrdataset: "
+ "dns_rbt_deletenode: %s after "
+ "dns_rbt_addnode(NSEC): %s",
+ isc_result_totext(tmpresult),
+ isc_result_totext(noderesult));
+
+ }
+
+ /*
+ * Set the error condition to be returned.
+ */
+ noderesult = nsecresult;
+
+ done:
+#ifdef BIND9
+ if (noderesult == ISC_R_SUCCESS && rbtdb->rpz_cidr != NULL)
+ dns_rpz_cidr_addip(rbtdb->rpz_cidr, name);
+#endif
+ if (noderesult == ISC_R_SUCCESS || noderesult == ISC_R_EXISTS)
+ *nodep = node;
+
return (noderesult);
}
@@ -7266,7 +7280,8 @@ getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash,
*hash = rbtversion->hash;
if (salt != NULL && salt_length != NULL) {
REQUIRE(*salt_length >= rbtversion->salt_length);
- memcpy(salt, rbtversion->salt, rbtversion->salt_length);
+ memmove(salt, rbtversion->salt,
+ rbtversion->salt_length);
}
if (salt_length != NULL)
*salt_length = rbtversion->salt_length;
@@ -9289,7 +9304,7 @@ overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
isc_rwlocktype_write);
header = isc_heap_element(rbtdb->heaps[locknum], 1);
- if (header && header->rdh_ttl <= now - RBTDB_VIRTUAL) {
+ if (header && header->rdh_ttl < now - RBTDB_VIRTUAL) {
expire_header(rbtdb, header, tree_locked);
purgecount--;
}
diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c
index 0b7fe8c28051d..69007f881efdf 100644
--- a/lib/dns/rcode.c
+++ b/lib/dns/rcode.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 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
@@ -194,7 +194,7 @@ str_totext(const char *source, isc_buffer_t *target) {
if (l > region.length)
return (ISC_R_NOSPACE);
- memcpy(region.base, source, l);
+ memmove(region.base, source, l);
isc_buffer_add(target, l);
return (ISC_R_SUCCESS);
}
@@ -381,9 +381,9 @@ dns_keyflags_fromtext(dns_keyflags_t *flagsp, isc_textregion_t *source)
unsigned int len;
char *delim = memchr(text, '|', end - text);
if (delim != NULL)
- len = delim - text;
+ len = (unsigned int)(delim - text);
else
- len = end - text;
+ len = (unsigned int)(end - text);
for (p = keyflags; p->name != NULL; p++) {
if (strncasecmp(p->name, text, len) == 0)
break;
diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c
index a83dab462ce52..5bdd1255b5f75 100644
--- a/lib/dns/rdata.c
+++ b/lib/dns/rdata.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) 1998-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -281,7 +281,7 @@ locator_pton(const char *src, unsigned char *dst) {
}
if (tp != endp)
return (0);
- memcpy(dst, tmp, NS_LOCATORSZ);
+ memmove(dst, tmp, NS_LOCATORSZ);
return (1);
}
@@ -322,7 +322,7 @@ mem_maybedup(isc_mem_t *mctx, void *source, size_t length) {
return (source);
new = isc_mem_allocate(mctx, length);
if (new != NULL)
- memcpy(new, source, length);
+ memmove(new, source, length);
return (new);
}
@@ -502,7 +502,7 @@ dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
isc_buffer_t st;
isc_boolean_t use_default = ISC_FALSE;
isc_uint32_t activelength;
- size_t length;
+ unsigned int length;
REQUIRE(dctx != NULL);
if (rdata != NULL) {
@@ -589,7 +589,7 @@ dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
isc_buffer_availableregion(target, &tr);
if (tr.length < rdata->length)
return (ISC_R_NOSPACE);
- memcpy(tr.base, rdata->data, rdata->length);
+ memmove(tr.base, rdata->data, rdata->length);
isc_buffer_add(target, rdata->length);
return (ISC_R_SUCCESS);
}
@@ -683,7 +683,7 @@ dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
unsigned long line;
void (*callback)(dns_rdatacallbacks_t *, const char *, ...);
isc_result_t tresult;
- size_t length;
+ unsigned int length;
isc_boolean_t unknown;
REQUIRE(origin == NULL || dns_name_isabsolute(origin) == ISC_TRUE);
@@ -916,7 +916,7 @@ dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
isc_buffer_t st;
isc_region_t region;
isc_boolean_t use_default = ISC_FALSE;
- size_t length;
+ unsigned int length;
REQUIRE(source != NULL);
if (rdata != NULL) {
@@ -1179,7 +1179,7 @@ txt_totext(isc_region_t *source, isc_buffer_t *target) {
return (ISC_R_NOSPACE);
*tp++ = '"';
tl--;
- isc_buffer_add(target, tp - (char *)region.base);
+ isc_buffer_add(target, (unsigned int)(tp - (char *)region.base));
isc_region_consume(source, *source->base + 1);
return (ISC_R_SUCCESS);
}
@@ -1245,7 +1245,7 @@ txt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
}
if (escape)
return (DNS_R_SYNTAX);
- *tregion.base = t - tregion.base - 1;
+ *tregion.base = (unsigned char)(t - tregion.base - 1);
isc_buffer_add(target, *tregion.base + 1);
return (ISC_R_SUCCESS);
}
@@ -1268,7 +1268,7 @@ txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
return (ISC_R_NOSPACE);
if (tregion.base != sregion.base)
- memcpy(tregion.base, sregion.base, n);
+ memmove(tregion.base, sregion.base, n);
isc_buffer_forward(source, n);
isc_buffer_add(target, n);
return (ISC_R_SUCCESS);
@@ -1326,7 +1326,7 @@ multitxt_totext(isc_region_t *source, isc_buffer_t *target) {
return (ISC_R_NOSPACE);
*tp++ = '"';
tl--;
- isc_buffer_add(target, tp - (char *)region.base);
+ isc_buffer_add(target, (unsigned int)(tp - (char *)region.base));
return (ISC_R_SUCCESS);
}
@@ -1390,7 +1390,7 @@ multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
}
if (escape)
return (DNS_R_SYNTAX);
- *t0 = t - t0 - 1;
+ *t0 = (unsigned char)(t - t0 - 1);
isc_buffer_add(target, *t0 + 1);
} while (n != 0);
return (ISC_R_SUCCESS);
@@ -1418,7 +1418,7 @@ multitxt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
return (ISC_R_NOSPACE);
if (tregion.base != sregion.base)
- memcpy(tregion.base, sregion.base, n);
+ memmove(tregion.base, sregion.base, n);
isc_buffer_forward(source, n);
isc_buffer_add(target, n);
isc_buffer_activeregion(source, &sregion);
@@ -1469,7 +1469,7 @@ str_totext(const char *source, isc_buffer_t *target) {
if (l > region.length)
return (ISC_R_NOSPACE);
- memcpy(region.base, source, l);
+ memmove(region.base, source, l);
isc_buffer_add(target, l);
return (ISC_R_SUCCESS);
}
@@ -1595,7 +1595,7 @@ mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
if (length > tr.length)
return (ISC_R_NOSPACE);
if (tr.base != base)
- memcpy(tr.base, base, length);
+ memmove(tr.base, base, length);
isc_buffer_add(target, length);
return (ISC_R_SUCCESS);
}
@@ -1613,7 +1613,7 @@ hexvalue(char value) {
c = tolower(c);
if ((s = strchr(hexdigits, c)) == NULL)
return (-1);
- return (s - hexdigits);
+ return (int)(s - hexdigits);
}
static int
@@ -1628,7 +1628,7 @@ decvalue(char value) {
return (-1);
if ((s = strchr(decdigits, value)) == NULL)
return (-1);
- return (s - decdigits);
+ return (int)(s - decdigits);
}
static const char atob_digits[86] =
@@ -1688,15 +1688,15 @@ byte_atob(int c, isc_buffer_t *target, struct state *state) {
}
} else if ((s = strchr(atob_digits, c)) != NULL) {
if (bcount == 0) {
- word = s - atob_digits;
+ word = (isc_int32_t)(s - atob_digits);
++bcount;
} else if (bcount < 4) {
word = times85(word);
- word += s - atob_digits;
+ word += (isc_int32_t)(s - atob_digits);
++bcount;
} else {
word = times85(word);
- word += s - atob_digits;
+ word += (isc_int32_t)(s - atob_digits);
RETERR(putbyte((word >> 24) & 0xff, target, state));
RETERR(putbyte((word >> 16) & 0xff, target, state));
RETERR(putbyte((word >> 8) & 0xff, target, state));
diff --git a/lib/dns/rdata/ch_3/a_1.c b/lib/dns/rdata/ch_3/a_1.c
index e3f98106514d1..d25fcb50ac40d 100644
--- a/lib/dns/rdata/ch_3/a_1.c
+++ b/lib/dns/rdata/ch_3/a_1.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005, 2007, 2009, 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
@@ -117,7 +117,7 @@ fromwire_ch_a(ARGS_FROMWIRE) {
if (tregion.length < 2)
return (ISC_R_NOSPACE);
- memcpy(tregion.base, sregion.base, 2);
+ memmove(tregion.base, sregion.base, 2);
isc_buffer_forward(source, 2);
isc_buffer_add(target, 2);
@@ -149,7 +149,7 @@ towire_ch_a(ARGS_TOWIRE) {
if (tregion.length < 2)
return (ISC_R_NOSPACE);
- memcpy(tregion.base, sregion.base, 2);
+ memmove(tregion.base, sregion.base, 2);
isc_buffer_add(target, 2);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/generic/afsdb_18.c b/lib/dns/rdata/generic/afsdb_18.c
index 279f86c677d77..af95fa12e91b6 100644
--- a/lib/dns/rdata/generic/afsdb_18.c
+++ b/lib/dns/rdata/generic/afsdb_18.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-2001, 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -113,7 +113,7 @@ fromwire_afsdb(ARGS_FROMWIRE) {
return (ISC_R_NOSPACE);
if (sr.length < 2)
return (ISC_R_UNEXPECTEDEND);
- memcpy(tr.base, sr.base, 2);
+ memmove(tr.base, sr.base, 2);
isc_buffer_forward(source, 2);
isc_buffer_add(target, 2);
return (dns_name_fromwire(&name, source, dctx, options, target));
@@ -134,7 +134,7 @@ towire_afsdb(ARGS_TOWIRE) {
dns_rdata_toregion(rdata, &sr);
if (tr.length < 2)
return (ISC_R_NOSPACE);
- memcpy(tr.base, sr.base, 2);
+ memmove(tr.base, sr.base, 2);
isc_region_consume(&sr, 2);
isc_buffer_add(target, 2);
diff --git a/lib/dns/rdata/generic/dnskey_48.c b/lib/dns/rdata/generic/dnskey_48.c
index 688e7ac5e18f3..aa705cab36848 100644
--- a/lib/dns/rdata/generic/dnskey_48.c
+++ b/lib/dns/rdata/generic/dnskey_48.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -32,6 +32,7 @@
static inline isc_result_t
fromtext_dnskey(ARGS_FROMTEXT) {
+ isc_result_t result;
isc_token_t token;
dns_secalg_t alg;
dns_secproto_t proto;
@@ -67,7 +68,15 @@ fromtext_dnskey(ARGS_FROMTEXT) {
if ((flags & 0xc000) == 0xc000)
return (ISC_R_SUCCESS);
- return (isc_base64_tobuffer(lexer, target, -1));
+ 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
@@ -185,6 +194,15 @@ fromwire_dnskey(ARGS_FROMWIRE) {
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));
diff --git a/lib/dns/rdata/generic/eui48_108.c b/lib/dns/rdata/generic/eui48_108.c
index 3e52fec0ed4a2..b25a7b7e03e43 100644
--- a/lib/dns/rdata/generic/eui48_108.c
+++ b/lib/dns/rdata/generic/eui48_108.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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
@@ -142,7 +142,7 @@ tostruct_eui48(ARGS_TOSTRUCT) {
eui48->common.rdtype = rdata->type;
ISC_LINK_INIT(&eui48->common, link);
- memcpy(eui48->eui48, rdata->data, rdata->length);
+ memmove(eui48->eui48, rdata->data, rdata->length);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/generic/eui64_109.c b/lib/dns/rdata/generic/eui64_109.c
index 245994fdf5c0b..33d2f637c8257 100644
--- a/lib/dns/rdata/generic/eui64_109.c
+++ b/lib/dns/rdata/generic/eui64_109.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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
@@ -147,7 +147,7 @@ tostruct_eui64(ARGS_TOSTRUCT) {
eui64->common.rdtype = rdata->type;
ISC_LINK_INIT(&eui64->common, link);
- memcpy(eui64->eui64, rdata->data, rdata->length);
+ memmove(eui64->eui64, rdata->data, rdata->length);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/generic/hip_55.c b/lib/dns/rdata/generic/hip_55.c
index 5a5140f8ddd6f..5198497dcb078 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 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009, 2011, 2013 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
@@ -76,7 +76,7 @@ fromtext_hip(ARGS_FROMTEXT) {
len = (unsigned char *)isc_buffer_used(target) - start;
if (len > 0xffU)
RETTOK(ISC_R_RANGE);
- RETERR(uint8_tobuffer(len, &hit_len));
+ RETERR(uint8_tobuffer((isc_uint32_t)len, &hit_len));
/*
* Public key (base64).
@@ -92,7 +92,7 @@ fromtext_hip(ARGS_FROMTEXT) {
len = (unsigned char *)isc_buffer_used(target) - start;
if (len > 0xffffU)
RETTOK(ISC_R_RANGE);
- RETERR(uint16_tobuffer(len, &key_len));
+ RETERR(uint16_tobuffer((isc_uint32_t)len, &key_len));
/*
* Rendezvous Servers.
@@ -122,7 +122,7 @@ static inline isc_result_t
totext_hip(ARGS_TOTEXT) {
isc_region_t region;
dns_name_t name;
- size_t length, key_len, hit_len;
+ unsigned int length, key_len, hit_len;
unsigned char algorithm;
char buf[sizeof("225 ")];
diff --git a/lib/dns/rdata/generic/ipseckey_45.c b/lib/dns/rdata/generic/ipseckey_45.c
index 1d2508c42e253..230d0d1e1e829 100644
--- a/lib/dns/rdata/generic/ipseckey_45.c
+++ b/lib/dns/rdata/generic/ipseckey_45.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005, 2007, 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
@@ -87,7 +87,7 @@ fromtext_ipseckey(ARGS_FROMTEXT) {
isc_buffer_availableregion(target, &region);
if (region.length < 4)
return (ISC_R_NOSPACE);
- memcpy(region.base, &addr, 4);
+ memmove(region.base, &addr, 4);
isc_buffer_add(target, 4);
break;
@@ -97,7 +97,7 @@ fromtext_ipseckey(ARGS_FROMTEXT) {
isc_buffer_availableregion(target, &region);
if (region.length < 16)
return (ISC_R_NOSPACE);
- memcpy(region.base, addr6, 16);
+ memmove(region.base, addr6, 16);
isc_buffer_add(target, 16);
break;
@@ -364,7 +364,7 @@ tostruct_ipseckey(ARGS_TOSTRUCT) {
break;
case 2:
- memcpy(ipseckey->in6_addr.s6_addr, region.base, 16);
+ memmove(ipseckey->in6_addr.s6_addr, region.base, 16);
isc_region_consume(&region, 16);
break;
diff --git a/lib/dns/rdata/generic/isdn_20.c b/lib/dns/rdata/generic/isdn_20.c
index 5aac73f3713f9..0bf2146013e8a 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 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -127,6 +127,8 @@ fromstruct_isdn(ARGS_FROMSTRUCT) {
RETERR(uint8_tobuffer(isdn->isdn_len, target));
RETERR(mem_tobuffer(target, isdn->isdn, isdn->isdn_len));
+ if (isdn->subaddress == NULL)
+ return (ISC_R_SUCCESS);
RETERR(uint8_tobuffer(isdn->subaddress_len, target));
return (mem_tobuffer(target, isdn->subaddress, isdn->subaddress_len));
}
@@ -153,11 +155,17 @@ tostruct_isdn(ARGS_TOSTRUCT) {
return (ISC_R_NOMEMORY);
isc_region_consume(&r, isdn->isdn_len);
- isdn->subaddress_len = uint8_fromregion(&r);
- isc_region_consume(&r, 1);
- isdn->subaddress = mem_maybedup(mctx, r.base, isdn->subaddress_len);
- if (isdn->subaddress == NULL)
- goto cleanup;
+ if (r.length == 0) {
+ isdn->subaddress_len = 0;
+ isdn->subaddress = NULL;
+ } else {
+ isdn->subaddress_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ isdn->subaddress = mem_maybedup(mctx, r.base,
+ isdn->subaddress_len);
+ if (isdn->subaddress == NULL)
+ goto cleanup;
+ }
isdn->mctx = mctx;
return (ISC_R_SUCCESS);
diff --git a/lib/dns/rdata/generic/key_25.c b/lib/dns/rdata/generic/key_25.c
index 1d0ba83a9b314..f55401e1b8acd 100644
--- a/lib/dns/rdata/generic/key_25.c
+++ b/lib/dns/rdata/generic/key_25.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -32,6 +32,7 @@
static inline isc_result_t
fromtext_key(ARGS_FROMTEXT) {
+ isc_result_t result;
isc_token_t token;
dns_secalg_t alg;
dns_secproto_t proto;
@@ -67,7 +68,15 @@ fromtext_key(ARGS_FROMTEXT) {
if ((flags & 0xc000) == 0xc000)
return (ISC_R_SUCCESS);
- return (isc_base64_tobuffer(lexer, target, -1));
+ 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
@@ -176,6 +185,15 @@ fromwire_key(ARGS_FROMWIRE) {
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));
diff --git a/lib/dns/rdata/generic/keydata_65533.c b/lib/dns/rdata/generic/keydata_65533.c
index a2d83f456e493..fae2bce8dbeb7 100644
--- a/lib/dns/rdata/generic/keydata_65533.c
+++ b/lib/dns/rdata/generic/keydata_65533.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009, 2011-2013 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
@@ -21,10 +21,11 @@
#include <dst/dst.h>
-#define RRTYPE_KEYDATA_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+#define RRTYPE_KEYDATA_ATTRIBUTES (0)
static inline isc_result_t
fromtext_keydata(ARGS_FROMTEXT) {
+ isc_result_t result;
isc_token_t token;
dns_secalg_t alg;
dns_secproto_t proto;
@@ -79,7 +80,15 @@ fromtext_keydata(ARGS_FROMTEXT) {
if ((flags & 0xc000) == 0xc000)
return (ISC_R_SUCCESS);
- return (isc_base64_tobuffer(lexer, target, -1));
+ 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) < 19)
+ return (ISC_R_UNEXPECTEDEND);
+
+ return (ISC_R_SUCCESS);
}
static inline isc_result_t
@@ -93,7 +102,9 @@ totext_keydata(ARGS_TOTEXT) {
const char *keyinfo;
REQUIRE(rdata->type == 65533);
- REQUIRE(rdata->length != 0);
+
+ if ((tctx->flags & DNS_STYLEFLAG_KEYDATA) == 0 || rdata->length < 16)
+ return (unknown_totext(rdata, tctx, target));
dns_rdata_toregion(rdata, &sr);
@@ -194,9 +205,6 @@ fromwire_keydata(ARGS_FROMWIRE) {
UNUSED(options);
isc_buffer_activeregion(source, &sr);
- if (sr.length < 16)
- return (ISC_R_UNEXPECTEDEND);
-
isc_buffer_forward(source, sr.length);
return (mem_tobuffer(target, sr.base, sr.length));
}
@@ -206,7 +214,6 @@ towire_keydata(ARGS_TOWIRE) {
isc_region_t sr;
REQUIRE(rdata->type == 65533);
- REQUIRE(rdata->length != 0);
UNUSED(cctx);
@@ -222,8 +229,6 @@ compare_keydata(ARGS_COMPARE) {
REQUIRE(rdata1->type == rdata2->type);
REQUIRE(rdata1->rdclass == rdata2->rdclass);
REQUIRE(rdata1->type == 65533);
- REQUIRE(rdata1->length != 0);
- REQUIRE(rdata2->length != 0);
dns_rdata_toregion(rdata1, &r1);
dns_rdata_toregion(rdata2, &r2);
@@ -271,7 +276,6 @@ tostruct_keydata(ARGS_TOSTRUCT) {
REQUIRE(rdata->type == 65533);
REQUIRE(target != NULL);
- REQUIRE(rdata->length != 0);
keydata->common.rdclass = rdata->rdclass;
keydata->common.rdtype = rdata->type;
diff --git a/lib/dns/rdata/generic/l32_105.c b/lib/dns/rdata/generic/l32_105.c
index 763ddb953fed9..d191624ebc25e 100644
--- a/lib/dns/rdata/generic/l32_105.c
+++ b/lib/dns/rdata/generic/l32_105.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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
@@ -51,7 +51,7 @@ fromtext_l32(ARGS_FROMTEXT) {
isc_buffer_availableregion(target, &region);
if (region.length < 4)
return (ISC_R_NOSPACE);
- memcpy(region.base, &addr, 4);
+ memmove(region.base, &addr, 4);
isc_buffer_add(target, 4);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/generic/l64_106.c b/lib/dns/rdata/generic/l64_106.c
index ff20663355ca7..d811d29ae515a 100644
--- a/lib/dns/rdata/generic/l64_106.c
+++ b/lib/dns/rdata/generic/l64_106.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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
@@ -155,7 +155,7 @@ tostruct_l64(ARGS_TOSTRUCT) {
dns_rdata_toregion(rdata, &region);
l64->pref = uint16_fromregion(&region);
- memcpy(l64->l64, region.base, region.length);
+ memmove(l64->l64, region.base, region.length);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/generic/nid_104.c b/lib/dns/rdata/generic/nid_104.c
index c96b0bf9c9809..39f16ed6f02bf 100644
--- a/lib/dns/rdata/generic/nid_104.c
+++ b/lib/dns/rdata/generic/nid_104.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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
@@ -155,7 +155,7 @@ tostruct_nid(ARGS_TOSTRUCT) {
dns_rdata_toregion(rdata, &region);
nid->pref = uint16_fromregion(&region);
- memcpy(nid->nid, region.base, region.length);
+ memmove(nid->nid, region.base, region.length);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/generic/opt_41.c b/lib/dns/rdata/generic/opt_41.c
index 4b51804317ccd..bd2adb5fe9711 100644
--- a/lib/dns/rdata/generic/opt_41.c
+++ b/lib/dns/rdata/generic/opt_41.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011-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
@@ -97,6 +97,7 @@ static inline isc_result_t
fromwire_opt(ARGS_FROMWIRE) {
isc_region_t sregion;
isc_region_t tregion;
+ isc_uint16_t opt;
isc_uint16_t length;
unsigned int total;
@@ -112,17 +113,48 @@ fromwire_opt(ARGS_FROMWIRE) {
while (sregion.length != 0) {
if (sregion.length < 4)
return (ISC_R_UNEXPECTEDEND);
- /*
- * Eat the 16bit option code. There is nothing to
- * be done with it currently.
- */
+ opt = uint16_fromregion(&sregion);
isc_region_consume(&sregion, 2);
length = uint16_fromregion(&sregion);
isc_region_consume(&sregion, 2);
total += 4;
if (sregion.length < length)
return (ISC_R_UNEXPECTEDEND);
- isc_region_consume(&sregion, length);
+ switch (opt) {
+ case DNS_OPT_CLIENT_SUBNET: {
+ isc_uint16_t family;
+ isc_uint8_t addrlen;
+ isc_uint8_t scope;
+ isc_uint8_t addrbytes;
+
+ if (length < 4)
+ return (DNS_R_FORMERR);
+ family = uint16_fromregion(&sregion);
+ isc_region_consume(&sregion, 2);
+ addrlen = uint8_fromregion(&sregion);
+ isc_region_consume(&sregion, 1);
+ scope = uint8_fromregion(&sregion);
+ isc_region_consume(&sregion, 1);
+ switch (family) {
+ case 1:
+ if (addrlen > 32U || scope > 32U)
+ return (DNS_R_FORMERR);
+ break;
+ case 2:
+ if (addrlen > 128U || scope > 128U)
+ return (DNS_R_FORMERR);
+ break;
+ }
+ addrbytes = (addrlen + 7) / 8;
+ if (addrbytes + 4 != length)
+ return (DNS_R_FORMERR);
+ isc_region_consume(&sregion, addrbytes);
+ break;
+ }
+ default:
+ isc_region_consume(&sregion, length);
+ break;
+ }
total += length;
}
@@ -130,7 +162,7 @@ fromwire_opt(ARGS_FROMWIRE) {
isc_buffer_availableregion(target, &tregion);
if (tregion.length < total)
return (ISC_R_NOSPACE);
- memcpy(tregion.base, sregion.base, total);
+ memmove(tregion.base, sregion.base, total);
isc_buffer_forward(source, total);
isc_buffer_add(target, total);
diff --git a/lib/dns/rdata/generic/rrsig_46.c b/lib/dns/rdata/generic/rrsig_46.c
index 58a327c02ed79..5dd5a31a7ca88 100644
--- a/lib/dns/rdata/generic/rrsig_46.c
+++ b/lib/dns/rdata/generic/rrsig_46.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012, 2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -90,7 +90,20 @@ fromtext_rrsig(ARGS_FROMTEXT) {
*/
RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
ISC_FALSE));
- RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_expire));
+ if (strlen(DNS_AS_STR(token)) <= 10U &&
+ *DNS_AS_STR(token) != '-' && *DNS_AS_STR(token) != '+') {
+ char *end;
+ unsigned long u;
+ isc_uint64_t u64;
+
+ u64 = u = strtoul(DNS_AS_STR(token), &end, 10);
+ if (u == ULONG_MAX || *end != 0)
+ RETTOK(DNS_R_SYNTAX);
+ if (u64 > 0xffffffffUL)
+ RETTOK(ISC_R_RANGE);
+ time_expire = u;
+ } else
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_expire));
RETERR(uint32_tobuffer(time_expire, target));
/*
@@ -98,7 +111,20 @@ fromtext_rrsig(ARGS_FROMTEXT) {
*/
RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
ISC_FALSE));
- RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_signed));
+ if (strlen(DNS_AS_STR(token)) <= 10U &&
+ *DNS_AS_STR(token) != '-' && *DNS_AS_STR(token) != '+') {
+ char *end;
+ unsigned long u;
+ isc_uint64_t u64;
+
+ u64 = u = strtoul(DNS_AS_STR(token), &end, 10);
+ if (u == ULONG_MAX || *end != 0)
+ RETTOK(DNS_R_SYNTAX);
+ if (u64 > 0xffffffffUL)
+ RETTOK(ISC_R_RANGE);
+ time_signed = u;
+ } else
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_signed));
RETERR(uint32_tobuffer(time_signed, target));
/*
diff --git a/lib/dns/rdata/generic/rt_21.c b/lib/dns/rdata/generic/rt_21.c
index 8f71a2afc8504..86fe2480b7998 100644
--- a/lib/dns/rdata/generic/rt_21.c
+++ b/lib/dns/rdata/generic/rt_21.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-2001, 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -109,7 +109,7 @@ fromwire_rt(ARGS_FROMWIRE) {
return (ISC_R_NOSPACE);
if (sregion.length < 2)
return (ISC_R_UNEXPECTEDEND);
- memcpy(tregion.base, sregion.base, 2);
+ memmove(tregion.base, sregion.base, 2);
isc_buffer_forward(source, 2);
isc_buffer_add(target, 2);
return (dns_name_fromwire(&name, source, dctx, options, target));
@@ -130,7 +130,7 @@ towire_rt(ARGS_TOWIRE) {
dns_rdata_toregion(rdata, &region);
if (tr.length < 2)
return (ISC_R_NOSPACE);
- memcpy(tr.base, region.base, 2);
+ memmove(tr.base, region.base, 2);
isc_region_consume(&region, 2);
isc_buffer_add(target, 2);
diff --git a/lib/dns/rdata/generic/soa_6.c b/lib/dns/rdata/generic/soa_6.c
index ac0a38f7c19e3..fe67d76f1ee3b 100644
--- a/lib/dns/rdata/generic/soa_6.c
+++ b/lib/dns/rdata/generic/soa_6.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) 1998-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -186,7 +186,7 @@ fromwire_soa(ARGS_FROMWIRE) {
if (tregion.length < 20)
return (ISC_R_NOSPACE);
- memcpy(tregion.base, sregion.base, 20);
+ memmove(tregion.base, sregion.base, 20);
isc_buffer_forward(source, 20);
isc_buffer_add(target, 20);
@@ -224,7 +224,7 @@ towire_soa(ARGS_TOWIRE) {
if (tregion.length < 20)
return (ISC_R_NOSPACE);
- memcpy(tregion.base, sregion.base, 20);
+ memmove(tregion.base, sregion.base, 20);
isc_buffer_add(target, 20);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/generic/spf_99.c b/lib/dns/rdata/generic/spf_99.c
index 492e315d45428..c7cdfc9fbbad5 100644
--- a/lib/dns/rdata/generic/spf_99.c
+++ b/lib/dns/rdata/generic/spf_99.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) 1998-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -103,7 +103,7 @@ towire_spf(ARGS_TOWIRE) {
if (region.length < rdata->length)
return (ISC_R_NOSPACE);
- memcpy(region.base, rdata->data, rdata->length);
+ memmove(region.base, rdata->data, rdata->length);
isc_buffer_add(target, rdata->length);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c
index e1bce6a0deb91..76109251a766d 100644
--- a/lib/dns/rdata/generic/txt_16.c
+++ b/lib/dns/rdata/generic/txt_16.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007-2009, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007-2009, 2012, 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
@@ -110,7 +110,7 @@ towire_txt(ARGS_TOWIRE) {
if (region.length < rdata->length)
return (ISC_R_NOSPACE);
- memcpy(region.base, rdata->data, rdata->length);
+ memmove(region.base, rdata->data, rdata->length);
isc_buffer_add(target, rdata->length);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/hs_4/a_1.c b/lib/dns/rdata/hs_4/a_1.c
index 50ae25d52b83e..5f8a87504c0ef 100644
--- a/lib/dns/rdata/hs_4/a_1.c
+++ b/lib/dns/rdata/hs_4/a_1.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) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -48,7 +48,7 @@ fromtext_hs_a(ARGS_FROMTEXT) {
isc_buffer_availableregion(target, &region);
if (region.length < 4)
return (ISC_R_NOSPACE);
- memcpy(region.base, &addr, 4);
+ memmove(region.base, &addr, 4);
isc_buffer_add(target, 4);
return (ISC_R_SUCCESS);
}
@@ -87,7 +87,7 @@ fromwire_hs_a(ARGS_FROMWIRE) {
if (tregion.length < 4)
return (ISC_R_NOSPACE);
- memcpy(tregion.base, sregion.base, 4);
+ memmove(tregion.base, sregion.base, 4);
isc_buffer_forward(source, 4);
isc_buffer_add(target, 4);
return (ISC_R_SUCCESS);
@@ -106,7 +106,7 @@ towire_hs_a(ARGS_TOWIRE) {
isc_buffer_availableregion(target, &region);
if (region.length < rdata->length)
return (ISC_R_NOSPACE);
- memcpy(region.base, rdata->data, rdata->length);
+ memmove(region.base, rdata->data, rdata->length);
isc_buffer_add(target, 4);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/in_1/a6_38.c b/lib/dns/rdata/in_1/a6_38.c
index 8619f8a213632..b6ef68878e2f0 100644
--- a/lib/dns/rdata/in_1/a6_38.c
+++ b/lib/dns/rdata/in_1/a6_38.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) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -122,7 +122,7 @@ totext_in_a6(ARGS_TOTEXT) {
if (prefixlen != 128) {
octets = prefixlen/8;
memset(addr, 0, sizeof(addr));
- memcpy(&addr[octets], sr.base, 16 - octets);
+ memmove(&addr[octets], sr.base, 16 - octets);
mask = 0xff >> (prefixlen % 8);
addr[octets] &= mask;
ar.base = addr;
@@ -347,7 +347,7 @@ tostruct_in_a6(ARGS_TOSTRUCT) {
if (a6->prefixlen != 128) {
octets = 16 - a6->prefixlen / 8;
INSIST(r.length >= octets);
- memcpy(a6->in6_addr.s6_addr + 16 - octets, r.base, octets);
+ memmove(a6->in6_addr.s6_addr + 16 - octets, r.base, octets);
isc_region_consume(&r, octets);
}
diff --git a/lib/dns/rdata/in_1/a_1.c b/lib/dns/rdata/in_1/a_1.c
index 902932e02548a..fcdcaae0545b7 100644
--- a/lib/dns/rdata/in_1/a_1.c
+++ b/lib/dns/rdata/in_1/a_1.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
@@ -50,7 +50,7 @@ fromtext_in_a(ARGS_FROMTEXT) {
isc_buffer_availableregion(target, &region);
if (region.length < 4)
return (ISC_R_NOSPACE);
- memcpy(region.base, &addr, 4);
+ memmove(region.base, &addr, 4);
isc_buffer_add(target, 4);
return (ISC_R_SUCCESS);
}
@@ -89,7 +89,7 @@ fromwire_in_a(ARGS_FROMWIRE) {
if (tregion.length < 4)
return (ISC_R_NOSPACE);
- memcpy(tregion.base, sregion.base, 4);
+ memmove(tregion.base, sregion.base, 4);
isc_buffer_forward(source, 4);
isc_buffer_add(target, 4);
return (ISC_R_SUCCESS);
@@ -108,7 +108,7 @@ towire_in_a(ARGS_TOWIRE) {
isc_buffer_availableregion(target, &region);
if (region.length < rdata->length)
return (ISC_R_NOSPACE);
- memcpy(region.base, rdata->data, rdata->length);
+ memmove(region.base, rdata->data, rdata->length);
isc_buffer_add(target, 4);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/in_1/aaaa_28.c b/lib/dns/rdata/in_1/aaaa_28.c
index 5aa59b2ccc2c6..3f88c4db0f2f5 100644
--- a/lib/dns/rdata/in_1/aaaa_28.c
+++ b/lib/dns/rdata/in_1/aaaa_28.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
@@ -51,7 +51,7 @@ fromtext_in_aaaa(ARGS_FROMTEXT) {
isc_buffer_availableregion(target, &region);
if (region.length < 16)
return (ISC_R_NOSPACE);
- memcpy(region.base, addr, 16);
+ memmove(region.base, addr, 16);
isc_buffer_add(target, 16);
return (ISC_R_SUCCESS);
}
@@ -90,7 +90,7 @@ fromwire_in_aaaa(ARGS_FROMWIRE) {
if (tregion.length < 16)
return (ISC_R_NOSPACE);
- memcpy(tregion.base, sregion.base, 16);
+ memmove(tregion.base, sregion.base, 16);
isc_buffer_forward(source, 16);
isc_buffer_add(target, 16);
return (ISC_R_SUCCESS);
@@ -109,7 +109,7 @@ towire_in_aaaa(ARGS_TOWIRE) {
isc_buffer_availableregion(target, &region);
if (region.length < rdata->length)
return (ISC_R_NOSPACE);
- memcpy(region.base, rdata->data, rdata->length);
+ memmove(region.base, rdata->data, rdata->length);
isc_buffer_add(target, 16);
return (ISC_R_SUCCESS);
}
@@ -165,7 +165,7 @@ tostruct_in_aaaa(ARGS_TOSTRUCT) {
dns_rdata_toregion(rdata, &r);
INSIST(r.length == 16);
- memcpy(aaaa->in6_addr.s6_addr, r.base, 16);
+ memmove(aaaa->in6_addr.s6_addr, r.base, 16);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdata/in_1/apl_42.c b/lib/dns/rdata/in_1/apl_42.c
index eb927b9219e3d..94133bae62965 100644
--- a/lib/dns/rdata/in_1/apl_42.c
+++ b/lib/dns/rdata/in_1/apl_42.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) 2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -148,7 +148,7 @@ totext_in_apl(ARGS_TOTEXT) {
INSIST(len <= 4);
INSIST(prefix <= 32);
memset(buf, 0, sizeof(buf));
- memcpy(buf, sr.base, len);
+ memmove(buf, sr.base, len);
RETERR(inet_totext(AF_INET, &ir, target));
break;
@@ -156,7 +156,7 @@ totext_in_apl(ARGS_TOTEXT) {
INSIST(len <= 16);
INSIST(prefix <= 128);
memset(buf, 0, sizeof(buf));
- memcpy(buf, sr.base, len);
+ memmove(buf, sr.base, len);
RETERR(inet_totext(AF_INET6, &ir, target));
break;
diff --git a/lib/dns/rdata/in_1/wks_11.c b/lib/dns/rdata/in_1/wks_11.c
index 1da2611da9b59..4587c813afab1 100644
--- a/lib/dns/rdata/in_1/wks_11.c
+++ b/lib/dns/rdata/in_1/wks_11.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009, 2011-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
@@ -98,7 +98,7 @@ fromtext_in_wks(ARGS_FROMTEXT) {
RETTOK(DNS_R_BADDOTTEDQUAD);
if (region.length < 4)
return (ISC_R_NOSPACE);
- memcpy(region.base, &addr, 4);
+ memmove(region.base, &addr, 4);
isc_buffer_add(target, 4);
/*
@@ -222,7 +222,7 @@ fromwire_in_wks(ARGS_FROMWIRE) {
if (tr.length < sr.length)
return (ISC_R_NOSPACE);
- memcpy(tr.base, sr.base, sr.length);
+ memmove(tr.base, sr.base, sr.length);
isc_buffer_add(target, sr.length);
isc_buffer_forward(source, sr.length);
@@ -278,7 +278,7 @@ fromstruct_in_wks(ARGS_FROMSTRUCT) {
a = ntohl(wks->in_addr.s_addr);
RETERR(uint32_tobuffer(a, target));
- RETERR(uint16_tobuffer(wks->protocol, target));
+ RETERR(uint8_tobuffer(wks->protocol, target));
return (mem_tobuffer(target, wks->map, wks->map_len));
}
@@ -300,8 +300,8 @@ tostruct_in_wks(ARGS_TOSTRUCT) {
n = uint32_fromregion(&region);
wks->in_addr.s_addr = htonl(n);
isc_region_consume(&region, 4);
- wks->protocol = uint16_fromregion(&region);
- isc_region_consume(&region, 2);
+ wks->protocol = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
wks->map_len = region.length;
wks->map = mem_maybedup(mctx, region.base, region.length);
if (wks->map == NULL)
diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c
index cb9ae5425ef9c..1c02b60201b28 100644
--- a/lib/dns/rdataslab.c
+++ b/lib/dns/rdataslab.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 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
@@ -318,7 +318,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
*rawbuf++ |= (x[i].rdata.flags & DNS_RDATA_OFFLINE) ?
DNS_RDATASLAB_OFFLINE : 0;
}
- memcpy(rawbuf, x[i].rdata.data, x[i].rdata.length);
+ memmove(rawbuf, x[i].rdata.data, x[i].rdata.length);
rawbuf += x[i].rdata.length;
}
@@ -711,7 +711,7 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
tstart = isc_mem_get(mctx, tlength);
if (tstart == NULL)
return (ISC_R_NOMEMORY);
- memcpy(tstart, nslab, reservelen);
+ memmove(tstart, nslab, reservelen);
tcurrent = tstart + reservelen;
#if DNS_RDATASET_FIXED
offsetbase = tcurrent;
@@ -790,7 +790,7 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
#if DNS_RDATASET_FIXED
tcurrent += 2; /* fill in later */
#endif
- memcpy(tcurrent, data, length);
+ memmove(tcurrent, data, length);
tcurrent += length;
oadded++;
if (oadded < ocount) {
@@ -817,7 +817,7 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
#if DNS_RDATASET_FIXED
tcurrent += 2; /* fill in later */
#endif
- memcpy(tcurrent, data, length);
+ memmove(tcurrent, data, length);
tcurrent += length;
nadded++;
if (nadded < ncount) {
@@ -913,7 +913,7 @@ dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
* This rdata isn't in the sslab, and thus isn't
* being subtracted.
*/
- tlength += mcurrent - mrdatabegin;
+ tlength += (unsigned int)(mcurrent - mrdatabegin);
tcount++;
} else
rcount++;
@@ -949,7 +949,7 @@ dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
tstart = isc_mem_get(mctx, tlength);
if (tstart == NULL)
return (ISC_R_NOMEMORY);
- memcpy(tstart, mslab, reservelen);
+ memmove(tstart, mslab, reservelen);
tcurrent = tstart + reservelen;
#if DNS_RDATASET_FIXED
offsetbase = tcurrent;
@@ -1000,11 +1000,12 @@ dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
* This rdata isn't in the sslab, and thus should be
* copied to the tslab.
*/
- unsigned int length = mcurrent - mrdatabegin;
+ unsigned int length;
+ length = (unsigned int)(mcurrent - mrdatabegin);
#if DNS_RDATASET_FIXED
offsettable[order] = tcurrent - offsetbase;
#endif
- memcpy(tcurrent, mrdatabegin, length);
+ memmove(tcurrent, mrdatabegin, length);
tcurrent += length;
}
dns_rdata_reset(&mrdata);
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index 27d15b9329cd5..2e60cd84cca24 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.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
@@ -105,6 +105,7 @@
#define RTRACE(m)
#define RRTRACE(r, m)
#define FCTXTRACE(m)
+#define FCTXTRACE2(m1, m2)
#define FTRACE(m)
#define QTRACE(m)
#endif
@@ -1132,6 +1133,10 @@ log_edns(fetchctx_t *fctx) {
if (fctx->reason == NULL)
return;
+ /*
+ * We do not know if fctx->domain is the actual domain the record
+ * lives in or a parent domain so we have a '?' after it.
+ */
dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_EDNS_DISABLED,
DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
@@ -3610,12 +3615,14 @@ 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, name, domain,
- 0, findoptions, ISC_TRUE,
+ result = dns_view_findzonecut(res->view, fwdname,
+ domain, 0, findoptions,
+ ISC_TRUE,
&fctx->nameservers,
NULL);
if (result != ISC_R_SUCCESS)
goto cleanup_name;
+
result = dns_name_dup(domain, mctx, &fctx->domain);
if (result != ISC_R_SUCCESS) {
dns_rdataset_disassociate(&fctx->nameservers);
@@ -5439,11 +5446,11 @@ is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
dns_rdataset_current(rdataset, &rdata);
if (rdataset->type == dns_rdatatype_a) {
INSIST(rdata.length == sizeof(ina.s_addr));
- memcpy(&ina.s_addr, rdata.data, sizeof(ina.s_addr));
+ memmove(&ina.s_addr, rdata.data, sizeof(ina.s_addr));
isc_netaddr_fromin(&netaddr, &ina);
} else {
INSIST(rdata.length == sizeof(in6a.s6_addr));
- memcpy(in6a.s6_addr, rdata.data, sizeof(in6a.s6_addr));
+ memmove(in6a.s6_addr, rdata.data, sizeof(in6a.s6_addr));
isc_netaddr_fromin6(&netaddr, &in6a);
}
@@ -6655,7 +6662,7 @@ log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query,
unsigned char *p, *buf, *nsid;
/* Allocate buffer for storing hex version of the NSID */
- buflen = nsid_len * 2 + 1;
+ buflen = (isc_uint16_t)nsid_len * 2 + 1;
buf = isc_mem_get(mctx, buflen);
if (buf == NULL)
return;
@@ -7307,9 +7314,12 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* NXDOMAIN, NXRDATASET, or referral.
*/
result = noanswer_response(fctx, NULL, 0);
- if (result == DNS_R_CHASEDSSERVERS) {
- } else if (result == DNS_R_DELEGATION) {
- force_referral:
+ switch (result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_CHASEDSSERVERS:
+ break;
+ case DNS_R_DELEGATION:
+ force_referral:
/*
* We don't have the answer, but we know a better
* place to look.
@@ -7334,7 +7344,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
fctx->adberr = 0;
result = ISC_R_SUCCESS;
- } else if (result != ISC_R_SUCCESS) {
+ break;
+ default:
/*
* Something has gone wrong.
*/
@@ -8844,7 +8855,7 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
}
memset(new, 0, len);
if (algorithms != NULL)
- memcpy(new, algorithms, *algorithms);
+ memmove(new, algorithms, *algorithms);
new[len-1] |= mask;
*new = len;
node->data = new;
diff --git a/lib/dns/rootns.c b/lib/dns/rootns.c
index 3502022c2ae17..34971788dd89e 100644
--- a/lib/dns/rootns.c
+++ b/lib/dns/rootns.c
@@ -201,7 +201,7 @@ dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
{
isc_result_t result, eresult;
isc_buffer_t source;
- size_t len;
+ unsigned int len;
dns_rdatacallbacks_t callbacks;
dns_db_t *db = NULL;
diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c
index 2d689e7ba1282..f617fe7b7c6a3 100644
--- a/lib/dns/rpz.c
+++ b/lib/dns/rpz.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2011-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
@@ -1115,7 +1115,7 @@ dns_rpz_cidr_find(dns_rpz_cidr_t *cidr, const isc_netaddr_t *netaddr,
* one could cast netaddr->type.in6 to dns_rpz_cidr_key_t *,
* but there are objections.
*/
- memcpy(src_ip6.w, &netaddr->type.in6, sizeof(src_ip6.w));
+ memmove(src_ip6.w, &netaddr->type.in6, sizeof(src_ip6.w));
for (i = 0; i < 4; i++) {
tgt_ip.w[i] = ntohl(src_ip6.w[i]);
}
diff --git a/lib/dns/rrl.c b/lib/dns/rrl.c
new file mode 100644
index 0000000000000..02554e9a9dfbd
--- /dev/null
+++ b/lib/dns/rrl.c
@@ -0,0 +1,1324 @@
+/*
+ * Copyright (C) 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
+ * 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.
+ */
+
+/*! \file */
+
+/*
+ * Rate limit DNS responses.
+ */
+
+/* #define ISC_LIST_CHECKINIT */
+
+#include <config.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+
+#include <dns/result.h>
+#include <dns/rcode.h>
+#include <dns/rdatatype.h>
+#include <dns/rdataclass.h>
+#include <dns/log.h>
+#include <dns/rrl.h>
+#include <dns/view.h>
+
+static void
+log_end(dns_rrl_t *rrl, dns_rrl_entry_t *e, isc_boolean_t early,
+ char *log_buf, unsigned int log_buf_len);
+
+/*
+ * Get a modulus for a hash function that is tolerably likely to be
+ * relatively prime to most inputs. Of course, we get a prime for for initial
+ * values not larger than the square of the last prime. We often get a prime
+ * after that.
+ * This works well in practice for hash tables up to at least 100
+ * times the square of the last prime and better than a multiplicative hash.
+ */
+static int
+hash_divisor(unsigned int initial) {
+ static isc_uint16_t primes[] = {
+ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
+ 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
+#if 0
+ 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157,
+ 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
+ 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367,
+ 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439,
+ 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
+ 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599,
+ 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
+ 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
+ 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
+ 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919,
+ 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,1009,
+#endif
+ };
+ int divisions, tries;
+ unsigned int result;
+ isc_uint16_t *pp, p;
+
+ result = initial;
+
+ if (primes[sizeof(primes)/sizeof(primes[0])-1] >= result) {
+ pp = primes;
+ while (*pp < result)
+ ++pp;
+ return (*pp);
+ }
+
+ if ((result & 1) == 0)
+ ++result;
+
+ divisions = 0;
+ tries = 1;
+ pp = primes;
+ do {
+ p = *pp++;
+ ++divisions;
+ if ((result % p) == 0) {
+ ++tries;
+ result += 2;
+ pp = primes;
+ }
+ } while (pp < &primes[sizeof(primes) / sizeof(primes[0])]);
+
+ if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DEBUG3))
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DEBUG3,
+ "%d hash_divisor() divisions in %d tries"
+ " to get %d from %d",
+ divisions, tries, result, initial);
+
+ return (result);
+}
+
+/*
+ * Convert a timestamp to a number of seconds in the past.
+ */
+static inline int
+delta_rrl_time(isc_stdtime_t ts, isc_stdtime_t now) {
+ int delta;
+
+ delta = now - ts;
+ if (delta >= 0)
+ return (delta);
+
+ /*
+ * The timestamp is in the future. That future might result from
+ * re-ordered requests, because we use timestamps on requests
+ * instead of consulting a clock. Timestamps in the distant future are
+ * assumed to result from clock changes. When the clock changes to
+ * the past, make existing timestamps appear to be in the past.
+ */
+ if (delta < -DNS_RRL_MAX_TIME_TRAVEL)
+ return (DNS_RRL_FOREVER);
+ return (0);
+}
+
+static inline int
+get_age(const dns_rrl_t *rrl, const dns_rrl_entry_t *e, isc_stdtime_t now) {
+ if (!e->ts_valid)
+ return (DNS_RRL_FOREVER);
+ return (delta_rrl_time(e->ts + rrl->ts_bases[e->ts_gen], now));
+}
+
+static inline void
+set_age(dns_rrl_t *rrl, dns_rrl_entry_t *e, isc_stdtime_t now) {
+ dns_rrl_entry_t *e_old;
+ unsigned int ts_gen;
+ int i, ts;
+
+ ts_gen = rrl->ts_gen;
+ ts = now - rrl->ts_bases[ts_gen];
+ if (ts < 0) {
+ if (ts < -DNS_RRL_MAX_TIME_TRAVEL)
+ ts = DNS_RRL_FOREVER;
+ else
+ ts = 0;
+ }
+
+ /*
+ * Make a new timestamp base if the current base is too old.
+ * All entries older than DNS_RRL_MAX_WINDOW seconds are ancient,
+ * useless history. Their timestamps can be treated as if they are
+ * all the same.
+ * We only do arithmetic on more recent timestamps, so bases for
+ * older timestamps can be recycled provided the old timestamps are
+ * marked as ancient history.
+ * This loop is almost always very short because most entries are
+ * recycled after one second and any entries that need to be marked
+ * are older than (DNS_RRL_TS_BASES)*DNS_RRL_MAX_TS seconds.
+ */
+ if (ts >= DNS_RRL_MAX_TS) {
+ ts_gen = (ts_gen + 1) % DNS_RRL_TS_BASES;
+ for (e_old = ISC_LIST_TAIL(rrl->lru), i = 0;
+ e_old != NULL && (e_old->ts_gen == ts_gen ||
+ !ISC_LINK_LINKED(e_old, hlink));
+ e_old = ISC_LIST_PREV(e_old, lru), ++i)
+ {
+ e_old->ts_valid = ISC_FALSE;
+ }
+ if (i != 0)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DEBUG1,
+ "rrl new time base scanned %d entries"
+ " at %d for %d %d %d %d",
+ i, now, rrl->ts_bases[ts_gen],
+ rrl->ts_bases[(ts_gen + 1) %
+ DNS_RRL_TS_BASES],
+ rrl->ts_bases[(ts_gen + 2) %
+ DNS_RRL_TS_BASES],
+ rrl->ts_bases[(ts_gen + 3) %
+ DNS_RRL_TS_BASES]);
+ rrl->ts_gen = ts_gen;
+ rrl->ts_bases[ts_gen] = now;
+ ts = 0;
+ }
+
+ e->ts_gen = ts_gen;
+ e->ts = ts;
+ e->ts_valid = ISC_TRUE;
+}
+
+static isc_result_t
+expand_entries(dns_rrl_t *rrl, int new) {
+ unsigned int bsize;
+ dns_rrl_block_t *b;
+ dns_rrl_entry_t *e;
+ double rate;
+ int i;
+
+ if (rrl->num_entries + new >= rrl->max_entries &&
+ rrl->max_entries != 0)
+ {
+ new = rrl->max_entries - rrl->num_entries;
+ if (new <= 0)
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Log expansions so that the user can tune max-table-size
+ * and min-table-size.
+ */
+ if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DROP) &&
+ rrl->hash != NULL) {
+ rate = rrl->probes;
+ if (rrl->searches != 0)
+ rate /= rrl->searches;
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DROP,
+ "increase from %d to %d RRL entries with"
+ " %d bins; average search length %.1f",
+ rrl->num_entries, rrl->num_entries+new,
+ rrl->hash->length, rate);
+ }
+
+ bsize = sizeof(dns_rrl_block_t) + (new-1)*sizeof(dns_rrl_entry_t);
+ b = isc_mem_get(rrl->mctx, bsize);
+ if (b == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_FAIL,
+ "isc_mem_get(%d) failed for RRL entries",
+ bsize);
+ return (ISC_R_NOMEMORY);
+ }
+ memset(b, 0, bsize);
+ b->size = bsize;
+
+ e = b->entries;
+ for (i = 0; i < new; ++i, ++e) {
+ ISC_LINK_INIT(e, hlink);
+ ISC_LIST_INITANDAPPEND(rrl->lru, e, lru);
+ }
+ rrl->num_entries += new;
+ ISC_LIST_INITANDAPPEND(rrl->blocks, b, link);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline dns_rrl_bin_t *
+get_bin(dns_rrl_hash_t *hash, unsigned int hval) {
+ return (&hash->bins[hval % hash->length]);
+}
+
+static void
+free_old_hash(dns_rrl_t *rrl) {
+ dns_rrl_hash_t *old_hash;
+ dns_rrl_bin_t *old_bin;
+ dns_rrl_entry_t *e, *e_next;
+
+ old_hash = rrl->old_hash;
+ for (old_bin = &old_hash->bins[0];
+ old_bin < &old_hash->bins[old_hash->length];
+ ++old_bin)
+ {
+ for (e = ISC_LIST_HEAD(*old_bin); e != NULL; e = e_next) {
+ e_next = ISC_LIST_NEXT(e, hlink);
+ ISC_LINK_INIT(e, hlink);
+ }
+ }
+
+ isc_mem_put(rrl->mctx, old_hash,
+ sizeof(*old_hash)
+ + (old_hash->length - 1) * sizeof(old_hash->bins[0]));
+ rrl->old_hash = NULL;
+}
+
+static isc_result_t
+expand_rrl_hash(dns_rrl_t *rrl, isc_stdtime_t now) {
+ dns_rrl_hash_t *hash;
+ int old_bins, new_bins, hsize;
+ double rate;
+
+ if (rrl->old_hash != NULL)
+ free_old_hash(rrl);
+
+ /*
+ * Most searches fail and so go to the end of the chain.
+ * Use a small hash table load factor.
+ */
+ old_bins = (rrl->hash == NULL) ? 0 : rrl->hash->length;
+ new_bins = old_bins/8 + old_bins;
+ if (new_bins < rrl->num_entries)
+ new_bins = rrl->num_entries;
+ new_bins = hash_divisor(new_bins);
+
+ hsize = sizeof(dns_rrl_hash_t) + (new_bins-1)*sizeof(hash->bins[0]);
+ hash = isc_mem_get(rrl->mctx, hsize);
+ if (hash == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_FAIL,
+ "isc_mem_get(%d) failed for"
+ " RRL hash table",
+ hsize);
+ return (ISC_R_NOMEMORY);
+ }
+ memset(hash, 0, hsize);
+ hash->length = new_bins;
+ rrl->hash_gen ^= 1;
+ hash->gen = rrl->hash_gen;
+
+ if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DROP) && old_bins != 0) {
+ rate = rrl->probes;
+ if (rrl->searches != 0)
+ rate /= rrl->searches;
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DROP,
+ "increase from %d to %d RRL bins for"
+ " %d entries; average search length %.1f",
+ old_bins, new_bins, rrl->num_entries, rate);
+ }
+
+ rrl->old_hash = rrl->hash;
+ if (rrl->old_hash != NULL)
+ rrl->old_hash->check_time = now;
+ rrl->hash = hash;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+ref_entry(dns_rrl_t *rrl, dns_rrl_entry_t *e, int probes, isc_stdtime_t now) {
+ /*
+ * Make the entry most recently used.
+ */
+ if (ISC_LIST_HEAD(rrl->lru) != e) {
+ if (e == rrl->last_logged)
+ rrl->last_logged = ISC_LIST_PREV(e, lru);
+ ISC_LIST_UNLINK(rrl->lru, e, lru);
+ ISC_LIST_PREPEND(rrl->lru, e, lru);
+ }
+
+ /*
+ * Expand the hash table if it is time and necessary.
+ * This will leave the newly referenced entry in a chain in the
+ * old hash table. It will migrate to the new hash table the next
+ * time it is used or be cut loose when the old hash table is destroyed.
+ */
+ rrl->probes += probes;
+ ++rrl->searches;
+ if (rrl->searches > 100 &&
+ delta_rrl_time(rrl->hash->check_time, now) > 1) {
+ if (rrl->probes/rrl->searches > 2)
+ expand_rrl_hash(rrl, now);
+ rrl->hash->check_time = now;
+ rrl->probes = 0;
+ rrl->searches = 0;
+ }
+}
+
+static inline isc_boolean_t
+key_cmp(const dns_rrl_key_t *a, const dns_rrl_key_t *b) {
+ if (memcmp(a, b, sizeof(dns_rrl_key_t)) == 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+static inline isc_uint32_t
+hash_key(const dns_rrl_key_t *key) {
+ isc_uint32_t hval;
+ int i;
+
+ hval = key->w[0];
+ for (i = sizeof(*key) / sizeof(key->w[0]) - 1; i >= 0; --i) {
+ hval = key->w[i] + (hval<<1);
+ }
+ return (hval);
+}
+
+/*
+ * Construct the hash table key.
+ * Use a hash of the DNS query name to save space in the database.
+ * Collisions result in legitimate rate limiting responses for one
+ * query name also limiting responses for other names to the
+ * same client. This is rare and benign enough given the large
+ * space costs compared to keeping the entire name in the database
+ * entry or the time costs of dynamic allocation.
+ */
+static void
+make_key(const dns_rrl_t *rrl, dns_rrl_key_t *key,
+ const isc_sockaddr_t *client_addr,
+ dns_rdatatype_t qtype, dns_name_t *qname, dns_rdataclass_t qclass,
+ dns_rrl_rtype_t rtype)
+{
+ dns_name_t base;
+ dns_offsets_t base_offsets;
+ int labels, i;
+
+ memset(key, 0, sizeof(*key));
+
+ key->s.rtype = rtype;
+ if (rtype == DNS_RRL_RTYPE_QUERY) {
+ key->s.qtype = qtype;
+ key->s.qclass = qclass & 0xff;
+ } else if (rtype == DNS_RRL_RTYPE_REFERRAL ||
+ rtype == DNS_RRL_RTYPE_NODATA) {
+ /*
+ * Because there is no qtype in the empty answer sections of
+ * referral and NODATA responses, count them as the same.
+ */
+ key->s.qclass = qclass & 0xff;
+ }
+
+ if (qname != NULL && qname->labels != 0) {
+ /*
+ * Ignore the first label of wildcards.
+ */
+ if ((qname->attributes & DNS_NAMEATTR_WILDCARD) != 0 &&
+ (labels = dns_name_countlabels(qname)) > 1)
+ {
+ dns_name_init(&base, base_offsets);
+ dns_name_getlabelsequence(qname, 1, labels-1, &base);
+ key->s.qname_hash = dns_name_hashbylabel(&base,
+ ISC_FALSE);
+ } else {
+ key->s.qname_hash = dns_name_hashbylabel(qname,
+ ISC_FALSE);
+ }
+ }
+
+ switch (client_addr->type.sa.sa_family) {
+ case AF_INET:
+ key->s.ip[0] = (client_addr->type.sin.sin_addr.s_addr &
+ rrl->ipv4_mask);
+ break;
+ case AF_INET6:
+ key->s.ipv6 = ISC_TRUE;
+ memmove(key->s.ip, &client_addr->type.sin6.sin6_addr,
+ sizeof(key->s.ip));
+ for (i = 0; i < DNS_RRL_MAX_PREFIX/32; ++i)
+ key->s.ip[i] &= rrl->ipv6_mask[i];
+ break;
+ }
+}
+
+static inline dns_rrl_rate_t *
+get_rate(dns_rrl_t *rrl, dns_rrl_rtype_t rtype) {
+ switch (rtype) {
+ case DNS_RRL_RTYPE_QUERY:
+ return (&rrl->responses_per_second);
+ case DNS_RRL_RTYPE_REFERRAL:
+ return (&rrl->referrals_per_second);
+ case DNS_RRL_RTYPE_NODATA:
+ return (&rrl->nodata_per_second);
+ case DNS_RRL_RTYPE_NXDOMAIN:
+ return (&rrl->nxdomains_per_second);
+ case DNS_RRL_RTYPE_ERROR:
+ return (&rrl->errors_per_second);
+ case DNS_RRL_RTYPE_ALL:
+ return (&rrl->all_per_second);
+ default:
+ INSIST(0);
+ }
+ return (NULL);
+}
+
+static int
+response_balance(dns_rrl_t *rrl, const dns_rrl_entry_t *e, int age) {
+ dns_rrl_rate_t *ratep;
+ int balance, rate;
+
+ if (e->key.s.rtype == DNS_RRL_RTYPE_TCP) {
+ rate = 1;
+ } else {
+ ratep = get_rate(rrl, e->key.s.rtype);
+ rate = ratep->scaled;
+ }
+
+ balance = e->responses + age * rate;
+ if (balance > rate)
+ balance = rate;
+ return (balance);
+}
+
+/*
+ * Search for an entry for a response and optionally create it.
+ */
+static dns_rrl_entry_t *
+get_entry(dns_rrl_t *rrl, const isc_sockaddr_t *client_addr,
+ dns_rdataclass_t qclass, dns_rdatatype_t qtype, dns_name_t *qname,
+ dns_rrl_rtype_t rtype, isc_stdtime_t now, isc_boolean_t create,
+ char *log_buf, unsigned int log_buf_len)
+{
+ dns_rrl_key_t key;
+ isc_uint32_t hval;
+ dns_rrl_entry_t *e;
+ dns_rrl_hash_t *hash;
+ dns_rrl_bin_t *new_bin, *old_bin;
+ int probes, age;
+
+ make_key(rrl, &key, client_addr, qtype, qname, qclass, rtype);
+ hval = hash_key(&key);
+
+ /*
+ * Look for the entry in the current hash table.
+ */
+ new_bin = get_bin(rrl->hash, hval);
+ probes = 1;
+ e = ISC_LIST_HEAD(*new_bin);
+ while (e != NULL) {
+ if (key_cmp(&e->key, &key)) {
+ ref_entry(rrl, e, probes, now);
+ return (e);
+ }
+ ++probes;
+ e = ISC_LIST_NEXT(e, hlink);
+ }
+
+ /*
+ * Look in the old hash table.
+ */
+ if (rrl->old_hash != NULL) {
+ old_bin = get_bin(rrl->old_hash, hval);
+ e = ISC_LIST_HEAD(*old_bin);
+ while (e != NULL) {
+ if (key_cmp(&e->key, &key)) {
+ ISC_LIST_UNLINK(*old_bin, e, hlink);
+ ISC_LIST_PREPEND(*new_bin, e, hlink);
+ e->hash_gen = rrl->hash_gen;
+ ref_entry(rrl, e, probes, now);
+ return (e);
+ }
+ e = ISC_LIST_NEXT(e, hlink);
+ }
+
+ /*
+ * Discard prevous hash table when all of its entries are old.
+ */
+ age = delta_rrl_time(rrl->old_hash->check_time, now);
+ if (age > rrl->window)
+ free_old_hash(rrl);
+ }
+
+ if (!create)
+ return (NULL);
+
+ /*
+ * The entry does not exist, so create it by finding a free entry.
+ * Keep currently penalized and logged entries.
+ * Try to make more entries if none are idle.
+ * Steal the oldest entry if we cannot create more.
+ */
+ for (e = ISC_LIST_TAIL(rrl->lru);
+ e != NULL;
+ e = ISC_LIST_PREV(e, lru))
+ {
+ if (!ISC_LINK_LINKED(e, hlink))
+ break;
+ age = get_age(rrl, e, now);
+ if (age <= 1) {
+ e = NULL;
+ break;
+ }
+ if (!e->logged && response_balance(rrl, e, age) > 0)
+ break;
+ }
+ if (e == NULL) {
+ expand_entries(rrl, ISC_MIN((rrl->num_entries+1)/2, 1000));
+ e = ISC_LIST_TAIL(rrl->lru);
+ }
+ if (e->logged)
+ log_end(rrl, e, ISC_TRUE, log_buf, log_buf_len);
+ if (ISC_LINK_LINKED(e, hlink)) {
+ if (e->hash_gen == rrl->hash_gen)
+ hash = rrl->hash;
+ else
+ hash = rrl->old_hash;
+ old_bin = get_bin(hash, hash_key(&e->key));
+ ISC_LIST_UNLINK(*old_bin, e, hlink);
+ }
+ ISC_LIST_PREPEND(*new_bin, e, hlink);
+ e->hash_gen = rrl->hash_gen;
+ e->key = key;
+ e->ts_valid = ISC_FALSE;
+ ref_entry(rrl, e, probes, now);
+ return (e);
+}
+
+static void
+debit_log(const dns_rrl_entry_t *e, int age, const char *action) {
+ char buf[sizeof("age=12345678")];
+ const char *age_str;
+
+ if (age == DNS_RRL_FOREVER) {
+ age_str = "";
+ } else {
+ snprintf(buf, sizeof(buf), "age=%d", age);
+ age_str = buf;
+ }
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DEBUG3,
+ "rrl %08x %6s responses=%-3d %s",
+ hash_key(&e->key), age_str, e->responses, action);
+}
+
+static inline dns_rrl_result_t
+debit_rrl_entry(dns_rrl_t *rrl, dns_rrl_entry_t *e, double qps, double scale,
+ const isc_sockaddr_t *client_addr, isc_stdtime_t now,
+ char *log_buf, unsigned int log_buf_len)
+{
+ int rate, new_rate, slip, new_slip, age, log_secs, min;
+ dns_rrl_rate_t *ratep;
+ dns_rrl_entry_t const *credit_e;
+
+ /*
+ * Pick the rate counter.
+ * Optionally adjust the rate by the estimated query/second rate.
+ */
+ ratep = get_rate(rrl, e->key.s.rtype);
+ rate = ratep->r;
+ if (rate == 0)
+ return (DNS_RRL_RESULT_OK);
+
+ if (scale < 1.0) {
+ /*
+ * The limit for clients that have used TCP is not scaled.
+ */
+ credit_e = get_entry(rrl, client_addr,
+ 0, dns_rdatatype_none, NULL,
+ DNS_RRL_RTYPE_TCP, now, ISC_FALSE,
+ log_buf, log_buf_len);
+ if (credit_e != NULL) {
+ age = get_age(rrl, e, now);
+ if (age < rrl->window)
+ scale = 1.0;
+ }
+ }
+ if (scale < 1.0) {
+ new_rate = (int) (rate * scale);
+ if (new_rate < 1)
+ new_rate = 1;
+ if (ratep->scaled != new_rate) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST,
+ DNS_RRL_LOG_DEBUG1,
+ "%d qps scaled %s by %.2f"
+ " from %d to %d",
+ (int)qps, ratep->str, scale,
+ rate, new_rate);
+ rate = new_rate;
+ ratep->scaled = rate;
+ }
+ }
+
+ min = -rrl->window * rate;
+
+ /*
+ * Treat time jumps into the recent past as no time.
+ * Treat entries older than the window as if they were just created
+ * Credit other entries.
+ */
+ age = get_age(rrl, e, now);
+ if (age > 0) {
+ /*
+ * Credit tokens earned during elapsed time.
+ */
+ if (age > rrl->window) {
+ e->responses = rate;
+ e->slip_cnt = 0;
+ } else {
+ e->responses += rate*age;
+ if (e->responses > rate) {
+ e->responses = rate;
+ e->slip_cnt = 0;
+ }
+ }
+ /*
+ * Find the seconds since last log message without overflowing
+ * small counter. This counter is reset when an entry is
+ * created. It is not necessarily reset when some requests
+ * are answered provided other requests continue to be dropped
+ * or slipped. This can happen when the request rate is just
+ * at the limit.
+ */
+ if (e->logged) {
+ log_secs = e->log_secs;
+ log_secs += age;
+ if (log_secs > DNS_RRL_MAX_LOG_SECS || log_secs < 0)
+ log_secs = DNS_RRL_MAX_LOG_SECS;
+ e->log_secs = log_secs;
+ }
+ }
+ set_age(rrl, e, now);
+
+ /*
+ * Debit the entry for this response.
+ */
+ if (--e->responses >= 0) {
+ if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DEBUG3))
+ debit_log(e, age, "");
+ return (DNS_RRL_RESULT_OK);
+ }
+
+ if (e->responses < min)
+ e->responses = min;
+
+ /*
+ * Drop this response unless it should slip or leak.
+ */
+ slip = rrl->slip.r;
+ if (slip > 2 && scale < 1.0) {
+ new_slip = (int) (slip * scale);
+ if (new_slip < 2)
+ new_slip = 2;
+ if (rrl->slip.scaled != new_slip) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST,
+ DNS_RRL_LOG_DEBUG1,
+ "%d qps scaled slip"
+ " by %.2f from %d to %d",
+ (int)qps, scale,
+ slip, new_slip);
+ slip = new_slip;
+ rrl->slip.scaled = slip;
+ }
+ }
+ if (slip != 0 && e->key.s.rtype != DNS_RRL_RTYPE_ALL) {
+ if (e->slip_cnt++ == 0) {
+ if ((int) e->slip_cnt >= slip)
+ e->slip_cnt = 0;
+ if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DEBUG3))
+ debit_log(e, age, "slip");
+ return (DNS_RRL_RESULT_SLIP);
+ } else if ((int) e->slip_cnt >= slip) {
+ e->slip_cnt = 0;
+ }
+ }
+
+ if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DEBUG3))
+ debit_log(e, age, "drop");
+ return (DNS_RRL_RESULT_DROP);
+}
+
+static inline dns_rrl_qname_buf_t *
+get_qname(dns_rrl_t *rrl, const dns_rrl_entry_t *e) {
+ dns_rrl_qname_buf_t *qbuf;
+
+ qbuf = rrl->qnames[e->log_qname];
+ if (qbuf == NULL || qbuf->e != e)
+ return (NULL);
+ return (qbuf);
+}
+
+static inline void
+free_qname(dns_rrl_t *rrl, dns_rrl_entry_t *e) {
+ dns_rrl_qname_buf_t *qbuf;
+
+ qbuf = get_qname(rrl, e);
+ if (qbuf != NULL) {
+ qbuf->e = NULL;
+ ISC_LIST_APPEND(rrl->qname_free, qbuf, link);
+ }
+}
+
+static void
+add_log_str(isc_buffer_t *lb, const char *str, unsigned int str_len) {
+ isc_region_t region;
+
+ isc_buffer_availableregion(lb, &region);
+ if (str_len >= region.length) {
+ if (region.length <= 0)
+ return;
+ str_len = region.length;
+ }
+ memmove(region.base, str, str_len);
+ isc_buffer_add(lb, str_len);
+}
+
+#define ADD_LOG_CSTR(eb, s) add_log_str(eb, s, sizeof(s)-1)
+
+/*
+ * Build strings for the logs
+ */
+static void
+make_log_buf(dns_rrl_t *rrl, dns_rrl_entry_t *e,
+ const char *str1, const char *str2, isc_boolean_t plural,
+ dns_name_t *qname, isc_boolean_t save_qname,
+ dns_rrl_result_t rrl_result, isc_result_t resp_result,
+ char *log_buf, unsigned int log_buf_len)
+{
+ isc_buffer_t lb;
+ dns_rrl_qname_buf_t *qbuf;
+ isc_netaddr_t cidr;
+ char strbuf[ISC_MAX(sizeof("/123"), sizeof(" (12345678)"))];
+ const char *rstr;
+ isc_result_t msg_result;
+
+ if (log_buf_len <= 1) {
+ if (log_buf_len == 1)
+ log_buf[0] = '\0';
+ return;
+ }
+ isc_buffer_init(&lb, log_buf, log_buf_len-1);
+
+ if (str1 != NULL)
+ add_log_str(&lb, str1, strlen(str1));
+ if (str2 != NULL)
+ add_log_str(&lb, str2, strlen(str2));
+
+ switch (rrl_result) {
+ case DNS_RRL_RESULT_OK:
+ break;
+ case DNS_RRL_RESULT_DROP:
+ ADD_LOG_CSTR(&lb, "drop ");
+ break;
+ case DNS_RRL_RESULT_SLIP:
+ ADD_LOG_CSTR(&lb, "slip ");
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+
+ switch (e->key.s.rtype) {
+ case DNS_RRL_RTYPE_QUERY:
+ break;
+ case DNS_RRL_RTYPE_REFERRAL:
+ ADD_LOG_CSTR(&lb, "referral ");
+ break;
+ case DNS_RRL_RTYPE_NODATA:
+ ADD_LOG_CSTR(&lb, "NODATA ");
+ break;
+ case DNS_RRL_RTYPE_NXDOMAIN:
+ ADD_LOG_CSTR(&lb, "NXDOMAIN ");
+ break;
+ case DNS_RRL_RTYPE_ERROR:
+ if (resp_result == ISC_R_SUCCESS) {
+ ADD_LOG_CSTR(&lb, "error ");
+ } else {
+ rstr = isc_result_totext(resp_result);
+ add_log_str(&lb, rstr, strlen(rstr));
+ ADD_LOG_CSTR(&lb, " error ");
+ }
+ break;
+ case DNS_RRL_RTYPE_ALL:
+ ADD_LOG_CSTR(&lb, "all ");
+ break;
+ default:
+ INSIST(0);
+ }
+
+ if (plural)
+ ADD_LOG_CSTR(&lb, "responses to ");
+ else
+ ADD_LOG_CSTR(&lb, "response to ");
+
+ memset(&cidr, 0, sizeof(cidr));
+ if (e->key.s.ipv6) {
+ snprintf(strbuf, sizeof(strbuf), "/%d", rrl->ipv6_prefixlen);
+ cidr.family = AF_INET6;
+ memset(&cidr.type.in6, 0, sizeof(cidr.type.in6));
+ memmove(&cidr.type.in6, e->key.s.ip, sizeof(e->key.s.ip));
+ } else {
+ snprintf(strbuf, sizeof(strbuf), "/%d", rrl->ipv4_prefixlen);
+ cidr.family = AF_INET;
+ cidr.type.in.s_addr = e->key.s.ip[0];
+ }
+ msg_result = isc_netaddr_totext(&cidr, &lb);
+ if (msg_result != ISC_R_SUCCESS)
+ ADD_LOG_CSTR(&lb, "?");
+ add_log_str(&lb, strbuf, strlen(strbuf));
+
+ if (e->key.s.rtype == DNS_RRL_RTYPE_QUERY ||
+ e->key.s.rtype == DNS_RRL_RTYPE_REFERRAL ||
+ e->key.s.rtype == DNS_RRL_RTYPE_NODATA ||
+ e->key.s.rtype == DNS_RRL_RTYPE_NXDOMAIN) {
+ qbuf = get_qname(rrl, e);
+ if (save_qname && qbuf == NULL &&
+ qname != NULL && dns_name_isabsolute(qname)) {
+ /*
+ * Capture the qname for the "stop limiting" message.
+ */
+ qbuf = ISC_LIST_TAIL(rrl->qname_free);
+ if (qbuf != NULL) {
+ ISC_LIST_UNLINK(rrl->qname_free, qbuf, link);
+ } else if (rrl->num_qnames < DNS_RRL_QNAMES) {
+ qbuf = isc_mem_get(rrl->mctx, sizeof(*qbuf));
+ if (qbuf != NULL) {
+ memset(qbuf, 0, sizeof(*qbuf));
+ ISC_LINK_INIT(qbuf, link);
+ qbuf->index = rrl->num_qnames;
+ rrl->qnames[rrl->num_qnames++] = qbuf;
+ } else {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST,
+ DNS_RRL_LOG_FAIL,
+ "isc_mem_get(%d)"
+ " failed for RRL qname",
+ (int)sizeof(*qbuf));
+ }
+ }
+ if (qbuf != NULL) {
+ e->log_qname = qbuf->index;
+ qbuf->e = e;
+ dns_fixedname_init(&qbuf->qname);
+ dns_name_copy(qname,
+ dns_fixedname_name(&qbuf->qname),
+ NULL);
+ }
+ }
+ if (qbuf != NULL)
+ qname = dns_fixedname_name(&qbuf->qname);
+ if (qname != NULL) {
+ ADD_LOG_CSTR(&lb, " for ");
+ (void)dns_name_totext(qname, ISC_TRUE, &lb);
+ } else {
+ ADD_LOG_CSTR(&lb, " for (?)");
+ }
+ if (e->key.s.rtype != DNS_RRL_RTYPE_NXDOMAIN) {
+ ADD_LOG_CSTR(&lb, " ");
+ (void)dns_rdataclass_totext(e->key.s.qclass, &lb);
+ if (e->key.s.rtype == DNS_RRL_RTYPE_QUERY) {
+ ADD_LOG_CSTR(&lb, " ");
+ (void)dns_rdatatype_totext(e->key.s.qtype, &lb);
+ }
+ }
+ snprintf(strbuf, sizeof(strbuf), " (%08x)",
+ e->key.s.qname_hash);
+ add_log_str(&lb, strbuf, strlen(strbuf));
+ }
+
+ /*
+ * We saved room for '\0'.
+ */
+ log_buf[isc_buffer_usedlength(&lb)] = '\0';
+}
+
+static void
+log_end(dns_rrl_t *rrl, dns_rrl_entry_t *e, isc_boolean_t early,
+ char *log_buf, unsigned int log_buf_len)
+{
+ if (e->logged) {
+ make_log_buf(rrl, e,
+ early ? "*" : NULL,
+ rrl->log_only ? "would stop limiting "
+ : "stop limiting ",
+ ISC_TRUE, NULL, ISC_FALSE,
+ DNS_RRL_RESULT_OK, ISC_R_SUCCESS,
+ log_buf, log_buf_len);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DROP,
+ "%s", log_buf);
+ free_qname(rrl, e);
+ e->logged = ISC_FALSE;
+ --rrl->num_logged;
+ }
+}
+
+/*
+ * Log messages for streams that have stopped being rate limited.
+ */
+static void
+log_stops(dns_rrl_t *rrl, isc_stdtime_t now, int limit,
+ char *log_buf, unsigned int log_buf_len)
+{
+ dns_rrl_entry_t *e;
+ int age;
+
+ for (e = rrl->last_logged; e != NULL; e = ISC_LIST_PREV(e, lru)) {
+ if (!e->logged)
+ continue;
+ if (now != 0) {
+ age = get_age(rrl, e, now);
+ if (age < DNS_RRL_STOP_LOG_SECS ||
+ response_balance(rrl, e, age) < 0)
+ break;
+ }
+
+ log_end(rrl, e, now == 0, log_buf, log_buf_len);
+ if (rrl->num_logged <= 0)
+ break;
+
+ /*
+ * Too many messages could stall real work.
+ */
+ if (--limit < 0) {
+ rrl->last_logged = ISC_LIST_PREV(e, lru);
+ return;
+ }
+ }
+ if (e == NULL) {
+ INSIST(rrl->num_logged == 0);
+ rrl->log_stops_time = now;
+ }
+ rrl->last_logged = e;
+}
+
+/*
+ * Main rate limit interface.
+ */
+dns_rrl_result_t
+dns_rrl(dns_view_t *view,
+ const isc_sockaddr_t *client_addr, isc_boolean_t is_tcp,
+ dns_rdataclass_t qclass, dns_rdatatype_t qtype,
+ dns_name_t *qname, isc_result_t resp_result, isc_stdtime_t now,
+ isc_boolean_t wouldlog, char *log_buf, unsigned int log_buf_len)
+{
+ dns_rrl_t *rrl;
+ dns_rrl_rtype_t rtype;
+ dns_rrl_entry_t *e;
+ isc_netaddr_t netclient;
+ int secs;
+ double qps, scale;
+ int exempt_match;
+ isc_result_t result;
+ dns_rrl_result_t rrl_result;
+
+ INSIST(log_buf != NULL && log_buf_len > 0);
+
+ rrl = view->rrl;
+ if (rrl->exempt != NULL) {
+ isc_netaddr_fromsockaddr(&netclient, client_addr);
+ result = dns_acl_match(&netclient, NULL, rrl->exempt,
+ &view->aclenv, &exempt_match, NULL);
+ if (result == ISC_R_SUCCESS && exempt_match > 0)
+ return (DNS_RRL_RESULT_OK);
+ }
+
+ LOCK(&rrl->lock);
+
+ /*
+ * Estimate total query per second rate when scaling by qps.
+ */
+ if (rrl->qps_scale == 0) {
+ qps = 0.0;
+ scale = 1.0;
+ } else {
+ ++rrl->qps_responses;
+ secs = delta_rrl_time(rrl->qps_time, now);
+ if (secs <= 0) {
+ qps = rrl->qps;
+ } else {
+ qps = (1.0*rrl->qps_responses) / secs;
+ if (secs >= rrl->window) {
+ if (isc_log_wouldlog(dns_lctx,
+ DNS_RRL_LOG_DEBUG3))
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST,
+ DNS_RRL_LOG_DEBUG3,
+ "%d responses/%d seconds"
+ " = %d qps",
+ rrl->qps_responses, secs,
+ (int)qps);
+ rrl->qps = qps;
+ rrl->qps_responses = 0;
+ rrl->qps_time = now;
+ } else if (qps < rrl->qps) {
+ qps = rrl->qps;
+ }
+ }
+ scale = rrl->qps_scale / qps;
+ }
+
+ /*
+ * Do maintenance once per second.
+ */
+ if (rrl->num_logged > 0 && rrl->log_stops_time != now)
+ log_stops(rrl, now, 8, log_buf, log_buf_len);
+
+ /*
+ * Notice TCP responses when scaling limits by qps.
+ * Do not try to rate limit TCP responses.
+ */
+ if (is_tcp) {
+ if (scale < 1.0) {
+ e = get_entry(rrl, client_addr,
+ 0, dns_rdatatype_none, NULL,
+ DNS_RRL_RTYPE_TCP, now, ISC_TRUE,
+ log_buf, log_buf_len);
+ if (e != NULL) {
+ e->responses = -(rrl->window+1);
+ set_age(rrl, e, now);
+ }
+ }
+ UNLOCK(&rrl->lock);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Find the right kind of entry, creating it if necessary.
+ * If that is impossible, then nothing more can be done
+ */
+ switch (resp_result) {
+ case ISC_R_SUCCESS:
+ rtype = DNS_RRL_RTYPE_QUERY;
+ break;
+ case DNS_R_DELEGATION:
+ rtype = DNS_RRL_RTYPE_REFERRAL;
+ break;
+ case DNS_R_NXRRSET:
+ rtype = DNS_RRL_RTYPE_NODATA;
+ break;
+ case DNS_R_NXDOMAIN:
+ rtype = DNS_RRL_RTYPE_NXDOMAIN;
+ break;
+ default:
+ rtype = DNS_RRL_RTYPE_ERROR;
+ break;
+ }
+ e = get_entry(rrl, client_addr, qclass, qtype, qname, rtype,
+ now, ISC_TRUE, log_buf, log_buf_len);
+ if (e == NULL) {
+ UNLOCK(&rrl->lock);
+ return (DNS_RRL_RESULT_OK);
+ }
+
+ if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DEBUG1)) {
+ /*
+ * Do not worry about speed or releasing the lock.
+ * This message appears before messages from debit_rrl_entry().
+ */
+ make_log_buf(rrl, e, "consider limiting ", NULL, ISC_FALSE,
+ qname, ISC_FALSE, DNS_RRL_RESULT_OK, resp_result,
+ log_buf, log_buf_len);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DEBUG1,
+ "%s", log_buf);
+ }
+
+ rrl_result = debit_rrl_entry(rrl, e, qps, scale, client_addr, now,
+ log_buf, log_buf_len);
+
+ if (rrl->all_per_second.r != 0) {
+ /*
+ * We must debit the all-per-second token bucket if we have
+ * an all-per-second limit for the IP address.
+ * The all-per-second limit determines the log message
+ * when both limits are hit.
+ * The response limiting must continue if the
+ * all-per-second limiting lapses.
+ */
+ dns_rrl_entry_t *e_all;
+ dns_rrl_result_t rrl_all_result;
+
+ e_all = get_entry(rrl, client_addr,
+ 0, dns_rdatatype_none, NULL,
+ DNS_RRL_RTYPE_ALL, now, ISC_TRUE,
+ log_buf, log_buf_len);
+ if (e_all == NULL) {
+ UNLOCK(&rrl->lock);
+ return (DNS_RRL_RESULT_OK);
+ }
+ rrl_all_result = debit_rrl_entry(rrl, e_all, qps, scale,
+ client_addr, now,
+ log_buf, log_buf_len);
+ if (rrl_all_result != DNS_RRL_RESULT_OK) {
+ int level;
+
+ e = e_all;
+ rrl_result = rrl_all_result;
+ if (rrl_result == DNS_RRL_RESULT_OK)
+ level = DNS_RRL_LOG_DEBUG2;
+ else
+ level = DNS_RRL_LOG_DEBUG1;
+ if (isc_log_wouldlog(dns_lctx, level)) {
+ make_log_buf(rrl, e,
+ "prefer all-per-second limiting ",
+ NULL, ISC_TRUE, qname, ISC_FALSE,
+ DNS_RRL_RESULT_OK, resp_result,
+ log_buf, log_buf_len);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST, level,
+ "%s", log_buf);
+ }
+ }
+ }
+
+ if (rrl_result == DNS_RRL_RESULT_OK) {
+ UNLOCK(&rrl->lock);
+ return (DNS_RRL_RESULT_OK);
+ }
+
+ /*
+ * Log occassionally in the rate-limit category.
+ */
+ if ((!e->logged || e->log_secs >= DNS_RRL_MAX_LOG_SECS) &&
+ isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DROP)) {
+ make_log_buf(rrl, e, rrl->log_only ? "would " : NULL,
+ e->logged ? "continue limiting " : "limit ",
+ ISC_TRUE, qname, ISC_TRUE,
+ DNS_RRL_RESULT_OK, resp_result,
+ log_buf, log_buf_len);
+ if (!e->logged) {
+ e->logged = ISC_TRUE;
+ if (++rrl->num_logged <= 1)
+ rrl->last_logged = e;
+ }
+ e->log_secs = 0;
+
+ /*
+ * Avoid holding the lock.
+ */
+ if (!wouldlog) {
+ UNLOCK(&rrl->lock);
+ e = NULL;
+ }
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
+ DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DROP,
+ "%s", log_buf);
+ }
+
+ /*
+ * Make a log message for the caller.
+ */
+ if (wouldlog)
+ make_log_buf(rrl, e,
+ rrl->log_only ? "would rate limit " : "rate limit ",
+ NULL, ISC_FALSE, qname, ISC_FALSE,
+ rrl_result, resp_result, log_buf, log_buf_len);
+
+ if (e != NULL) {
+ /*
+ * Do not save the qname unless we might need it for
+ * the ending log message.
+ */
+ if (!e->logged)
+ free_qname(rrl, e);
+ UNLOCK(&rrl->lock);
+ }
+
+ return (rrl_result);
+}
+
+void
+dns_rrl_view_destroy(dns_view_t *view) {
+ dns_rrl_t *rrl;
+ dns_rrl_block_t *b;
+ dns_rrl_hash_t *h;
+ char log_buf[DNS_RRL_LOG_BUF_LEN];
+ int i;
+
+ rrl = view->rrl;
+ if (rrl == NULL)
+ return;
+ view->rrl = NULL;
+
+ /*
+ * Assume the caller takes care of locking the view and anything else.
+ */
+
+ if (rrl->num_logged > 0)
+ log_stops(rrl, 0, ISC_INT32_MAX, log_buf, sizeof(log_buf));
+
+ for (i = 0; i < DNS_RRL_QNAMES; ++i) {
+ if (rrl->qnames[i] == NULL)
+ break;
+ isc_mem_put(rrl->mctx, rrl->qnames[i], sizeof(*rrl->qnames[i]));
+ }
+
+ if (rrl->exempt != NULL)
+ dns_acl_detach(&rrl->exempt);
+
+ DESTROYLOCK(&rrl->lock);
+
+ while (!ISC_LIST_EMPTY(rrl->blocks)) {
+ b = ISC_LIST_HEAD(rrl->blocks);
+ ISC_LIST_UNLINK(rrl->blocks, b, link);
+ isc_mem_put(rrl->mctx, b, b->size);
+ }
+
+ h = rrl->hash;
+ if (h != NULL)
+ isc_mem_put(rrl->mctx, h,
+ sizeof(*h) + (h->length - 1) * sizeof(h->bins[0]));
+
+ h = rrl->old_hash;
+ if (h != NULL)
+ isc_mem_put(rrl->mctx, h,
+ sizeof(*h) + (h->length - 1) * sizeof(h->bins[0]));
+
+ isc_mem_putanddetach(&rrl->mctx, rrl, sizeof(*rrl));
+}
+
+isc_result_t
+dns_rrl_init(dns_rrl_t **rrlp, dns_view_t *view, int min_entries) {
+ dns_rrl_t *rrl;
+ isc_result_t result;
+
+ *rrlp = NULL;
+
+ rrl = isc_mem_get(view->mctx, sizeof(*rrl));
+ if (rrl == NULL)
+ return (ISC_R_NOMEMORY);
+ memset(rrl, 0, sizeof(*rrl));
+ isc_mem_attach(view->mctx, &rrl->mctx);
+ result = isc_mutex_init(&rrl->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_putanddetach(&rrl->mctx, rrl, sizeof(*rrl));
+ return (result);
+ }
+ isc_stdtime_get(&rrl->ts_bases[0]);
+
+ view->rrl = rrl;
+
+ result = expand_entries(rrl, min_entries);
+ if (result != ISC_R_SUCCESS) {
+ dns_rrl_view_destroy(view);
+ return (result);
+ }
+ result = expand_rrl_hash(rrl, 0);
+ if (result != ISC_R_SUCCESS) {
+ dns_rrl_view_destroy(view);
+ return (result);
+ }
+
+ *rrlp = rrl;
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/dns/spnego.c b/lib/dns/spnego.c
index 0c1c8583650df..2da79f8b55ce7 100644
--- a/lib/dns/spnego.c
+++ b/lib/dns/spnego.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2006-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
@@ -463,7 +463,7 @@ code_NegTokenArg(OM_uint32 * minor_status,
free(buf);
return (GSS_S_FAILURE);
}
- memcpy(*outbuf, buf + buf_size - buf_len, buf_len);
+ memmove(*outbuf, buf + buf_size - buf_len, buf_len);
*outbuf_size = buf_len;
free(buf);
@@ -856,7 +856,7 @@ der_get_octet_string(const unsigned char *p, size_t len,
data->data = malloc(len);
if (data->data == NULL)
return (ENOMEM);
- memcpy(data->data, p, len);
+ memmove(data->data, p, len);
} else
data->data = NULL;
if (size)
@@ -1107,7 +1107,7 @@ length_len(size_t len)
if (len < 128U)
return (1);
else
- return (len_unsigned(len) + 1);
+ return (len_unsigned((unsigned int)len) + 1);
}
@@ -1191,18 +1191,18 @@ der_put_length(unsigned char *p, size_t len, size_t val, size_t *size)
if (len < 1U)
return (ASN1_OVERFLOW);
if (val < 128U) {
- *p = val;
+ *p = (unsigned char)val;
*size = 1;
return (0);
} else {
size_t l;
int e;
- e = der_put_unsigned(p, len - 1, val, &l);
+ e = der_put_unsigned(p, len - 1, (unsigned int)val, &l);
if (e)
return (e);
p -= l;
- *p = 0x80 | l;
+ *p = 0x80 | (unsigned char)l;
*size = l + 1;
return (0);
}
@@ -1217,7 +1217,7 @@ der_put_octet_string(unsigned char *p, size_t len,
p -= data->length;
len -= data->length;
POST(len);
- memcpy(p + 1, data->data, data->length);
+ memmove(p + 1, data->data, data->length);
*size = data->length;
return (0);
}
@@ -1227,10 +1227,10 @@ der_put_oid(unsigned char *p, size_t len,
const oid *data, size_t *size)
{
unsigned char *base = p;
- int n;
+ size_t n;
- for (n = data->length - 1; n >= 2; --n) {
- unsigned u = data->components[n];
+ for (n = data->length; n >= 3u; --n) {
+ unsigned u = data->components[n - 1];
if (len < 1U)
return (ASN1_OVERFLOW);
@@ -1397,7 +1397,7 @@ gssapi_mech_make_header(u_char *p,
p += len_len;
*p++ = 0x06;
*p++ = mech->length;
- memcpy(p, mech->elements, mech->length);
+ memmove(p, mech->elements, mech->length);
p += mech->length;
return (p);
}
@@ -1430,7 +1430,7 @@ gssapi_spnego_encapsulate(OM_uint32 * minor_status,
gss_release_buffer(minor_status, output_token);
return (GSS_S_FAILURE);
}
- memcpy(p, buf, buf_size);
+ memmove(p, buf, buf_size);
return (GSS_S_COMPLETE);
}
diff --git a/lib/dns/spnego_asn1.c b/lib/dns/spnego_asn1.c
index b506054566935..a90f1be63c2cb 100644
--- a/lib/dns/spnego_asn1.c
+++ b/lib/dns/spnego_asn1.c
@@ -229,7 +229,7 @@ encode_MechTypeList(unsigned char *p, size_t len, const MechTypeList * data, siz
int i, e;
for (i = (data)->len - 1; i >= 0; --i) {
- int oldret = ret;
+ size_t oldret = ret;
ret = 0;
e = encode_MechType(p, len, &(data)->val[i], &l);
BACK;
@@ -257,7 +257,7 @@ decode_MechTypeList(const unsigned char *p, size_t len, MechTypeList * data, siz
len = reallen;
{
size_t origlen = len;
- int oldret = ret;
+ size_t oldret = ret;
ret = 0;
(data)->len = 0;
(data)->val = NULL;
@@ -418,7 +418,7 @@ encode_NegTokenInit(unsigned char *p, size_t len, const NegTokenInit * data, siz
int e;
if ((data)->mechListMIC) {
- int oldret = ret;
+ size_t oldret = ret;
ret = 0;
e = encode_octet_string(p, len, (data)->mechListMIC, &l);
BACK;
@@ -427,7 +427,7 @@ encode_NegTokenInit(unsigned char *p, size_t len, const NegTokenInit * data, siz
ret += oldret;
}
if ((data)->mechToken) {
- int oldret = ret;
+ size_t oldret = ret;
ret = 0;
e = encode_octet_string(p, len, (data)->mechToken, &l);
BACK;
@@ -436,7 +436,7 @@ encode_NegTokenInit(unsigned char *p, size_t len, const NegTokenInit * data, siz
ret += oldret;
}
if ((data)->reqFlags) {
- int oldret = ret;
+ size_t oldret = ret;
ret = 0;
e = encode_ContextFlags(p, len, (data)->reqFlags, &l);
BACK;
@@ -444,7 +444,7 @@ encode_NegTokenInit(unsigned char *p, size_t len, const NegTokenInit * data, siz
BACK;
ret += oldret;
} {
- int oldret = ret;
+ size_t oldret = ret;
ret = 0;
e = encode_MechTypeList(p, len, &(data)->mechTypes, &l);
BACK;
@@ -641,7 +641,7 @@ encode_NegTokenResp(unsigned char *p, size_t len, const NegTokenResp * data, siz
int e;
if ((data)->mechListMIC) {
- int oldret = ret;
+ size_t oldret = ret;
ret = 0;
e = encode_octet_string(p, len, (data)->mechListMIC, &l);
BACK;
@@ -650,7 +650,7 @@ encode_NegTokenResp(unsigned char *p, size_t len, const NegTokenResp * data, siz
ret += oldret;
}
if ((data)->responseToken) {
- int oldret = ret;
+ size_t oldret = ret;
ret = 0;
e = encode_octet_string(p, len, (data)->responseToken, &l);
BACK;
@@ -659,7 +659,7 @@ encode_NegTokenResp(unsigned char *p, size_t len, const NegTokenResp * data, siz
ret += oldret;
}
if ((data)->supportedMech) {
- int oldret = ret;
+ size_t oldret = ret;
ret = 0;
e = encode_MechType(p, len, (data)->supportedMech, &l);
BACK;
@@ -668,7 +668,7 @@ encode_NegTokenResp(unsigned char *p, size_t len, const NegTokenResp * data, siz
ret += oldret;
}
if ((data)->negState) {
- int oldret = ret;
+ size_t oldret = ret;
ret = 0;
e = encode_enumerated(p, len, (data)->negState, &l);
BACK;
diff --git a/lib/dns/ssu.c b/lib/dns/ssu.c
index 49a777a6447e2..7adb769cf35e5 100644
--- a/lib/dns/ssu.c
+++ b/lib/dns/ssu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2010, 2011, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2010, 2011, 2013, 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
@@ -217,7 +217,7 @@ dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
result = ISC_R_NOMEMORY;
goto failure;
}
- memcpy(rule->types, types, ntypes * sizeof(dns_rdatatype_t));
+ memmove(rule->types, types, ntypes * sizeof(dns_rdatatype_t));
} else
rule->types = NULL;
diff --git a/lib/dns/ssu_external.c b/lib/dns/ssu_external.c
index 43d231d63eb09..759482768d8f5 100644
--- a/lib/dns/ssu_external.c
+++ b/lib/dns/ssu_external.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2011-2013 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
@@ -131,7 +131,7 @@ dns_ssu_external_match(dns_name_t *identity,
isc_buffer_t *tkey_token = NULL;
int fd;
const char *sock_path;
- size_t req_len;
+ unsigned int req_len;
isc_region_t token_region;
unsigned char *data;
isc_buffer_t buf;
diff --git a/lib/dns/time.c b/lib/dns/time.c
index 0f245a246a9d8..d331ca3bfe102 100644
--- a/lib/dns/time.c
+++ b/lib/dns/time.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 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
@@ -98,7 +98,7 @@ dns_time64_totext(isc_int64_t t, isc_buffer_t *target) {
if (l > region.length)
return (ISC_R_NOSPACE);
- memcpy(region.base, buf, l);
+ memmove(region.base, buf, l);
isc_buffer_add(target, l);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c
index 161c18808ef46..11b4f49eb04bc 100644
--- a/lib/dns/tkey.c
+++ b/lib/dns/tkey.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-2001, 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -152,7 +152,7 @@ add_rdata_to_list(dns_message_t *msg, dns_name_t *name, dns_rdata_t *rdata,
dns_rdata_toregion(rdata, &r);
RETERR(isc_buffer_allocate(msg->mctx, &tmprdatabuf, r.length));
isc_buffer_availableregion(tmprdatabuf, &newr);
- memcpy(newr.base, r.base, r.length);
+ memmove(newr.base, r.base, r.length);
dns_rdata_fromregion(newrdata, rdata->rdclass, rdata->type, &newr);
dns_message_takebuffer(msg, &tmprdatabuf);
@@ -252,12 +252,12 @@ compute_secret(isc_buffer_t *shared, isc_region_t *queryrandomness,
if (r.length < sizeof(digests) || r.length < r2.length)
return (ISC_R_NOSPACE);
if (r2.length > sizeof(digests)) {
- memcpy(r.base, r2.base, r2.length);
+ memmove(r.base, r2.base, r2.length);
for (i = 0; i < sizeof(digests); i++)
r.base[i] ^= digests[i];
isc_buffer_add(secret, r2.length);
} else {
- memcpy(r.base, digests, sizeof(digests));
+ memmove(r.base, digests, sizeof(digests));
for (i = 0; i < r2.length; i++)
r.base[i] ^= r2.base[i];
isc_buffer_add(secret, sizeof(digests));
@@ -534,7 +534,7 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
goto failure;
}
tkeyout->keylen = isc_buffer_usedlength(outtoken);
- memcpy(tkeyout->key, isc_buffer_base(outtoken),
+ memmove(tkeyout->key, isc_buffer_base(outtoken),
isc_buffer_usedlength(outtoken));
isc_buffer_free(&outtoken);
} else {
@@ -544,7 +544,7 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
goto failure;
}
tkeyout->keylen = tkeyin->keylen;
- memcpy(tkeyout->key, tkeyin->key, tkeyin->keylen);
+ memmove(tkeyout->key, tkeyin->key, tkeyin->keylen);
}
tkeyout->error = dns_rcode_noerror;
diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c
index c7768f4c788a4..00ab570d9e34d 100644
--- a/lib/dns/tsig.c
+++ b/lib/dns/tsig.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-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -1370,21 +1370,21 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
* Extract the header.
*/
isc_buffer_usedregion(source, &r);
- memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
+ memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
/*
* Decrement the additional field counter.
*/
- memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
+ memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
- memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
+ memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
/*
* Put in the original id.
*/
id = htons(tsig.originalid);
- memcpy(&header[0], &id, 2);
+ memmove(&header[0], &id, 2);
/*
* Digest the modified header.
@@ -1609,16 +1609,16 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
* Extract the header.
*/
isc_buffer_usedregion(source, &r);
- memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
+ memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
/*
* Decrement the additional field counter if necessary.
*/
if (has_tsig) {
- memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
+ memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
- memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
+ memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
}
/*
@@ -1627,7 +1627,7 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
/* XXX Can TCP transfers be forwarded? How would that work? */
if (has_tsig) {
id = htons(tsig.originalid);
- memcpy(&header[0], &id, 2);
+ memmove(&header[0], &id, 2);
}
/*
diff --git a/lib/dns/ttl.c b/lib/dns/ttl.c
index d3cf024138db1..c794859064a06 100644
--- a/lib/dns/ttl.c
+++ b/lib/dns/ttl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -53,7 +53,7 @@ ttlfmt(unsigned int t, const char *s, isc_boolean_t verbose,
isc_boolean_t space, isc_buffer_t *target)
{
char tmp[60];
- size_t len;
+ unsigned int len;
isc_region_t region;
if (verbose)
@@ -68,7 +68,7 @@ ttlfmt(unsigned int t, const char *s, isc_boolean_t verbose,
isc_buffer_availableregion(target, &region);
if (len > region.length)
return (ISC_R_NOSPACE);
- memcpy(region.base, tmp, len);
+ memmove(region.base, tmp, len);
isc_buffer_add(target, len);
return (ISC_R_SUCCESS);
diff --git a/lib/dns/update.c b/lib/dns/update.c
index 14ffcc2234d89..e727c347ce93a 100644
--- a/lib/dns/update.c
+++ b/lib/dns/update.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2011-2013 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
@@ -232,7 +232,6 @@ do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
* Create a singleton diff.
*/
dns_diff_init(diff->mctx, &temp_diff);
- temp_diff.resign = diff->resign;
ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
/*
@@ -1211,7 +1210,9 @@ del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
for (i = 0; i < nkeys; i++) {
if (rrsig.keyid == dst_key_id(keys[i])) {
found = ISC_TRUE;
- if (!dst_key_isprivate(keys[i])) {
+ if (!dst_key_isprivate(keys[i]) &&
+ !dst_key_inactive(keys[i]))
+ {
/*
* The re-signing code in zone.c
* will mark this as offline.
@@ -1354,7 +1355,6 @@ dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
dns_diff_init(diff->mctx, &affected);
dns_diff_init(diff->mctx, &sig_diff);
- sig_diff.resign = dns_zone_getsigresigninginterval(zone);
dns_diff_init(diff->mctx, &nsec_diff);
dns_diff_init(diff->mctx, &nsec_mindiff);
diff --git a/lib/dns/validator.c b/lib/dns/validator.c
index 8cf7f665ec88b..d7982caa777a4 100644
--- a/lib/dns/validator.c
+++ b/lib/dns/validator.c
@@ -3753,8 +3753,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
val->keytable = NULL;
result = dns_view_getsecroots(val->view, &val->keytable);
if (result != ISC_R_SUCCESS)
- return (result);
-
+ goto cleanup_mutex;
val->keynode = NULL;
val->key = NULL;
val->siginfo = NULL;
@@ -3787,6 +3786,9 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
return (ISC_R_SUCCESS);
+ cleanup_mutex:
+ DESTROYLOCK(&val->lock);
+
cleanup_event:
isc_task_detach(&tclone);
isc_event_free(ISC_EVENT_PTR(&event));
diff --git a/lib/dns/view.c b/lib/dns/view.c
index 9c1a201a8bd94..142b09edbd748 100644
--- a/lib/dns/view.c
+++ b/lib/dns/view.c
@@ -49,6 +49,7 @@
#include <dns/masterdump.h>
#include <dns/order.h>
#include <dns/peer.h>
+#include <dns/rrl.h>
#include <dns/rbt.h>
#include <dns/rdataset.h>
#include <dns/request.h>
@@ -184,6 +185,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->answeracl_exclude = NULL;
view->denyanswernames = NULL;
view->answernames_exclude = NULL;
+ view->rrl = NULL;
view->provideixfr = ISC_TRUE;
view->maxcachettl = 7 * 24 * 3600;
view->maxncachettl = 3 * 3600;
@@ -335,10 +337,16 @@ destroy(dns_view_t *view) {
dns_acache_detach(&view->acache);
}
dns_rpz_view_destroy(view);
-#else
+#ifdef USE_RRL
+ dns_rrl_view_destroy(view);
+#else /* USE_RRL */
+ INSIST(view->rrl == NULL);
+#endif /* USE_RRL */
+#else /* BIND9 */
INSIST(view->acache == NULL);
INSIST(ISC_LIST_EMPTY(view->rpz_zones));
-#endif
+ INSIST(view->rrl == NULL);
+#endif /* BIND9 */
if (view->requestmgr != NULL)
dns_requestmgr_detach(&view->requestmgr);
if (view->task != NULL)
@@ -560,6 +568,8 @@ dialup(dns_zone_t *zone, void *dummy) {
void
dns_view_dialup(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(view->zonetable != NULL);
+
(void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL);
}
#endif
@@ -868,6 +878,7 @@ dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
+ REQUIRE(view->zonetable != NULL);
result = dns_zt_mount(view->zonetable, zone);
@@ -882,6 +893,7 @@ dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
REQUIRE(DNS_VIEW_VALID(view));
+ LOCK(&view->lock);
if (view->zonetable != NULL) {
result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
if (result == DNS_R_PARTIALMATCH) {
@@ -890,6 +902,7 @@ dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
}
} else
result = ISC_R_NOTFOUND;
+ UNLOCK(&view->lock);
return (result);
}
@@ -952,7 +965,12 @@ dns_view_find2(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
is_staticstub_zone = ISC_FALSE;
#ifdef BIND9
zone = NULL;
- result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+ LOCK(&view->lock);
+ if (view->zonetable != NULL)
+ result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+ else
+ result = ISC_R_NOTFOUND;
+ UNLOCK(&view->lock);
if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub &&
!use_static_stub) {
result = ISC_R_NOTFOUND;
@@ -1223,9 +1241,14 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
*/
#ifdef BIND9
zone = NULL;
- result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+ LOCK(&view->lock);
+ if (view->zonetable != NULL)
+ result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+ else
+ result = ISC_R_NOTFOUND;
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
result = dns_zone_getdb(zone, &db);
+ UNLOCK(&view->lock);
#else
result = ISC_R_NOTFOUND;
#endif
@@ -1404,6 +1427,8 @@ dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name,
dns_zone_t **zp = NULL;;
REQUIRE(list != NULL);
+ REQUIRE(zonep != NULL && *zonep == NULL);
+
for (view = ISC_LIST_HEAD(*list);
view != NULL;
view = ISC_LIST_NEXT(view, link)) {
@@ -1415,7 +1440,13 @@ dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name,
* treat it as not found.
*/
zp = (zone1 == NULL) ? &zone1 : &zone2;
- result = dns_zt_find(view->zonetable, name, 0, NULL, zp);
+ LOCK(&view->lock);
+ if (view->zonetable != NULL)
+ result = dns_zt_find(view->zonetable, name, 0,
+ NULL, zp);
+ else
+ result = ISC_R_NOTFOUND;
+ UNLOCK(&view->lock);
INSIST(result == ISC_R_SUCCESS ||
result == ISC_R_NOTFOUND ||
result == DNS_R_PARTIALMATCH);
@@ -1706,13 +1737,17 @@ dns_view_getrootdelonly(dns_view_t *view) {
#ifdef BIND9
isc_result_t
dns_view_freezezones(dns_view_t *view, isc_boolean_t value) {
+
REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(view->zonetable != NULL);
+
return (dns_zt_freezezones(view->zonetable, value));
}
#endif
void
dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) {
+
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
REQUIRE(view->resstats == NULL);
diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c
index 813f616e6fa08..30f2f3b347f45 100644
--- a/lib/dns/xfrin.c
+++ b/lib/dns/xfrin.c
@@ -221,7 +221,6 @@ static isc_result_t xfrin_start(dns_xfrin_ctx_t *xfr);
static void xfrin_connect_done(isc_task_t *task, isc_event_t *event);
static isc_result_t xfrin_send_request(dns_xfrin_ctx_t *xfr);
static void xfrin_send_done(isc_task_t *task, isc_event_t *event);
-static void xfrin_sendlen_done(isc_task_t *task, isc_event_t *event);
static void xfrin_recv_done(isc_task_t *task, isc_event_t *event);
static void xfrin_timeout(isc_task_t *task, isc_event_t *event);
@@ -270,13 +269,18 @@ axfr_init(dns_xfrin_ctx_t *xfr) {
static isc_result_t
axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
- return (dns_db_create(xfr->mctx, /* XXX */
- "rbt", /* XXX guess */
- &xfr->name,
- dns_dbtype_zone,
- xfr->rdclass,
- 0, NULL, /* XXX guess */
- dbp));
+ isc_result_t result;
+
+ result = dns_db_create(xfr->mctx, /* XXX */
+ "rbt", /* XXX guess */
+ &xfr->name,
+ dns_dbtype_zone,
+ xfr->rdclass,
+ 0, NULL, /* XXX guess */
+ dbp);
+ if (result == ISC_R_SUCCESS)
+ result = dns_zone_rpz_enable_db(xfr->zone, *dbp);
+ return (result);
}
static isc_result_t
@@ -861,8 +865,11 @@ xfrin_create(isc_mem_t *mctx,
xfr->sourceaddr = *sourceaddr;
isc_sockaddr_setport(&xfr->sourceaddr, 0);
- isc_buffer_init(&xfr->qbuffer, xfr->qbuffer_data,
- sizeof(xfr->qbuffer_data));
+ /*
+ * Reserve 2 bytes for TCP length at the begining of the buffer.
+ */
+ isc_buffer_init(&xfr->qbuffer, &xfr->qbuffer_data[2],
+ sizeof(xfr->qbuffer_data) - 2);
xfr->magic = XFRIN_MAGIC;
*xfrp = xfr;
@@ -938,6 +945,8 @@ xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
isc_result_t result = cev->result;
char sourcetext[ISC_SOCKADDR_FORMATSIZE];
isc_sockaddr_t sockaddr;
+ dns_zonemgr_t * zmgr;
+ isc_time_t now;
REQUIRE(VALID_XFRIN(xfr));
@@ -952,16 +961,16 @@ xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
return;
}
- if (result != ISC_R_SUCCESS) {
- dns_zonemgr_t * zmgr = dns_zone_getmgr(xfr->zone);
- isc_time_t now;
-
- if (zmgr != NULL) {
+ zmgr = dns_zone_getmgr(xfr->zone);
+ if (zmgr != NULL) {
+ if (result != ISC_R_SUCCESS) {
TIME_NOW(&now);
dns_zonemgr_unreachableadd(zmgr, &xfr->masteraddr,
&xfr->sourceaddr, &now);
- }
- goto failure;
+ goto failure;
+ } else
+ dns_zonemgr_unreachabledel(zmgr, &xfr->masteraddr,
+ &xfr->sourceaddr);
}
result = isc_socket_getsockname(xfr->socket, &sockaddr);
@@ -1042,10 +1051,8 @@ static isc_result_t
xfrin_send_request(dns_xfrin_ctx_t *xfr) {
isc_result_t result;
isc_region_t region;
- isc_region_t lregion;
dns_rdataset_t *qrdataset = NULL;
dns_message_t *msg = NULL;
- unsigned char length[2];
dns_difftuple_t *soatuple = NULL;
dns_name_t *qname = NULL;
dns_dbversion_t *ver = NULL;
@@ -1114,12 +1121,16 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
isc_buffer_usedregion(&xfr->qbuffer, &region);
INSIST(region.length <= 65535);
- length[0] = region.length >> 8;
- length[1] = region.length & 0xFF;
- lregion.base = length;
- lregion.length = 2;
- CHECK(isc_socket_send(xfr->socket, &lregion, xfr->task,
- xfrin_sendlen_done, xfr));
+ /*
+ * Record message length and adjust region to include TCP
+ * length field.
+ */
+ xfr->qbuffer_data[0] = (region.length >> 8) & 0xff;
+ xfr->qbuffer_data[1] = region.length & 0xff;
+ region.base -= 2;
+ region.length += 2;
+ CHECK(isc_socket_send(xfr->socket, &region, xfr->task,
+ xfrin_send_done, xfr));
xfr->sends++;
failure:
@@ -1136,42 +1147,6 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
return (result);
}
-/* XXX there should be library support for sending DNS TCP messages */
-
-static void
-xfrin_sendlen_done(isc_task_t *task, isc_event_t *event) {
- isc_socketevent_t *sev = (isc_socketevent_t *) event;
- dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
- isc_result_t evresult = sev->result;
- isc_result_t result;
- isc_region_t region;
-
- REQUIRE(VALID_XFRIN(xfr));
-
- UNUSED(task);
-
- INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
- isc_event_free(&event);
-
- xfr->sends--;
- if (xfr->shuttingdown) {
- maybe_free(xfr);
- return;
- }
-
- xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request length prefix");
- CHECK(evresult);
-
- isc_buffer_usedregion(&xfr->qbuffer, &region);
- CHECK(isc_socket_send(xfr->socket, &region, xfr->task,
- xfrin_send_done, xfr));
- xfr->sends++;
- failure:
- if (result != ISC_R_SUCCESS)
- xfrin_fail(xfr, result, "failed sending request length prefix");
-}
-
-
static void
xfrin_send_done(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sev = (isc_socketevent_t *) event;
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 10ba807c52f17..01ff97b11dcbc 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.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
@@ -37,6 +37,7 @@
#include <isc/strerror.h>
#include <isc/string.h>
#include <isc/taskpool.h>
+#include <isc/thread.h>
#include <isc/timer.h>
#include <isc/util.h>
@@ -162,10 +163,20 @@ typedef struct dns_asyncload dns_asyncload_t;
#define UNLOCK_ZONE(z) \
do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
#define LOCKED_ZONE(z) ((z)->locked)
+#define TRYLOCK_ZONE(result, z) \
+ do { \
+ result = isc_mutex_trylock(&(z)->lock); \
+ if (result == ISC_R_SUCCESS) { \
+ INSIST((z)->locked == ISC_FALSE); \
+ (z)->locked = ISC_TRUE; \
+ } \
+ } while (0)
#else
#define LOCK_ZONE(z) LOCK(&(z)->lock)
#define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
#define LOCKED_ZONE(z) ISC_TRUE
+#define TRYLOCK_ZONE(result, z) \
+ do { result = isc_mutex_trylock(&(z)->lock); } while (0)
#endif
#ifdef ISC_RWLOCK_USEATOMIC
@@ -455,6 +466,7 @@ struct dns_unreachable {
isc_sockaddr_t local;
isc_uint32_t expire;
isc_uint32_t last;
+ isc_uint32_t count;
};
struct dns_zonemgr {
@@ -468,7 +480,8 @@ struct dns_zonemgr {
isc_taskpool_t * loadtasks;
isc_task_t * task;
isc_pool_t * mctxpool;
- isc_ratelimiter_t * rl;
+ isc_ratelimiter_t * notifyrl;
+ isc_ratelimiter_t * refreshrl;
isc_rwlock_t rwlock;
isc_mutex_t iolock;
isc_rwlock_t urlock;
@@ -673,7 +686,6 @@ static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
static isc_result_t zone_send_secureserial(dns_zone_t *zone,
- isc_boolean_t secure_locked,
isc_uint32_t serial);
#if 0
@@ -729,10 +741,7 @@ static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
dns_dbnode_t *node, dns_name_t *name,
dns_diff_t *diff);
static void zone_rekey(dns_zone_t *zone);
-static isc_boolean_t delsig_ok(dns_rdata_rrsig_t *rrsig_ptr,
- dst_key_t **keys, unsigned int nkeys);
-static isc_result_t zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked,
- dns_db_t *db);
+static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
#define ENTER zone_debuglog(zone, me, 1, "enter")
@@ -767,6 +776,20 @@ static const char *dbargv_default[] = { "rbt" };
} \
} while (0)
+typedef struct nsec3param nsec3param_t;
+struct nsec3param {
+ unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
+ unsigned int length;
+ isc_boolean_t nsec;
+ isc_boolean_t replace;
+ ISC_LINK(nsec3param_t) link;
+};
+typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
+struct np3event {
+ isc_event_t event;
+ nsec3param_t params;
+};
+
/*%
* Increment resolver-related statistics counters. Zone must be locked.
*/
@@ -967,6 +990,7 @@ zone_free(dns_zone_t *zone) {
REQUIRE(zone->irefs == 0);
REQUIRE(!LOCKED_ZONE(zone));
REQUIRE(zone->timer == NULL);
+ REQUIRE(zone->zmgr == NULL);
/*
* Managed objects. Order is important.
@@ -981,8 +1005,6 @@ zone_free(dns_zone_t *zone) {
isc_task_detach(&zone->task);
if (zone->loadtask != NULL)
isc_task_detach(&zone->loadtask);
- if (zone->zmgr != NULL)
- dns_zonemgr_releasezone(zone->zmgr, zone);
/* Unmanaged objects */
for (signing = ISC_LIST_HEAD(zone->signing);
@@ -1534,6 +1556,18 @@ dns_zone_get_rpz(dns_zone_t *zone) {
return (zone->is_rpz);
}
+/*
+ * If a zone is a response policy zone, mark its new database.
+ */
+isc_result_t
+dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
+#ifdef BIND9
+ if (zone->is_rpz)
+ return (dns_db_rpz_enabled(db, NULL));
+#endif
+ return (ISC_R_SUCCESS);
+}
+
static isc_result_t
zone_load(dns_zone_t *zone, unsigned int flags) {
isc_result_t result;
@@ -1880,8 +1914,7 @@ zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
result = dns_master_loadfileinc3(load->zone->masterfile,
dns_db_origin(load->db),
dns_db_origin(load->db),
- load->zone->rdclass, options,
- load->zone->sigresigninginterval,
+ load->zone->rdclass, options, 0,
&load->callbacks, task,
zone_loaddone, load,
&load->zone->lctx, load->zone->mctx,
@@ -1933,15 +1966,20 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
LOCK_ZONE(zone);
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
if (zone->db != NULL) {
+ const dns_master_style_t *output_style;
+
dns_db_currentversion(zone->db, &version);
dns_master_initrawheader(&rawdata);
if (inline_secure(zone))
get_raw_serial(zone->raw, &rawdata);
+ if (zone->type == dns_zone_key)
+ output_style = &dns_master_style_keyzone;
+ else
+ output_style = &dns_master_style_default;
result = dns_master_dumpinc3(zone->mctx, zone->db, version,
- &dns_master_style_default,
- zone->masterfile, zone->task,
- dump_done, zone, &zone->dctx,
- zone->masterformat, &rawdata);
+ output_style, zone->masterfile,
+ zone->task, dump_done, zone, &zone->dctx, zone->masterformat,
+ &rawdata);
dns_db_closeversion(zone->db, &version, ISC_FALSE);
} else
result = ISC_R_CANCELED;
@@ -1987,14 +2025,9 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
isc_result_t tresult;
unsigned int options;
-#ifdef BIND9
- if (zone->is_rpz) {
- result = dns_db_rpz_enabled(db, NULL);
- if (result != ISC_R_SUCCESS)
- return (result);
- }
-#endif
-
+ result = dns_zone_rpz_enable_db(zone, db);
+ if (result != ISC_R_SUCCESS)
+ return (result);
options = get_master_options(zone);
if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
options |= DNS_MASTER_MANYERRORS;
@@ -2047,8 +2080,7 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
}
result = dns_master_loadfile3(zone->masterfile,
&zone->origin, &zone->origin,
- zone->rdclass, options,
- zone->sigresigninginterval,
+ zone->rdclass, options, 0,
&callbacks, zone->mctx,
zone->masterformat);
tresult = dns_db_endload(db, &callbacks.add_private);
@@ -2485,7 +2517,7 @@ isspf(const dns_rdata_t *rdata) {
INSIST(tl <= rdl);
if (len > sizeof(buf) - i - 1)
len = sizeof(buf) - i - 1;
- memcpy(buf + i, data, len);
+ memmove(buf + i, data, len);
i += len;
data += tl;
rdl -= tl;
@@ -2737,14 +2769,22 @@ resume_signingwithkey(dns_zone_t *zone) {
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_t rdataset;
isc_result_t result;
+ dns_db_t *db = NULL;
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL)
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ if (db == NULL)
+ goto cleanup;
- result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
+ result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
if (result != ISC_R_SUCCESS)
goto cleanup;
- dns_db_currentversion(zone->db, &version);
+ dns_db_currentversion(db, &version);
dns_rdataset_init(&rdataset);
- result = dns_db_findrdataset(zone->db, node, version,
+ result = dns_db_findrdataset(db, node, version,
zone->privatetype,
dns_rdatatype_none, 0,
&rdataset, NULL);
@@ -2777,10 +2817,13 @@ resume_signingwithkey(dns_zone_t *zone) {
dns_rdataset_disassociate(&rdataset);
cleanup:
- if (node != NULL)
- dns_db_detachnode(zone->db, &node);
- if (version != NULL)
- dns_db_closeversion(zone->db, &version, ISC_FALSE);
+ if (db != NULL) {
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (version != NULL)
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ dns_db_detach(&db);
+ }
}
static isc_result_t
@@ -2793,18 +2836,33 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
unsigned int options = 0;
char saltbuf[255*2+1];
char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
+ dns_db_t *db = NULL;
int i;
- dns_db_currentversion(zone->db, &version);
- result = dns_nsec_nseconly(zone->db, version, &nseconly);
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL)
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ if (db == NULL) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+ dns_db_currentversion(db, &version);
+ result = dns_nsec_nseconly(db, version, &nseconly);
nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
- dns_db_closeversion(zone->db, &version, ISC_FALSE);
- if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0)
- return (ISC_R_SUCCESS);
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
- if (nsec3chain == NULL)
- return (ISC_R_NOMEMORY);
+ if (nsec3chain == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
nsec3chain->magic = 0;
nsec3chain->done = ISC_FALSE;
@@ -2816,7 +2874,7 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
nsec3chain->nsec3param.iterations = nsec3param->iterations;
nsec3chain->nsec3param.flags = nsec3param->flags;
nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
- memcpy(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
+ memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
nsec3chain->nsec3param.salt = nsec3chain->salt;
nsec3chain->seen_nsec = ISC_FALSE;
nsec3chain->delete_nsec = ISC_FALSE;
@@ -2866,7 +2924,7 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
for (current = ISC_LIST_HEAD(zone->nsec3chain);
current != NULL;
current = ISC_LIST_NEXT(current, link)) {
- if (current->db == zone->db &&
+ if (current->db == db &&
current->nsec3param.hash == nsec3param->hash &&
current->nsec3param.iterations == nsec3param->iterations &&
current->nsec3param.salt_length == nsec3param->salt_length
@@ -2875,28 +2933,25 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
current->done = ISC_TRUE;
}
- if (zone->db != NULL) {
- dns_db_attach(zone->db, &nsec3chain->db);
- if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
- options = DNS_DB_NONSEC3;
- result = dns_db_createiterator(nsec3chain->db, options,
- &nsec3chain->dbiterator);
- if (result == ISC_R_SUCCESS)
- dns_dbiterator_first(nsec3chain->dbiterator);
- if (result == ISC_R_SUCCESS) {
- dns_dbiterator_pause(nsec3chain->dbiterator);
- ISC_LIST_INITANDAPPEND(zone->nsec3chain,
- nsec3chain, link);
- nsec3chain = NULL;
- if (isc_time_isepoch(&zone->nsec3chaintime)) {
- TIME_NOW(&now);
- zone->nsec3chaintime = now;
- if (zone->task != NULL)
- zone_settimer(zone, &now);
- }
+ dns_db_attach(db, &nsec3chain->db);
+ if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
+ options = DNS_DB_NONSEC3;
+ result = dns_db_createiterator(nsec3chain->db, options,
+ &nsec3chain->dbiterator);
+ if (result == ISC_R_SUCCESS)
+ dns_dbiterator_first(nsec3chain->dbiterator);
+ if (result == ISC_R_SUCCESS) {
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ ISC_LIST_INITANDAPPEND(zone->nsec3chain,
+ nsec3chain, link);
+ nsec3chain = NULL;
+ if (isc_time_isepoch(&zone->nsec3chaintime)) {
+ TIME_NOW(&now);
+ zone->nsec3chaintime = now;
+ if (zone->task != NULL)
+ zone_settimer(zone, &now);
}
- } else
- result = ISC_R_NOTFOUND;
+ }
if (nsec3chain != NULL) {
if (nsec3chain->db != NULL)
@@ -2905,6 +2960,10 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
dns_dbiterator_destroy(&nsec3chain->dbiterator);
isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
}
+
+ cleanup:
+ if (db != NULL)
+ dns_db_detach(&db);
return (result);
}
@@ -2916,21 +2975,29 @@ resume_addnsec3chain(dns_zone_t *zone) {
isc_result_t result;
dns_rdata_nsec3param_t nsec3param;
isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
+ dns_db_t *db = NULL;
if (zone->privatetype == 0)
return;
- result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL)
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ if (db == NULL)
+ goto cleanup;
+
+ result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
if (result != ISC_R_SUCCESS)
goto cleanup;
- dns_db_currentversion(zone->db, &version);
+ dns_db_currentversion(db, &version);
- result = dns_nsec_nseconly(zone->db, version, &nseconly);
+ result = dns_nsec_nseconly(db, version, &nseconly);
nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
dns_rdataset_init(&rdataset);
- result = dns_db_findrdataset(zone->db, node, version,
+ result = dns_db_findrdataset(db, node, version,
zone->privatetype, dns_rdatatype_none,
0, &rdataset, NULL);
if (result != ISC_R_SUCCESS) {
@@ -2965,10 +3032,13 @@ resume_addnsec3chain(dns_zone_t *zone) {
}
dns_rdataset_disassociate(&rdataset);
cleanup:
- if (node != NULL)
- dns_db_detachnode(zone->db, &node);
- if (version != NULL)
- dns_db_closeversion(zone->db, &version, ISC_FALSE);
+ if (db != NULL) {
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (version != NULL)
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ dns_db_detach(&db);
+ }
}
static void
@@ -2978,20 +3048,35 @@ set_resigntime(dns_zone_t *zone) {
unsigned int resign;
isc_result_t result;
isc_uint32_t nanosecs;
+ dns_db_t *db = NULL;
dns_rdataset_init(&rdataset);
dns_fixedname_init(&fixed);
- result = dns_db_getsigningtime(zone->db, &rdataset,
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL)
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ if (db == NULL) {
+ isc_time_settoepoch(&zone->resigntime);
+ return;
+ }
+
+ result = dns_db_getsigningtime(db, &rdataset,
dns_fixedname_name(&fixed));
if (result != ISC_R_SUCCESS) {
isc_time_settoepoch(&zone->resigntime);
- return;
+ goto cleanup;
}
- resign = rdataset.resign;
+
+ resign = rdataset.resign - zone->sigresigninginterval;
dns_rdataset_disassociate(&rdataset);
isc_random_get(&nanosecs);
nanosecs %= 1000000000;
isc_time_set(&zone->resigntime, resign, nanosecs);
+ cleanup:
+ dns_db_detach(&db);
+ return;
}
static isc_result_t
@@ -3334,6 +3419,8 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
/* Convert rdata to keydata. */
result = dns_rdata_tostruct(&rdata, &keydata, NULL);
+ if (result == ISC_R_UNEXPECTEDEND)
+ continue;
RUNTIME_CHECK(result == ISC_R_SUCCESS);
/* Set the key refresh timer. */
@@ -3387,7 +3474,6 @@ do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
* Create a singleton diff.
*/
dns_diff_init(diff->mctx, &temp_diff);
- temp_diff.resign = diff->resign;
ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
/*
@@ -3739,9 +3825,9 @@ maybe_send_secure(dns_zone_t *zone) {
NULL, &soacount, &serial, NULL,
NULL, NULL, NULL, NULL);
if (result == ISC_R_SUCCESS && soacount > 0U)
- zone_send_secureserial(zone->raw, ISC_TRUE, serial);
+ zone_send_secureserial(zone->raw, serial);
} else
- zone_send_securedb(zone->raw, ISC_TRUE, zone->raw->db);
+ zone_send_securedb(zone->raw, zone->raw->db);
} else
DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
@@ -3763,6 +3849,7 @@ zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
/*
* The zone is presumed to be locked.
+ * If this is a inline_raw zone the secure version is also locked.
*/
static isc_result_t
zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
@@ -3778,6 +3865,10 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
isc_boolean_t nomaster = ISC_FALSE;
unsigned int options;
+ INSIST(LOCKED_ZONE(zone));
+ if (inline_raw(zone))
+ INSIST(LOCKED_ZONE(zone->secure));
+
TIME_NOW(&now);
/*
@@ -3855,8 +3946,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
else
options = 0;
result = dns_journal_rollforward2(zone->mctx, db, options,
- zone->sigresigninginterval,
- zone->journal);
+ 0, zone->journal);
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
result != ISC_R_RANGE) {
@@ -4128,9 +4218,9 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
inline_raw(zone))
{
if (zone->secure->db == NULL)
- zone_send_securedb(zone, ISC_FALSE, db);
+ zone_send_securedb(zone, db);
else
- zone_send_secureserial(zone, ISC_FALSE, serial);
+ zone_send_secureserial(zone, serial);
}
}
@@ -4183,7 +4273,8 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
dns_zone_log(zone, ISC_LOG_DEBUG(3),
"next resign: %s/%s in %d seconds",
namebuf, typebuf,
- next.resign - timenow);
+ next.resign - timenow -
+ zone->sigresigninginterval);
dns_rdataset_disassociate(&next);
} else
dns_zone_log(zone, ISC_LOG_WARNING,
@@ -4231,12 +4322,9 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
static isc_boolean_t
exit_check(dns_zone_t *zone) {
-
REQUIRE(LOCKED_ZONE(zone));
- if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
- zone->irefs == 0)
- {
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
/*
* DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
*/
@@ -4891,7 +4979,7 @@ set_addrkeylist(unsigned int count,
newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
if (newaddrs == NULL)
return (ISC_R_NOMEMORY);
- memcpy(newaddrs, addrs, count * sizeof(*newaddrs));
+ memmove(newaddrs, addrs, count * sizeof(*newaddrs));
newnames = NULL;
if (names != NULL) {
@@ -5153,6 +5241,7 @@ find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
const char *directory = dns_zone_getkeydirectory(zone);
CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
+ memset(keys, 0, sizeof(*keys) * maxkeys);
result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
directory, mctx, maxkeys, keys,
nkeys);
@@ -5219,19 +5308,39 @@ set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
* have no new key.
*/
static isc_boolean_t
-delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys) {
+delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
+ isc_boolean_t *warn)
+{
unsigned int i = 0;
+ isc_boolean_t have_ksk = ISC_FALSE, have_zsk = ISC_FALSE;
+ isc_boolean_t have_pksk = ISC_FALSE, have_pzsk = ISC_FALSE;
- /*
- * It's okay to delete a signature if there is an active ZSK
- * with the same algorithm
- */
for (i = 0; i < nkeys; i++) {
- if (rrsig_ptr->algorithm == dst_key_alg(keys[i]) &&
- (dst_key_isprivate(keys[i])) && !KSK(keys[i]))
- return (ISC_TRUE);
+ if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
+ continue;
+ if (dst_key_isprivate(keys[i])) {
+ if (KSK(keys[i]))
+ have_ksk = have_pksk = ISC_TRUE;
+ else
+ have_zsk = have_pzsk = ISC_TRUE;
+ } else {
+ if (KSK(keys[i]))
+ have_ksk = ISC_TRUE;
+ else
+ have_zsk = ISC_TRUE;
+ }
}
+ if (have_zsk && have_ksk && !have_pzsk)
+ *warn = ISC_TRUE;
+
+ /*
+ * It's okay to delete a signature if there is an active key
+ * with the same algorithm to replace it.
+ */
+ if (have_pksk || have_pzsk)
+ return (ISC_TRUE);
+
/*
* Failing that, it is *not* okay to delete a signature
* if the associated public key is still in the DNSKEY RRset
@@ -5299,7 +5408,8 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (type != dns_rdatatype_dnskey) {
- if (delsig_ok(&rrsig, keys, nkeys)) {
+ isc_boolean_t warn = ISC_FALSE, deleted = ISC_FALSE;
+ if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
result = update_one_rr(db, ver, zonediff->diff,
DNS_DIFFOP_DELRESIGN, name,
rdataset.ttl, &rdata);
@@ -5307,7 +5417,9 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
changed = ISC_TRUE;
if (result != ISC_R_SUCCESS)
break;
- } else {
+ deleted = ISC_TRUE;
+ }
+ if (warn) {
/*
* At this point, we've got an RRSIG,
* which is signed by an inactive key.
@@ -5317,7 +5429,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
* offline will prevent us spinning waiting
* for the private part.
*/
- if (incremental) {
+ if (incremental && !deleted) {
result = offline(db, ver, zonediff,
name, rdataset.ttl,
&rdata);
@@ -5365,7 +5477,9 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
* We want the earliest offline expire time
* iff there is a new offline signature.
*/
- if (!dst_key_isprivate(keys[i])) {
+ if (!dst_key_inactive(keys[i]) &&
+ !dst_key_isprivate(keys[i]))
+ {
isc_int64_t timeexpire =
dns_time64_from32(rrsig.timeexpire);
if (warn != 0 && warn > timeexpire)
@@ -5383,6 +5497,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
result = offline(db, ver, zonediff,
name, rdataset.ttl,
&rdata);
+ changed = ISC_TRUE;
break;
}
result = update_one_rr(db, ver, zonediff->diff,
@@ -5551,7 +5666,6 @@ zone_resigninc(dns_zone_t *zone) {
dns_rdataset_init(&rdataset);
dns_fixedname_init(&fixed);
dns_diff_init(zone->mctx, &_sig_diff);
- _sig_diff.resign = zone->sigresigninginterval;
zonediff_init(&zonediff, &_sig_diff);
/*
@@ -5611,7 +5725,7 @@ zone_resigninc(dns_zone_t *zone) {
i = 0;
while (result == ISC_R_SUCCESS) {
- resign = rdataset.resign;
+ resign = rdataset.resign - zone->sigresigninginterval;
covers = rdataset.covers;
dns_rdataset_disassociate(&rdataset);
@@ -6480,7 +6594,6 @@ zone_nsec3chain(dns_zone_t *zone) {
dns_diff_init(zone->mctx, &nsec3_diff);
dns_diff_init(zone->mctx, &nsec_diff);
dns_diff_init(zone->mctx, &_sig_diff);
- _sig_diff.resign = zone->sigresigninginterval;
zonediff_init(&zonediff, &_sig_diff);
ISC_LIST_INIT(cleanup);
@@ -7326,7 +7439,6 @@ zone_sign(dns_zone_t *zone) {
dns_fixedname_init(&nextfixed);
nextname = dns_fixedname_name(&nextfixed);
dns_diff_init(zone->mctx, &_sig_diff);
- _sig_diff.resign = zone->sigresigninginterval;
dns_diff_init(zone->mctx, &post_diff);
zonediff_init(&zonediff, &_sig_diff);
ISC_LIST_INIT(cleanup);
@@ -7340,8 +7452,13 @@ zone_sign(dns_zone_t *zone) {
}
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
- dns_db_attach(zone->db, &db);
+ if (zone->db != NULL)
+ dns_db_attach(zone->db, &db);
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ if (db == NULL) {
+ result = ISC_R_FAILURE;
+ goto failure;
+ }
result = dns_db_newversion(db, &version);
if (result != ISC_R_SUCCESS) {
@@ -7760,7 +7877,7 @@ zone_sign(dns_zone_t *zone) {
isc_time_settoepoch(&zone->signingtime);
}
-static void
+static isc_result_t
normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
unsigned char *data, int size) {
dns_rdata_dnskey_t dnskey;
@@ -7781,6 +7898,8 @@ normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
break;
case dns_rdatatype_keydata:
result = dns_rdata_tostruct(rr, &keydata, NULL);
+ if (result == ISC_R_UNEXPECTEDEND)
+ return (result);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
dns_keydata_todnskey(&keydata, &dnskey, NULL);
dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
@@ -7789,6 +7908,7 @@ normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
default:
INSIST(0);
}
+ return (ISC_R_SUCCESS);
}
/*
@@ -7812,14 +7932,18 @@ matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
dns_rdata_init(&rdata1);
dns_rdata_init(&rdata2);
- normalize_key(rr, &rdata1, data1, sizeof(data1));
+ result = normalize_key(rr, &rdata1, data1, sizeof(data1));
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
for (result = dns_rdataset_first(rdset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdset)) {
dns_rdata_reset(&rdata);
dns_rdataset_current(rdset, &rdata);
- normalize_key(&rdata, &rdata2, data2, sizeof(data2));
+ result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
+ if (result != ISC_R_SUCCESS)
+ continue;
if (dns_rdata_compare(&rdata1, &rdata2) == 0)
return (ISC_TRUE);
}
@@ -7926,7 +8050,11 @@ minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
name, 0, &rdata));
/* Update refresh timer */
- CHECK(dns_rdata_tostruct(&rdata, &keydata, NULL));
+ result = dns_rdata_tostruct(&rdata, &keydata, NULL);
+ if (result == ISC_R_UNEXPECTEDEND)
+ continue;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
keydata.refresh = refresh_time(kfetch, ISC_TRUE);
set_refreshkeytimer(zone, &keydata, now);
@@ -8077,7 +8205,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
INSIST(result == ISC_R_SUCCESS);
dns_diff_init(mctx, &diff);
- diff.resign = zone->sigresigninginterval;
CHECK(dns_db_newversion(kfetch->db, &ver));
@@ -8823,11 +8950,29 @@ void
dns_zone_markdirty(dns_zone_t *zone) {
isc_uint32_t serial;
isc_result_t result = ISC_R_SUCCESS;
+ dns_zone_t *secure = NULL;
+ /*
+ * Obtaining a lock on the zone->secure (see zone_send_secureserial)
+ * could result in a deadlock due to a LOR so we will spin if we
+ * can't obtain the both locks.
+ */
+ again:
LOCK_ZONE(zone);
if (zone->type == dns_zone_master) {
if (inline_raw(zone)) {
unsigned int soacount;
+ secure = zone->secure;
+ INSIST(secure != zone);
+ TRYLOCK_ZONE(result, secure);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK_ZONE(zone);
+ secure = NULL;
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_thread_yield();
+#endif
+ goto again;
+ }
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
if (zone->db != NULL) {
@@ -8839,13 +8984,15 @@ dns_zone_markdirty(dns_zone_t *zone) {
result = DNS_R_NOTLOADED;
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
if (result == ISC_R_SUCCESS && soacount > 0U)
- zone_send_secureserial(zone, ISC_FALSE, serial);
+ zone_send_secureserial(zone, serial);
}
/* XXXMPA make separate call back */
if (result == ISC_R_SUCCESS)
set_resigntime(zone);
}
+ if (secure != NULL)
+ UNLOCK_ZONE(secure);
zone_needdump(zone, DNS_DUMP_DELAY);
UNLOCK_ZONE(zone);
}
@@ -9156,15 +9303,20 @@ zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
result = DNS_R_CONTINUE;
UNLOCK_ZONE(zone);
} else {
+ const dns_master_style_t *output_style;
+
dns_masterrawheader_t rawdata;
dns_db_currentversion(db, &version);
dns_master_initrawheader(&rawdata);
if (inline_secure(zone))
get_raw_serial(zone->raw, &rawdata);
+ if (zone->type == dns_zone_key)
+ output_style = &dns_master_style_keyzone;
+ else
+ output_style = &dns_master_style_default;
result = dns_master_dump3(zone->mctx, db, version,
- &dns_master_style_default,
- masterfile, masterformat,
- &rawdata);
+ output_style, masterfile,
+ masterformat, &rawdata);
dns_db_closeversion(db, &version, ISC_FALSE);
}
fail:
@@ -9311,7 +9463,6 @@ forward_cancel(dns_zone_t *zone) {
static void
zone_unload(dns_zone_t *zone) {
-
/*
* 'zone' locked by caller.
*/
@@ -9565,7 +9716,7 @@ notify_send_queue(dns_notify_t *notify) {
return (ISC_R_NOMEMORY);
e->ev_arg = notify;
e->ev_sender = NULL;
- result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
+ result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
notify->zone->task, &e);
if (result != ISC_R_SUCCESS)
isc_event_free(&e);
@@ -10331,6 +10482,12 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
LOCK_ZONE(zone);
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
+ isc_event_free(&event);
+ dns_request_destroy(&zone->request);
+ goto detach;
+ }
+
/*
* if timeout log and next master;
*/
@@ -10718,7 +10875,7 @@ queue_soa_query(dns_zone_t *zone) {
e->ev_arg = zone;
e->ev_sender = NULL;
- result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
+ result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
if (result != ISC_R_SUCCESS) {
zone_idetach(&dummy);
isc_event_free(&e);
@@ -11279,6 +11436,12 @@ zone_shutdown(isc_task_t *task, isc_event_t *event) {
linked = ISC_TRUE;
zone->statelist = NULL;
}
+ if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
+ ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
+ statelink);
+ zone->statelist = NULL;
+ zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
+ }
RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
}
@@ -11288,6 +11451,10 @@ zone_shutdown(isc_task_t *task, isc_event_t *event) {
if (zone->xfr != NULL)
dns_xfrin_shutdown(zone->xfr);
+ /* Safe to release the zone now */
+ if (zone->zmgr != NULL)
+ dns_zonemgr_releasezone(zone->zmgr, zone);
+
LOCK_ZONE(zone);
if (linked) {
INSIST(zone->irefs > 0);
@@ -11439,10 +11606,10 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) {
isc_time_compare(&zone->refreshtime, &next) < 0)
next = zone->refreshtime;
}
- if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
- INSIST(!isc_time_isepoch(&zone->expiretime));
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
+ !isc_time_isepoch(&zone->expiretime)) {
if (isc_time_isepoch(&next) ||
- isc_time_compare(&zone->expiretime, &next) < 0)
+ isc_time_compare(&zone->expiretime, &next) < 0)
next = zone->expiretime;
}
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
@@ -12102,7 +12269,7 @@ zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
/*
* Leave space for terminating '\0'.
*/
- isc_buffer_init(&buffer, buf, length - 1);
+ isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
if (dns_name_dynamic(&zone->origin))
result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
@@ -12140,7 +12307,7 @@ zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
/*
* Leave space for terminating '\0'.
*/
- isc_buffer_init(&buffer, buf, length - 1);
+ isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
if (dns_name_dynamic(&zone->origin))
result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
if (result != ISC_R_SUCCESS &&
@@ -12160,7 +12327,7 @@ zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
/*
* Leave space for terminating '\0'.
*/
- isc_buffer_init(&buffer, buf, length - 1);
+ isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
(void)dns_rdataclass_totext(zone->rdclass, &buffer);
buf[isc_buffer_usedlength(&buffer)] = '\0';
@@ -12177,7 +12344,7 @@ zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
/*
* Leave space for terminating '\0'.
*/
- isc_buffer_init(&buffer, buf, length - 1);
+ isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
if (zone->view == NULL) {
isc_buffer_putstr(&buffer, "_none");
@@ -12644,6 +12811,7 @@ sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb,
static void
receive_secure_serial(isc_task_t *task, isc_event_t *event) {
+ static char me[] = "receive_secure_serial";
isc_result_t result;
dns_journal_t *rjournal = NULL;
isc_uint32_t start, end;
@@ -12659,16 +12827,23 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) {
end = ((struct secure_event *)event)->serial;
isc_event_free(&event);
+ ENTER;
+
LOCK_ZONE(zone);
dns_diff_init(zone->mctx, &diff);
UNUSED(task);
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL)
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
/*
* zone->db may be NULL if the load from disk failed.
*/
- if (zone->db == NULL || !inline_secure(zone)) {
+ if (db == NULL || !inline_secure(zone)) {
result = ISC_R_FAILURE;
goto failure;
}
@@ -12713,7 +12888,6 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) {
}
}
- dns_db_attach(zone->db, &db);
dns_db_currentversion(db, &oldver);
CHECK(dns_db_newversion(db, &newver));
@@ -12795,9 +12969,7 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) {
}
static isc_result_t
-zone_send_secureserial(dns_zone_t *zone, isc_boolean_t locked,
- isc_uint32_t serial)
-{
+zone_send_secureserial(dns_zone_t *zone, isc_uint32_t serial) {
isc_event_t *e;
dns_zone_t *dummy = NULL;
@@ -12808,10 +12980,8 @@ zone_send_secureserial(dns_zone_t *zone, isc_boolean_t locked,
if (e == NULL)
return (ISC_R_NOMEMORY);
((struct secure_event *)e)->serial = serial;
- if (locked)
- zone_iattach(zone->secure, &dummy);
- else
- dns_zone_iattach(zone->secure, &dummy);
+ INSIST(LOCKED_ZONE(zone->secure));
+ zone_iattach(zone->secure, &dummy);
isc_task_send(zone->secure->task, &e);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
@@ -12869,6 +13039,203 @@ checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
0, NULL));
}
+/*
+ * This function should populate an nsec3paramlist_t with the
+ * nsecparam_t data from a zone.
+ */
+static isc_result_t
+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;
+ nsec3param_t *next;
+ dns_db_t *db = NULL;
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(nsec3list != NULL);
+ REQUIRE(ISC_LIST_EMPTY(*nsec3list));
+
+ 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,
+ dns_rdatatype_none, 0, &rdataset, NULL);
+
+ if (result != ISC_R_SUCCESS)
+ goto getprivate;
+
+ /*
+ * walk nsec3param rdataset making a list of parameters (note that
+ * multiple simultaneous nsec3 chains are annoyingly legal -- this
+ * is why we use an nsec3list, even tho we will usually only have
+ * one)
+ */
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ dns_rdata_init(&rdata_in);
+ dns_rdataset_current(&rdataset, &rdata_in);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
+ "looping through nsec3param data");
+ nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
+ if (nsec3param == NULL)
+ CHECK(ISC_R_NOMEMORY);
+ ISC_LINK_INIT(nsec3param, link);
+
+ /*
+ * now transfer the data from the rdata to
+ * the nsec3param
+ */
+ dns_rdata_init(&prdata_out);
+ dns_nsec3param_toprivate(&rdata_in, &prdata_out,
+ zone->privatetype, nsec3param->data,
+ sizeof(nsec3param->data));
+ nsec3param->length = prdata_out.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)
+ goto done;
+
+ /*
+ * walk private type records, converting them to nsec3 parameters
+ * using dns_nsec3param_fromprivate(), do the right thing based on
+ * CREATE and REMOVE flags
+ */
+ for (result = dns_rdataset_first(&prdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&prdataset))
+ {
+ dns_rdata_init(&prdata_in);
+ dns_rdataset_current(&prdataset, &prdata_in);
+ 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,
+ buf, sizeof(buf)))
+ continue;
+
+ if ((prdata_out.data[1] & DNS_NSEC3FLAG_REMOVE) !=0) {
+ prdata_out.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) {
+ ISC_LIST_UNLINK(*nsec3list,
+ nsec3p, link);
+ isc_mem_put(zone->mctx, nsec3p,
+ sizeof(nsec3param_t));
+ }
+ }
+ continue;
+ }
+
+ nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
+ if (nsec3param == NULL)
+ 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;
+ ISC_LIST_APPEND(*nsec3list, nsec3param, link);
+ }
+
+ done:
+ if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (version != NULL)
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (dns_rdataset_isassociated(&prdataset))
+ dns_rdataset_disassociate(&prdataset);
+ return (result);
+}
+
+/*
+ * Walk the list of the nsec3 chains desired for the zone, converting
+ * parameters to private type records using dns_nsec3param_toprivate(),
+ * and insert them into the new zone db.
+ */
+static isc_result_t
+restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
+ nsec3paramlist_t *nsec3list)
+{
+ isc_result_t result;
+ dns_diff_t diff;
+ dns_rdata_t rdata;
+ nsec3param_t *nsec3p = NULL;
+ nsec3param_t *next;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
+
+ dns_diff_init(zone->mctx, &diff);
+
+ /*
+ * Loop through the list of private-type records, set the INITIAL
+ * and CREATE flags, and the add the record to the apex of the tree
+ * in db.
+ */
+ for (nsec3p = ISC_LIST_HEAD(*nsec3list);
+ nsec3p != NULL;
+ nsec3p = next)
+ {
+ next = ISC_LIST_NEXT(nsec3p, link);
+ dns_rdata_init(&rdata);
+ nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
+ rdata.length = nsec3p->length;
+ rdata.data = nsec3p->data;
+ rdata.type = zone->privatetype;
+ rdata.rdclass = zone->rdclass;
+ CHECK(update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
+ &zone->origin, 0, &rdata));
+ }
+
+ result = ISC_R_SUCCESS;
+
+failure:
+ for (nsec3p = ISC_LIST_HEAD(*nsec3list);
+ nsec3p != NULL;
+ nsec3p = next)
+ {
+ next = ISC_LIST_NEXT(nsec3p, link);
+ ISC_LIST_UNLINK(*nsec3list, nsec3p, link);
+ isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
+ }
+
+ dns_diff_clear(&diff);
+ return (result);
+}
+
static void
receive_secure_db(isc_task_t *task, isc_event_t *event) {
isc_result_t result;
@@ -12884,25 +13251,44 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) {
isc_time_t loadtime;
unsigned int oldserial = 0;
isc_boolean_t have_oldserial = ISC_FALSE;
+ nsec3paramlist_t nsec3list;
UNUSED(task);
+ ISC_LIST_INIT(nsec3list);
+
zone = event->ev_arg;
rawdb = ((struct secure_event *)event)->db;
isc_event_free(&event);
- REQUIRE(inline_secure(zone));
-
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
dns_rdataset_init(&rdataset);
+ LOCK_ZONE(zone);
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
+ result = ISC_R_SHUTTINGDOWN;
+ goto failure;
+ }
+
TIME_NOW(&loadtime);
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
if (zone->db != NULL) {
result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
if (result == ISC_R_SUCCESS)
have_oldserial = ISC_TRUE;
+
+ /*
+ * assemble nsec3parameters from the old zone, and set a flag
+ * if any are found
+ */
+ result = save_nsec3param(zone, &nsec3list);
+ if (result != ISC_R_SUCCESS) {
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ goto failure;
+ }
}
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
result = dns_db_create(zone->mctx, zone->db_argv[0],
&zone->origin, dns_dbtype_zone, zone->rdclass,
@@ -12963,21 +13349,27 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) {
dns_db_detachnode(db, &node);
}
+ /*
+ * Call restore_nsec3param() to create private-type records from
+ * the old nsec3 parameters and insert them into db
+ */
+ if (!ISC_LIST_EMPTY(nsec3list))
+ restore_nsec3param(zone, db, version, &nsec3list);
+
dns_db_closeversion(db, &version, ISC_TRUE);
+
/*
* Lock hierarchy: zmgr, zone, raw.
*/
- LOCK_ZONE(zone);
- if (inline_secure(zone))
- LOCK_ZONE(zone->raw);
+ INSIST(zone != zone->raw);
+ LOCK_ZONE(zone->raw);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
zone_needdump(zone, 0); /* XXXMPA */
- if (inline_secure(zone))
- UNLOCK_ZONE(zone->raw);
- UNLOCK_ZONE(zone);
+ UNLOCK_ZONE(zone->raw);
failure:
+ UNLOCK_ZONE(zone);
if (result != ISC_R_SUCCESS)
dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
dns_result_totext(result));
@@ -12998,7 +13390,7 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) {
}
static isc_result_t
-zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked, dns_db_t *db) {
+zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
isc_event_t *e;
dns_db_t *dummy = NULL;
dns_zone_t *secure = NULL;
@@ -13011,11 +13403,8 @@ zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked, dns_db_t *db) {
return (ISC_R_NOMEMORY);
dns_db_attach(db, &dummy);
((struct secure_event *)e)->db = dummy;
- if (locked)
- zone_iattach(zone->secure, &secure);
- else
- dns_zone_iattach(zone->secure, &secure);
-
+ INSIST(LOCKED_ZONE(zone->secure));
+ zone_iattach(zone->secure, &secure);
isc_task_send(zone->secure->task, &e);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
return (ISC_R_SUCCESS);
@@ -13024,12 +13413,29 @@ zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked, dns_db_t *db) {
isc_result_t
dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
isc_result_t result;
+ dns_zone_t *secure = NULL;
REQUIRE(DNS_ZONE_VALID(zone));
+ again:
LOCK_ZONE(zone);
+ if (inline_raw(zone)) {
+ secure = zone->secure;
+ INSIST(secure != zone);
+ TRYLOCK_ZONE(result, secure);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK_ZONE(zone);
+ secure = NULL;
+#if ISC_PLATFORM_USETHREADS
+ isc_thread_yield();
+#endif
+ goto again;
+ }
+ }
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
result = zone_replacedb(zone, db, dump);
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
+ if (secure != NULL)
+ UNLOCK_ZONE(secure);
UNLOCK_ZONE(zone);
return (result);
}
@@ -13046,6 +13452,8 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
*/
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(LOCKED_ZONE(zone));
+ if (inline_raw(zone))
+ REQUIRE(LOCKED_ZONE(zone->secure));
result = zone_get_from_db(zone, db, &nscount, &soacount,
NULL, NULL, NULL, NULL, NULL, NULL);
@@ -13145,7 +13553,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
}
}
if (zone->type == dns_zone_master && inline_raw(zone))
- zone_send_secureserial(zone, ISC_FALSE, serial);
+ zone_send_secureserial(zone, serial);
} else {
if (dump && zone->masterfile != NULL) {
/*
@@ -13198,7 +13606,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
}
if (inline_raw(zone))
- zone_send_securedb(zone, ISC_FALSE, db);
+ zone_send_securedb(zone, db);
}
dns_db_closeversion(db, &ver, ISC_FALSE);
@@ -13253,13 +13661,34 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
isc_uint32_t serial, refresh, retry, expire, minimum;
isc_result_t xfrresult = result;
isc_boolean_t free_needed;
+ dns_zone_t *secure = NULL;
REQUIRE(DNS_ZONE_VALID(zone));
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"zone transfer finished: %s", dns_result_totext(result));
+ /*
+ * Obtaining a lock on the zone->secure (see zone_send_secureserial)
+ * could result in a deadlock due to a LOR so we will spin if we
+ * can't obtain the both locks.
+ */
+ again:
LOCK_ZONE(zone);
+ if (inline_raw(zone)) {
+ secure = zone->secure;
+ INSIST(secure != zone);
+ TRYLOCK_ZONE(result, secure);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK_ZONE(zone);
+ secure = NULL;
+#if ISC_PLATFORM_USETHREADS
+ isc_thread_yield();
+#endif
+ goto again;
+ }
+ }
+
INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
@@ -13349,7 +13778,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
"transferred serial %u%s",
serial, buf);
if (inline_raw(zone))
- zone_send_secureserial(zone, ISC_FALSE, serial);
+ zone_send_secureserial(zone, serial);
}
/*
@@ -13461,17 +13890,22 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
}
+ if (secure != NULL)
+ UNLOCK_ZONE(secure);
/*
* This transfer finishing freed up a transfer quota slot.
* Let any other zones waiting for quota have it.
*/
- UNLOCK_ZONE(zone);
- RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
- ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
- zone->statelist = NULL;
- zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
- RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
- LOCK_ZONE(zone);
+ if (zone->zmgr != NULL &&
+ zone->statelist == &zone->zmgr->xfrin_in_progress) {
+ UNLOCK_ZONE(zone);
+ RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
+ ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
+ zone->statelist = NULL;
+ zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
+ RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
+ LOCK_ZONE(zone);
+ }
/*
* Retry with a different server if necessary.
@@ -13493,6 +13927,7 @@ zone_loaddone(void *arg, isc_result_t result) {
dns_load_t *load = arg;
dns_zone_t *zone;
isc_result_t tresult;
+ dns_zone_t *secure = NULL;
REQUIRE(DNS_LOAD_VALID(load));
zone = load->zone;
@@ -13507,9 +13942,22 @@ zone_loaddone(void *arg, isc_result_t result) {
/*
* Lock hierarchy: zmgr, zone, raw.
*/
+ again:
LOCK_ZONE(zone);
if (inline_secure(zone))
LOCK_ZONE(zone->raw);
+ else if (inline_raw(zone)) {
+ secure = zone->secure;
+ TRYLOCK_ZONE(result, secure);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK_ZONE(zone);
+ secure = NULL;
+#if ISC_PLATFORM_USETHREADS
+ isc_thread_yield();
+#endif
+ goto again;
+ }
+ }
(void)zone_postload(zone, load->db, load->loadtime, result);
zonemgr_putio(&zone->readio);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
@@ -13523,6 +13971,8 @@ zone_loaddone(void *arg, isc_result_t result) {
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
if (inline_secure(zone))
UNLOCK_ZONE(zone->raw);
+ else if (secure != NULL)
+ UNLOCK_ZONE(secure);
UNLOCK_ZONE(zone);
load->magic = 0;
@@ -13573,9 +14023,18 @@ dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
void
dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
+ isc_time_t now;
+
REQUIRE(DNS_ZONE_VALID(zone));
+ LOCK_ZONE(zone);
zone->sigresigninginterval = interval;
+ set_resigntime(zone);
+ if (zone->task != NULL) {
+ TIME_NOW(&now);
+ zone_settimer(zone, &now);
+ }
+ UNLOCK_ZONE(zone);
}
isc_uint32_t
@@ -13632,6 +14091,7 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
isc_sockaddr_t masteraddr;
isc_time_t now;
const char *soa_before = "";
+ isc_boolean_t loaded;
UNUSED(task);
@@ -13665,7 +14125,11 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
/*
* Decide whether we should request IXFR or AXFR.
*/
- if (zone->db == NULL) {
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ loaded = ISC_TF(zone->db != NULL);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ if (!loaded) {
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"no database exists yet, requesting AXFR of "
"initial version from %s", master);
@@ -13885,8 +14349,18 @@ forward_callback(isc_task_t *task, isc_event_t *event) {
case dns_rcode_yxrrset:
case dns_rcode_nxrrset:
case dns_rcode_refused:
- case dns_rcode_nxdomain:
+ case dns_rcode_nxdomain: {
+ char rcode[128];
+ isc_buffer_t rb;
+
+ isc_buffer_init(&rb, rcode, sizeof(rcode));
+ (void)dns_rcode_totext(msg->rcode, &rb);
+ dns_zone_log(zone, ISC_LOG_INFO,
+ "forwarded dynamic update: "
+ "master %s returned: %.*s",
+ master, (int)rb.used, rcode);
break;
+ }
/* These should not occur if the masters/zone are valid. */
case dns_rcode_notzone:
@@ -14036,7 +14510,8 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
zmgr->loadtasks = NULL;
zmgr->mctxpool = NULL;
zmgr->task = NULL;
- zmgr->rl = NULL;
+ zmgr->notifyrl = NULL;
+ zmgr->refreshrl = NULL;
ISC_LIST_INIT(zmgr->zones);
ISC_LIST_INIT(zmgr->waiting_for_xfrin);
ISC_LIST_INIT(zmgr->xfrin_in_progress);
@@ -14060,15 +14535,24 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_task_setname(zmgr->task, "zmgr", zmgr);
result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
- &zmgr->rl);
+ &zmgr->notifyrl);
if (result != ISC_R_SUCCESS)
goto free_task;
+ result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
+ &zmgr->refreshrl);
+ if (result != ISC_R_SUCCESS)
+ goto free_notifyrl;
+
/* default to 20 refresh queries / notifies per second. */
isc_interval_set(&interval, 0, 1000000000/2);
- result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
+ result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
- isc_ratelimiter_setpertic(zmgr->rl, 10);
+ isc_ratelimiter_setpertic(zmgr->notifyrl, 10);
+
+ result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_ratelimiter_setpertic(zmgr->refreshrl, 10);
zmgr->iolimit = 1;
zmgr->ioactive = 0;
@@ -14077,7 +14561,7 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
result = isc_mutex_init(&zmgr->iolock);
if (result != ISC_R_SUCCESS)
- goto free_rl;
+ goto free_refreshrl;
zmgr->magic = ZONEMGR_MAGIC;
@@ -14088,8 +14572,10 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
free_iolock:
DESTROYLOCK(&zmgr->iolock);
#endif
- free_rl:
- isc_ratelimiter_detach(&zmgr->rl);
+ free_refreshrl:
+ isc_ratelimiter_detach(&zmgr->refreshrl);
+ free_notifyrl:
+ isc_ratelimiter_detach(&zmgr->notifyrl);
free_task:
isc_task_detach(&zmgr->task);
free_urlock:
@@ -14287,7 +14773,8 @@ dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
- isc_ratelimiter_shutdown(zmgr->rl);
+ isc_ratelimiter_shutdown(zmgr->notifyrl);
+ isc_ratelimiter_shutdown(zmgr->refreshrl);
if (zmgr->task != NULL)
isc_task_destroy(&zmgr->task);
@@ -14419,7 +14906,8 @@ zonemgr_free(dns_zonemgr_t *zmgr) {
zmgr->magic = 0;
DESTROYLOCK(&zmgr->iolock);
- isc_ratelimiter_detach(&zmgr->rl);
+ isc_ratelimiter_detach(&zmgr->notifyrl);
+ isc_ratelimiter_detach(&zmgr->refreshrl);
isc_rwlock_destroy(&zmgr->urlock);
isc_rwlock_destroy(&zmgr->rwlock);
@@ -14809,9 +15297,14 @@ dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
}
isc_interval_set(&interval, s, ns);
- result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
+
+ result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
- isc_ratelimiter_setpertic(zmgr->rl, pertic);
+ isc_ratelimiter_setpertic(zmgr->notifyrl, pertic);
+
+ result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_ratelimiter_setpertic(zmgr->refreshrl, pertic);
zmgr->serialqueryrate = value;
}
@@ -14831,6 +15324,7 @@ dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
isc_rwlocktype_t locktype;
isc_result_t result;
isc_uint32_t seconds = isc_time_seconds(now);
+ isc_uint32_t count = 0;
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
@@ -14844,12 +15338,13 @@ dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
if (result == ISC_R_SUCCESS) {
locktype = isc_rwlocktype_write;
zmgr->unreachable[i].last = seconds;
+ count = zmgr->unreachable[i].count;
}
break;
}
}
RWUNLOCK(&zmgr->urlock, locktype);
- return (ISC_TF(i < UNREACH_CHACHE_SIZE));
+ return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
}
void
@@ -14923,6 +15418,10 @@ dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
*/
zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
zmgr->unreachable[i].last = seconds;
+ if (zmgr->unreachable[i].expire < seconds)
+ zmgr->unreachable[i].count = 1;
+ else
+ zmgr->unreachable[i].count++;
} else if (slot != UNREACH_CHACHE_SIZE) {
/*
* Found a empty slot. Add a new entry to the cache.
@@ -14931,6 +15430,7 @@ dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
zmgr->unreachable[slot].last = seconds;
zmgr->unreachable[slot].remote = *remote;
zmgr->unreachable[slot].local = *local;
+ zmgr->unreachable[slot].count = 1;
} else {
/*
* Replace the least recently used entry in the cache.
@@ -14939,6 +15439,7 @@ dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
zmgr->unreachable[oldest].last = seconds;
zmgr->unreachable[oldest].remote = *remote;
zmgr->unreachable[oldest].local = *local;
+ zmgr->unreachable[oldest].count = 1;
}
RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
}
@@ -15358,6 +15859,7 @@ zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
dns_signing_t *current;
isc_result_t result = ISC_R_SUCCESS;
isc_time_t now;
+ dns_db_t *db = NULL;
signing = isc_mem_get(zone->mctx, sizeof *signing);
if (signing == NULL)
@@ -15373,10 +15875,22 @@ zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
TIME_NOW(&now);
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL)
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ if (db == NULL) {
+ result = ISC_R_NOTFOUND;
+ goto cleanup;
+ }
+
+ dns_db_attach(db, &signing->db);
+
for (current = ISC_LIST_HEAD(zone->signing);
current != NULL;
current = ISC_LIST_NEXT(current, link)) {
- if (current->db == zone->db &&
+ if (current->db == signing->db &&
current->algorithm == signing->algorithm &&
current->keyid == signing->keyid) {
if (current->delete != signing->delete)
@@ -15386,25 +15900,21 @@ zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
}
}
- if (zone->db != NULL) {
- dns_db_attach(zone->db, &signing->db);
- result = dns_db_createiterator(signing->db, 0,
- &signing->dbiterator);
+ result = dns_db_createiterator(signing->db, 0,
+ &signing->dbiterator);
- if (result == ISC_R_SUCCESS)
- result = dns_dbiterator_first(signing->dbiterator);
- if (result == ISC_R_SUCCESS) {
- dns_dbiterator_pause(signing->dbiterator);
- ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
- signing = NULL;
- if (isc_time_isepoch(&zone->signingtime)) {
- zone->signingtime = now;
- if (zone->task != NULL)
- zone_settimer(zone, &now);
- }
+ if (result == ISC_R_SUCCESS)
+ result = dns_dbiterator_first(signing->dbiterator);
+ if (result == ISC_R_SUCCESS) {
+ dns_dbiterator_pause(signing->dbiterator);
+ ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
+ signing = NULL;
+ if (isc_time_isepoch(&zone->signingtime)) {
+ zone->signingtime = now;
+ if (zone->task != NULL)
+ zone_settimer(zone, &now);
}
- } else
- result = ISC_R_NOTFOUND;
+ }
cleanup:
if (signing != NULL) {
@@ -15414,6 +15924,8 @@ zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
dns_dbiterator_destroy(&signing->dbiterator);
isc_mem_put(zone->mctx, signing, sizeof *signing);
}
+ if (db != NULL)
+ dns_db_detach(&db);
return (result);
}
@@ -15822,7 +16334,6 @@ zone_rekey(dns_zone_t *zone) {
mctx = zone->mctx;
dns_diff_init(mctx, &diff);
dns_diff_init(mctx, &_sig_diff);
- _sig_diff.resign = zone->sigresigninginterval;
zonediff_init(&zonediff, &_sig_diff);
CHECK(dns_zone_getdb(zone, &db));
@@ -16182,18 +16693,34 @@ dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
{
isc_time_t loadtime;
isc_result_t result;
+ dns_zone_t *secure = NULL;
TIME_NOW(&loadtime);
/*
* Lock hierarchy: zmgr, zone, raw.
*/
+ again:
LOCK_ZONE(zone);
if (inline_secure(zone))
LOCK_ZONE(zone->raw);
+ else if (inline_raw(zone)) {
+ secure = zone->secure;
+ TRYLOCK_ZONE(result, secure);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK_ZONE(zone);
+ secure = NULL;
+#if ISC_PLATFORM_USETHREADS
+ isc_thread_yield();
+#endif
+ goto again;
+ }
+ }
result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
if (inline_secure(zone))
UNLOCK_ZONE(zone->raw);
+ else if (secure != NULL)
+ UNLOCK_ZONE(secure);
UNLOCK_ZONE(zone);
return result;
}
@@ -16504,14 +17031,6 @@ dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
return (result);
}
-struct nsec3param {
- isc_event_t event;
- unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
- unsigned int length;
- isc_boolean_t nsec;
- isc_boolean_t replace;
-};
-
static void
setnsec3param(isc_task_t *task, isc_event_t *event) {
const char *me = "setnsec3param";
@@ -16523,7 +17042,8 @@ setnsec3param(isc_task_t *task, isc_event_t *event) {
dns_dbnode_t *node = NULL;
dns_rdataset_t prdataset, nrdataset;
dns_diff_t diff;
- struct nsec3param *np = (struct nsec3param *)event;
+ struct np3event *npe = (struct np3event *)event;
+ nsec3param_t *np;
dns_update_log_t log = { update_log_cb, NULL };
dns_rdata_t rdata;
isc_boolean_t nseconly;
@@ -16536,6 +17056,8 @@ setnsec3param(isc_task_t *task, isc_event_t *event) {
ENTER;
+ np = &npe->params;
+
dns_rdataset_init(&prdataset);
dns_rdataset_init(&nrdataset);
dns_diff_init(zone->mctx, &diff);
@@ -16687,7 +17209,8 @@ dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
dns_rdata_t nrdata = DNS_RDATA_INIT;
dns_rdata_t prdata = DNS_RDATA_INIT;
unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
- struct nsec3param *np;
+ struct np3event *npe;
+ nsec3param_t *np;
dns_zone_t *dummy = NULL;
isc_buffer_t b;
isc_event_t *e;
@@ -16698,13 +17221,15 @@ dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
LOCK_ZONE(zone);
e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
- setnsec3param, zone, sizeof(struct nsec3param));
+ setnsec3param, zone, sizeof(struct np3event));
if (e == NULL) {
result = ISC_R_NOMEMORY;
goto failure;
}
- np = (struct nsec3param *) e;
+ npe = (struct np3event *) e;
+ np = &npe->params;
+
np->replace = replace;
if (hash == 0) {
np->length = 0;