summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bind/lib/dns/diff.c
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>2019-12-16 16:16:22 +0000
committerderaadt <deraadt@openbsd.org>2019-12-16 16:16:22 +0000
commit2fc5abb04c862f358e234358caea4444e15db068 (patch)
tree1c77d5b577fef0399be14245b2108ca9c1a8819d /usr.sbin/bind/lib/dns/diff.c
parentNeed to include message size in the maximum buffer calculation. (diff)
downloadwireguard-openbsd-2fc5abb04c862f358e234358caea4444e15db068.tar.xz
wireguard-openbsd-2fc5abb04c862f358e234358caea4444e15db068.zip
Update to bind-9.10.5-P3, which appears to have been the last ISC version.
We only use this tree to build dig and nslookup. Our previous version predated edns0 support in those tools, and we want that. This is the worst code I've looked at in years, with layers and layers of spaghetti abstraction clearly unfit for reuse, but then reused anyways, and the old ones remain behind. So this is a 8MB diff. florian, sthen, and otto tried this merge before but failed.
Diffstat (limited to 'usr.sbin/bind/lib/dns/diff.c')
-rw-r--r--usr.sbin/bind/lib/dns/diff.c163
1 files changed, 127 insertions, 36 deletions
diff --git a/usr.sbin/bind/lib/dns/diff.c b/usr.sbin/bind/lib/dns/diff.c
index 13982902d34..3c681479563 100644
--- a/usr.sbin/bind/lib/dns/diff.c
+++ b/usr.sbin/bind/lib/dns/diff.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009, 2011, 2013-2015 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $ISC: diff.c,v 1.9.18.3 2005/04/27 05:01:15 sra Exp $ */
+/* $Id: diff.c,v 1.2 2019/12/16 16:16:24 deraadt Exp $ */
/*! \file */
@@ -26,6 +26,7 @@
#include <isc/buffer.h>
#include <isc/file.h>
#include <isc/mem.h>
+#include <isc/print.h>
#include <isc/string.h>
#include <isc/util.h>
@@ -35,6 +36,7 @@
#include <dns/rdataclass.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
#include <dns/rdatatype.h>
#include <dns/result.h>
@@ -72,12 +74,13 @@ dns_difftuple_create(isc_mem_t *mctx,
t = isc_mem_allocate(mctx, size);
if (t == NULL)
return (ISC_R_NOMEMORY);
- t->mctx = mctx;
+ t->mctx = NULL;
+ isc_mem_attach(mctx, &t->mctx);
t->op = op;
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;
@@ -85,7 +88,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;
@@ -104,10 +107,15 @@ dns_difftuple_create(isc_mem_t *mctx,
void
dns_difftuple_free(dns_difftuple_t **tp) {
dns_difftuple_t *t = *tp;
+ isc_mem_t *mctx;
+
REQUIRE(DNS_DIFFTUPLE_VALID(t));
+
dns_name_invalidate(&t->name);
t->magic = 0;
- isc_mem_free(t->mctx, t);
+ mctx = t->mctx;
+ isc_mem_free(mctx, t);
+ isc_mem_detach(&mctx);
*tp = NULL;
}
@@ -192,6 +200,40 @@ dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuplep)
ENSURE(*tuplep == NULL);
}
+static isc_stdtime_t
+setresign(dns_rdataset_t *modified) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t sig;
+ isc_stdtime_t when;
+ isc_result_t result;
+
+ result = dns_rdataset_first(modified);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdataset_current(modified, &rdata);
+ (void)dns_rdata_tostruct(&rdata, &sig, NULL);
+ if ((rdata.flags & DNS_RDATA_OFFLINE) != 0)
+ when = 0;
+ else
+ when = sig.timeexpire;
+ dns_rdata_reset(&rdata);
+
+ result = dns_rdataset_next(modified);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(modified, &rdata);
+ (void)dns_rdata_tostruct(&rdata, &sig, NULL);
+ if ((rdata.flags & DNS_RDATA_OFFLINE) != 0) {
+ goto next_rr;
+ }
+ if (when == 0 || sig.timeexpire < when)
+ when = sig.timeexpire;
+ next_rr:
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(modified);
+ }
+ INSIST(result == ISC_R_NOMORE);
+ return (when);
+}
+
static isc_result_t
diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
isc_boolean_t warn)
@@ -220,14 +262,14 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
* but such diffs should never be created in the first
* place.
*/
- node = NULL;
- CHECK(dns_db_findnode(db, name, ISC_TRUE, &node));
while (t != NULL && dns_name_equal(&t->name, name)) {
dns_rdatatype_t type, covers;
dns_diffop_t op;
dns_rdatalist_t rdl;
dns_rdataset_t rds;
+ dns_rdataset_t ardataset;
+ dns_rdataset_t *modified = NULL;
op = t->op;
type = t->rdata.type;
@@ -248,12 +290,20 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
* of the diff itself is not affected.
*/
+ dns_rdatalist_init(&rdl);
rdl.type = type;
rdl.covers = covers;
rdl.rdclass = t->rdata.rdclass;
rdl.ttl = t->ttl;
- ISC_LIST_INIT(rdl.rdata);
- ISC_LINK_INIT(&rdl, link);
+
+ node = NULL;
+ if (type != dns_rdatatype_nsec3 &&
+ covers != dns_rdatatype_nsec3)
+ CHECK(dns_db_findnode(db, name, ISC_TRUE,
+ &node));
+ else
+ CHECK(dns_db_findnsec3node(db, name, ISC_TRUE,
+ &node));
while (t != NULL &&
dns_name_equal(&t->name, name) &&
@@ -269,7 +319,7 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
sizeof(classbuf));
if (t->ttl != rdl.ttl && warn)
isc_log_write(DIFF_COMMON_LOGARGS,
- ISC_LOG_WARNING,
+ ISC_LOG_WARNING,
"'%s/%s/%s': TTL differs in "
"rdataset, adjusting "
"%lu -> %lu",
@@ -285,28 +335,51 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
*/
dns_rdataset_init(&rds);
CHECK(dns_rdatalist_tordataset(&rdl, &rds));
+ if (rds.type == dns_rdatatype_rrsig)
+ switch (op) {
+ case DNS_DIFFOP_ADDRESIGN:
+ case DNS_DIFFOP_DELRESIGN:
+ modified = &ardataset;
+ dns_rdataset_init(modified);
+ break;
+ default:
+ break;
+ }
rds.trust = dns_trust_ultimate;
/*
* Merge the rdataset into the database.
*/
- if (op == DNS_DIFFOP_ADD) {
+ switch (op) {
+ case DNS_DIFFOP_ADD:
+ case DNS_DIFFOP_ADDRESIGN:
result = dns_db_addrdataset(db, node, ver,
0, &rds,
DNS_DBADD_MERGE|
DNS_DBADD_EXACT|
DNS_DBADD_EXACTTTL,
- NULL);
- } else if (op == DNS_DIFFOP_DEL) {
+ modified);
+ break;
+ case DNS_DIFFOP_DEL:
+ case DNS_DIFFOP_DELRESIGN:
result = dns_db_subtractrdataset(db, node, ver,
&rds,
DNS_DBSUB_EXACT,
- NULL);
- } else {
+ modified);
+ break;
+ default:
INSIST(0);
}
- if (result == DNS_R_UNCHANGED) {
- /*
+
+ if (result == ISC_R_SUCCESS) {
+ if (modified != NULL) {
+ isc_stdtime_t resign;
+ resign = setresign(modified);
+ dns_db_setsigningtime(db, modified,
+ resign);
+ }
+ } else if (result == DNS_R_UNCHANGED) {
+ /*
* This will not happen when executing a
* dynamic update, because that code will
* generate strictly minimal diffs.
@@ -314,20 +387,34 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
* from a server that is not as careful.
* Issue a warning and continue.
*/
- if (warn)
+ if (warn) {
+ dns_name_format(dns_db_origin(db),
+ namebuf,
+ sizeof(namebuf));
+ dns_rdataclass_format(dns_db_class(db),
+ classbuf,
+ sizeof(classbuf));
isc_log_write(DIFF_COMMON_LOGARGS,
ISC_LOG_WARNING,
- "update with no effect");
- } else if (result == ISC_R_SUCCESS ||
- result == DNS_R_NXRRSET) {
+ "%s/%s: dns_diff_apply: "
+ "update with no effect",
+ namebuf, classbuf);
+ }
+ } else if (result == DNS_R_NXRRSET) {
/*
* OK.
*/
} else {
+ if (modified != NULL &&
+ dns_rdataset_isassociated(modified))
+ dns_rdataset_disassociate(modified);
CHECK(result);
}
+ dns_db_detachnode(db, &node);
+ if (modified != NULL &&
+ dns_rdataset_isassociated(modified))
+ dns_rdataset_disassociate(modified);
}
- dns_db_detachnode(db, &node);
}
return (ISC_R_SUCCESS);
@@ -373,12 +460,11 @@ dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
type = t->rdata.type;
covers = rdata_covers(&t->rdata);
+ dns_rdatalist_init(&rdl);
rdl.type = type;
rdl.covers = covers;
rdl.rdclass = t->rdata.rdclass;
rdl.ttl = t->ttl;
- ISC_LIST_INIT(rdl.rdata);
- ISC_LINK_INIT(&rdl, link);
while (t != NULL && dns_name_equal(&t->name, name) &&
t->op == op && t->rdata.type == type &&
@@ -400,6 +486,7 @@ dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
if (result == DNS_R_UNCHANGED) {
isc_log_write(DIFF_COMMON_LOGARGS,
ISC_LOG_WARNING,
+ "dns_diff_load: "
"update with no effect");
} else if (result == ISC_R_SUCCESS ||
result == DNS_R_NXRRSET) {
@@ -437,7 +524,6 @@ dns_diff_sort(dns_diff_t *diff, dns_diff_compare_func *compare) {
v = isc_mem_get(diff->mctx, length * sizeof(dns_difftuple_t *));
if (v == NULL)
return (ISC_R_NOMEMORY);
- i = 0;
for (i = 0; i < length; i++) {
p = ISC_LIST_HEAD(diff->tuples);
v[i] = p;
@@ -455,7 +541,7 @@ dns_diff_sort(dns_diff_t *diff, dns_diff_compare_func *compare) {
/*
* Create an rdataset containing the single RR of the given
- * tuple. The caller must allocate the the rdata, rdataset and
+ * tuple. The caller must allocate the rdata, rdataset and
* an rdatalist structure for it to refer to.
*/
@@ -467,11 +553,10 @@ diff_tuple_tordataset(dns_difftuple_t *t, dns_rdata_t *rdata,
REQUIRE(rdl != NULL);
REQUIRE(rds != NULL);
+ dns_rdatalist_init(rdl);
rdl->type = t->rdata.type;
rdl->rdclass = t->rdata.rdclass;
rdl->ttl = t->ttl;
- ISC_LIST_INIT(rdl->rdata);
- ISC_LINK_INIT(rdl, link);
dns_rdataset_init(rds);
ISC_LINK_INIT(rdata, link);
dns_rdata_clone(&t->rdata, rdata);
@@ -485,6 +570,7 @@ dns_diff_print(dns_diff_t *diff, FILE *file) {
dns_difftuple_t *t;
char *mem = NULL;
unsigned int size = 2048;
+ const char *op = NULL;
REQUIRE(DNS_DIFF_VALID(diff));
@@ -536,15 +622,20 @@ dns_diff_print(dns_diff_t *diff, FILE *file) {
buf.used--;
isc_buffer_usedregion(&buf, &r);
+ switch (t->op) {
+ case DNS_DIFFOP_EXISTS: op = "exists"; break;
+ case DNS_DIFFOP_ADD: op = "add"; break;
+ case DNS_DIFFOP_DEL: op = "del"; break;
+ case DNS_DIFFOP_ADDRESIGN: op = "add re-sign"; break;
+ case DNS_DIFFOP_DELRESIGN: op = "del re-sign"; break;
+ }
if (file != NULL)
- fprintf(file, "%s %.*s\n",
- t->op == DNS_DIFFOP_ADD ? "add" : "del",
- (int) r.length, (char *) r.base);
+ fprintf(file, "%s %.*s\n", op, (int) r.length,
+ (char *) r.base);
else
isc_log_write(DIFF_COMMON_LOGARGS, ISC_LOG_DEBUG(7),
- "%s %.*s",
- t->op == DNS_DIFFOP_ADD ? "add" : "del",
- (int) r.length, (char *) r.base);
+ "%s %.*s", op, (int) r.length,
+ (char *) r.base);
}
result = ISC_R_SUCCESS;
cleanup: