mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-03 16:15:27 +00:00
Split journal.[ch] into journal.[ch] and diff.[ch]
This commit is contained in:
@@ -17,7 +17,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: dnssec-signzone.c,v 1.117 2000/12/07 23:00:59 bwelling Exp $ */
|
/* $Id: dnssec-signzone.c,v 1.118 2000/12/09 02:17:01 bwelling Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include <dns/db.h>
|
#include <dns/db.h>
|
||||||
#include <dns/dbiterator.h>
|
#include <dns/dbiterator.h>
|
||||||
|
#include <dns/diff.h>
|
||||||
#include <dns/dnssec.h>
|
#include <dns/dnssec.h>
|
||||||
#include <dns/fixedname.h>
|
#include <dns/fixedname.h>
|
||||||
#include <dns/journal.h>
|
#include <dns/journal.h>
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: update.c,v 1.76 2000/12/05 22:48:56 gson Exp $ */
|
/* $Id: update.c,v 1.77 2000/12/09 02:17:03 bwelling Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <dns/db.h>
|
#include <dns/db.h>
|
||||||
#include <dns/dbiterator.h>
|
#include <dns/dbiterator.h>
|
||||||
|
#include <dns/diff.h>
|
||||||
#include <dns/dnssec.h>
|
#include <dns/dnssec.h>
|
||||||
#include <dns/events.h>
|
#include <dns/events.h>
|
||||||
#include <dns/fixedname.h>
|
#include <dns/fixedname.h>
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||||
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
# $Id: Makefile.in,v 1.116 2000/12/04 23:21:40 bwelling Exp $
|
# $Id: Makefile.in,v 1.117 2000/12/09 02:17:04 bwelling Exp $
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
@@ -95,9 +95,10 @@ OPENSSLOBJS = sec/openssl/a_bitstr.@O@ sec/openssl/a_bytes.@O@ \
|
|||||||
# Alphabetically
|
# Alphabetically
|
||||||
OBJS = a6.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
|
OBJS = a6.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
|
||||||
cache.@O@ callbacks.@O@ compress.@O@ \
|
cache.@O@ callbacks.@O@ compress.@O@ \
|
||||||
db.@O@ dbiterator.@O@ dbtable.@O@ dispatch.@O@ dnssec.@O@ \
|
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
|
||||||
forward.@O@ journal.@O@ keytable.@O@ lib.@O@ log.@O@ \
|
dnssec.@O@ forward.@O@ journal.@O@ keytable.@O@ \
|
||||||
lookup.@O@ master.@O@ masterdump.@O@ message.@O@ \
|
lib.@O@ log.@O@ lookup.@O@ \
|
||||||
|
master.@O@ masterdump.@O@ message.@O@ \
|
||||||
name.@O@ ncache.@O@ nxt.@O@ peer.@O@ \
|
name.@O@ ncache.@O@ nxt.@O@ peer.@O@ \
|
||||||
rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rdata.@O@ rdatalist.@O@ \
|
rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rdata.@O@ rdatalist.@O@ \
|
||||||
rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ request.@O@ \
|
rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ request.@O@ \
|
||||||
@@ -110,9 +111,10 @@ OBJS = a6.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
|
|||||||
# Alphabetically
|
# Alphabetically
|
||||||
SRCS = a6.c acl.c adb.c byaddr.c \
|
SRCS = a6.c acl.c adb.c byaddr.c \
|
||||||
cache.c callbacks.c compress.c \
|
cache.c callbacks.c compress.c \
|
||||||
db.c dbiterator.c dbtable.c dispatch.c dnssec.c \
|
db.c dbiterator.c dbtable.c diff.c dispatch.c \
|
||||||
forward.c journal.c keytable.c lib.c log.c \
|
dnssec.c forward.c journal.c keytable.c \
|
||||||
lookup.c master.c masterdump.c message.c \
|
lib.c log.c lookup.c \
|
||||||
|
master.c masterdump.c message.c \
|
||||||
name.c ncache.c nxt.c peer.c \
|
name.c ncache.c nxt.c peer.c \
|
||||||
rbt.c rbtdb.c rbtdb64.c rdata.c rdatalist.c \
|
rbt.c rbtdb.c rbtdb64.c rdata.c rdatalist.c \
|
||||||
rdataset.c rdatasetiter.c rdataslab.c request.c \
|
rdataset.c rdatasetiter.c rdataslab.c request.c \
|
||||||
|
535
lib/dns/diff.c
Normal file
535
lib/dns/diff.c
Normal file
@@ -0,0 +1,535 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2000 Internet Software Consortium.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and 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 INTERNET SOFTWARE CONSORTIUM
|
||||||
|
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||||
|
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||||
|
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* $Id: diff.c,v 1.1 2000/12/09 02:17:10 bwelling Exp $ */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <isc/file.h>
|
||||||
|
#include <isc/mem.h>
|
||||||
|
#include <isc/net.h> /* Required for ntohl. */
|
||||||
|
#include <isc/stdio.h>
|
||||||
|
#include <isc/string.h>
|
||||||
|
#include <isc/util.h>
|
||||||
|
|
||||||
|
#include <dns/compress.h>
|
||||||
|
#include <dns/db.h>
|
||||||
|
#include <dns/dbiterator.h>
|
||||||
|
#include <dns/diff.h>
|
||||||
|
#include <dns/fixedname.h>
|
||||||
|
#include <dns/log.h>
|
||||||
|
#include <dns/rdatalist.h>
|
||||||
|
#include <dns/rdataset.h>
|
||||||
|
#include <dns/rdatasetiter.h>
|
||||||
|
#include <dns/result.h>
|
||||||
|
|
||||||
|
#define CHECK(op) \
|
||||||
|
do { result = (op); \
|
||||||
|
if (result != ISC_R_SUCCESS) goto failure; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define DIFF_COMMON_LOGARGS \
|
||||||
|
dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_DIFF
|
||||||
|
|
||||||
|
static dns_rdatatype_t
|
||||||
|
rdata_covers(dns_rdata_t *rdata) {
|
||||||
|
return (rdata->type == dns_rdatatype_sig ?
|
||||||
|
dns_rdata_covers(rdata) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_difftuple_create(isc_mem_t *mctx,
|
||||||
|
dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
|
||||||
|
dns_rdata_t *rdata, dns_difftuple_t **tp)
|
||||||
|
{
|
||||||
|
dns_difftuple_t *t;
|
||||||
|
unsigned int size;
|
||||||
|
unsigned char *datap;
|
||||||
|
|
||||||
|
REQUIRE(tp != NULL && *tp == NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new tuple. The variable-size wire-format name data and
|
||||||
|
* rdata immediately follow the dns_difftuple_t structure
|
||||||
|
* in memory.
|
||||||
|
*/
|
||||||
|
size = sizeof(*t) + name->length + rdata->length;
|
||||||
|
t = isc_mem_allocate(mctx, size);
|
||||||
|
if (t == NULL)
|
||||||
|
return (ISC_R_NOMEMORY);
|
||||||
|
t->mctx = mctx;
|
||||||
|
t->op = op;
|
||||||
|
|
||||||
|
datap = (unsigned char *)(t + 1);
|
||||||
|
|
||||||
|
memcpy(datap, name->ndata, name->length);
|
||||||
|
dns_name_init(&t->name, NULL);
|
||||||
|
dns_name_clone(name, &t->name);
|
||||||
|
t->name.ndata = datap;
|
||||||
|
datap += name->length;
|
||||||
|
|
||||||
|
t->ttl = ttl;
|
||||||
|
|
||||||
|
memcpy(datap, rdata->data, rdata->length);
|
||||||
|
dns_rdata_init(&t->rdata);
|
||||||
|
dns_rdata_clone(rdata, &t->rdata);
|
||||||
|
t->rdata.data = datap;
|
||||||
|
datap += rdata->length;
|
||||||
|
|
||||||
|
ISC_LINK_INIT(&t->rdata, link);
|
||||||
|
ISC_LINK_INIT(t, link);
|
||||||
|
t->magic = DNS_DIFFTUPLE_MAGIC;
|
||||||
|
|
||||||
|
INSIST(datap == (unsigned char *)t + size);
|
||||||
|
|
||||||
|
*tp = t;
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_difftuple_free(dns_difftuple_t **tp) {
|
||||||
|
dns_difftuple_t *t = *tp;
|
||||||
|
REQUIRE(DNS_DIFFTUPLE_VALID(t));
|
||||||
|
dns_name_invalidate(&t->name);
|
||||||
|
t->magic = 0;
|
||||||
|
isc_mem_free(t->mctx, t);
|
||||||
|
*tp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_difftuple_copy(dns_difftuple_t *orig, dns_difftuple_t **copyp) {
|
||||||
|
return (dns_difftuple_create(orig->mctx, orig->op, &orig->name,
|
||||||
|
orig->ttl, &orig->rdata, copyp));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_diff_init(isc_mem_t *mctx, dns_diff_t *diff) {
|
||||||
|
diff->mctx = mctx;
|
||||||
|
ISC_LIST_INIT(diff->tuples);
|
||||||
|
diff->magic = DNS_DIFF_MAGIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_diff_clear(dns_diff_t *diff) {
|
||||||
|
dns_difftuple_t *t;
|
||||||
|
REQUIRE(DNS_DIFF_VALID(diff));
|
||||||
|
while ((t = ISC_LIST_HEAD(diff->tuples)) != NULL) {
|
||||||
|
ISC_LIST_UNLINK(diff->tuples, t, link);
|
||||||
|
dns_difftuple_free(&t);
|
||||||
|
}
|
||||||
|
ENSURE(ISC_LIST_EMPTY(diff->tuples));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_diff_append(dns_diff_t *diff, dns_difftuple_t **tuplep)
|
||||||
|
{
|
||||||
|
ISC_LIST_APPEND(diff->tuples, *tuplep, link);
|
||||||
|
*tuplep = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX this is O(N) */
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuplep)
|
||||||
|
{
|
||||||
|
dns_difftuple_t *ot, *next_ot;
|
||||||
|
|
||||||
|
REQUIRE(DNS_DIFF_VALID(diff));
|
||||||
|
REQUIRE(DNS_DIFFTUPLE_VALID(*tuplep));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for an existing tuple with the same owner name,
|
||||||
|
* rdata, and TTL. If we are doing an addition and find a
|
||||||
|
* deletion or vice versa, remove both the old and the
|
||||||
|
* new tuple since they cancel each other out (assuming
|
||||||
|
* that we never delete nonexistent data or add existing
|
||||||
|
* data).
|
||||||
|
*
|
||||||
|
* If we find an old update of the same kind as
|
||||||
|
* the one we are doing, there must be a programming
|
||||||
|
* error. We report it but try to continue anyway.
|
||||||
|
*/
|
||||||
|
for (ot = ISC_LIST_HEAD(diff->tuples); ot != NULL;
|
||||||
|
ot = next_ot)
|
||||||
|
{
|
||||||
|
next_ot = ISC_LIST_NEXT(ot, link);
|
||||||
|
if (dns_name_equal(&ot->name, &(*tuplep)->name) &&
|
||||||
|
dns_rdata_compare(&ot->rdata, &(*tuplep)->rdata) == 0 &&
|
||||||
|
ot->ttl == (*tuplep)->ttl)
|
||||||
|
{
|
||||||
|
ISC_LIST_UNLINK(diff->tuples, ot, link);
|
||||||
|
if ((*tuplep)->op == ot->op) {
|
||||||
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||||
|
"unexpected non-minimal diff");
|
||||||
|
} else {
|
||||||
|
dns_difftuple_free(tuplep);
|
||||||
|
}
|
||||||
|
dns_difftuple_free(&ot);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*tuplep != NULL) {
|
||||||
|
ISC_LIST_APPEND(diff->tuples, *tuplep, link);
|
||||||
|
*tuplep = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENSURE(*tuplep == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver)
|
||||||
|
{
|
||||||
|
dns_difftuple_t *t;
|
||||||
|
dns_dbnode_t *node = NULL;
|
||||||
|
isc_result_t result;
|
||||||
|
|
||||||
|
REQUIRE(DNS_DIFF_VALID(diff));
|
||||||
|
REQUIRE(DNS_DB_VALID(db));
|
||||||
|
|
||||||
|
t = ISC_LIST_HEAD(diff->tuples);
|
||||||
|
while (t != NULL) {
|
||||||
|
dns_name_t *name;
|
||||||
|
|
||||||
|
INSIST(node == NULL);
|
||||||
|
name = &t->name;
|
||||||
|
/*
|
||||||
|
* Find the node.
|
||||||
|
* We create the node if it does not exist.
|
||||||
|
* This will cause an empty node to be created if the diff
|
||||||
|
* contains a deletion of an RR at a nonexistent name,
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
op = t->op;
|
||||||
|
type = t->rdata.type;
|
||||||
|
covers = rdata_covers(&t->rdata);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Collect a contiguous set of updates with
|
||||||
|
* the same operation (add/delete) and RR type
|
||||||
|
* into a single rdatalist so that the
|
||||||
|
* database rrset merging/subtraction code
|
||||||
|
* can work more efficiently than if each
|
||||||
|
* RR were merged into / subtracted from
|
||||||
|
* the database separately.
|
||||||
|
*
|
||||||
|
* This is done by linking rdata structures from the
|
||||||
|
* diff into "rdatalist". This uses the rdata link
|
||||||
|
* field, not the diff link field, so the structure
|
||||||
|
* of the diff itself is not affected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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 &&
|
||||||
|
rdata_covers(&t->rdata) == covers)
|
||||||
|
{
|
||||||
|
if (t->ttl != rdl.ttl) {
|
||||||
|
isc_log_write(DIFF_COMMON_LOGARGS,
|
||||||
|
ISC_LOG_WARNING,
|
||||||
|
"TTL differs in rdataset, "
|
||||||
|
"adjusting %lu -> %lu",
|
||||||
|
(unsigned long) t->ttl,
|
||||||
|
(unsigned long) rdl.ttl);
|
||||||
|
}
|
||||||
|
ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
|
||||||
|
t = ISC_LIST_NEXT(t, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert the rdatalist into a rdataset.
|
||||||
|
*/
|
||||||
|
dns_rdataset_init(&rds);
|
||||||
|
CHECK(dns_rdatalist_tordataset(&rdl, &rds));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Merge the rdataset into the database.
|
||||||
|
*/
|
||||||
|
if (op == DNS_DIFFOP_ADD) {
|
||||||
|
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) {
|
||||||
|
result = dns_db_subtractrdataset(db, node, ver,
|
||||||
|
&rds,
|
||||||
|
DNS_DBSUB_EXACT,
|
||||||
|
NULL);
|
||||||
|
} else {
|
||||||
|
INSIST(0);
|
||||||
|
}
|
||||||
|
if (result == DNS_R_UNCHANGED) {
|
||||||
|
/*
|
||||||
|
* This will not happen when executing a
|
||||||
|
* dynamic update, because that code will
|
||||||
|
* generate strictly minimal diffs.
|
||||||
|
* It may happen when receiving an IXFR
|
||||||
|
* from a server that is not as careful.
|
||||||
|
* Issue a warning and continue.
|
||||||
|
*/
|
||||||
|
isc_log_write(DIFF_COMMON_LOGARGS,
|
||||||
|
ISC_LOG_WARNING,
|
||||||
|
"update with no effect");
|
||||||
|
} else if (result == ISC_R_SUCCESS ||
|
||||||
|
result == DNS_R_NXRRSET) {
|
||||||
|
/*
|
||||||
|
* OK.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
CHECK(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dns_db_detachnode(db, &node);
|
||||||
|
}
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
|
failure:
|
||||||
|
if (node != NULL)
|
||||||
|
dns_db_detachnode(db, &node);
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX this duplicates lots of code in dns_diff_apply(). */
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
|
||||||
|
void *add_private)
|
||||||
|
{
|
||||||
|
dns_difftuple_t *t;
|
||||||
|
isc_result_t result;
|
||||||
|
|
||||||
|
REQUIRE(DNS_DIFF_VALID(diff));
|
||||||
|
|
||||||
|
t = ISC_LIST_HEAD(diff->tuples);
|
||||||
|
while (t != NULL) {
|
||||||
|
dns_name_t *name;
|
||||||
|
|
||||||
|
name = &t->name;
|
||||||
|
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;
|
||||||
|
|
||||||
|
op = t->op;
|
||||||
|
type = t->rdata.type;
|
||||||
|
covers = rdata_covers(&t->rdata);
|
||||||
|
|
||||||
|
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 &&
|
||||||
|
rdata_covers(&t->rdata) == covers)
|
||||||
|
{
|
||||||
|
ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
|
||||||
|
t = ISC_LIST_NEXT(t, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert the rdatalist into a rdataset.
|
||||||
|
*/
|
||||||
|
dns_rdataset_init(&rds);
|
||||||
|
CHECK(dns_rdatalist_tordataset(&rdl, &rds));
|
||||||
|
rds.trust = dns_trust_ultimate;
|
||||||
|
|
||||||
|
INSIST(op == DNS_DIFFOP_ADD);
|
||||||
|
result = (*addfunc)(add_private, name, &rds);
|
||||||
|
if (result == DNS_R_UNCHANGED) {
|
||||||
|
isc_log_write(DIFF_COMMON_LOGARGS,
|
||||||
|
ISC_LOG_WARNING,
|
||||||
|
"update with no effect");
|
||||||
|
} else if (result == ISC_R_SUCCESS ||
|
||||||
|
result == DNS_R_NXRRSET) {
|
||||||
|
/*
|
||||||
|
* OK.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
CHECK(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = ISC_R_SUCCESS;
|
||||||
|
failure:
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX uses qsort(); a merge sort would be more natural for lists,
|
||||||
|
* and perhaps safer wrt thread stack overflow.
|
||||||
|
*/
|
||||||
|
isc_result_t
|
||||||
|
dns_diff_sort(dns_diff_t *diff, dns_diff_compare_func *compare) {
|
||||||
|
unsigned int length = 0;
|
||||||
|
unsigned int i;
|
||||||
|
dns_difftuple_t **v;
|
||||||
|
dns_difftuple_t *p;
|
||||||
|
REQUIRE(DNS_DIFF_VALID(diff));
|
||||||
|
|
||||||
|
for (p = ISC_LIST_HEAD(diff->tuples);
|
||||||
|
p != NULL;
|
||||||
|
p = ISC_LIST_NEXT(p, link))
|
||||||
|
length++;
|
||||||
|
if (length == 0)
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
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;
|
||||||
|
ISC_LIST_UNLINK(diff->tuples, p, link);
|
||||||
|
}
|
||||||
|
INSIST(ISC_LIST_HEAD(diff->tuples) == NULL);
|
||||||
|
qsort(v, length, sizeof(v[0]), compare);
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
ISC_LIST_APPEND(diff->tuples, v[i], link);
|
||||||
|
}
|
||||||
|
isc_mem_put(diff->mctx, v, length * sizeof(dns_difftuple_t *));
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an rdataset containing the single RR of the given
|
||||||
|
* tuple. The caller must allocate the the rdata, rdataset and
|
||||||
|
* an rdatalist structure for it to refer to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
diff_tuple_tordataset(dns_difftuple_t *t, dns_rdata_t *rdata,
|
||||||
|
dns_rdatalist_t *rdl, dns_rdataset_t *rds)
|
||||||
|
{
|
||||||
|
REQUIRE(DNS_DIFFTUPLE_VALID(t));
|
||||||
|
REQUIRE(rdl != NULL);
|
||||||
|
REQUIRE(rds != NULL);
|
||||||
|
|
||||||
|
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);
|
||||||
|
ISC_LIST_APPEND(rdl->rdata, rdata, link);
|
||||||
|
return (dns_rdatalist_tordataset(rdl, rds));
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_diff_print(dns_diff_t *diff, FILE *file) {
|
||||||
|
isc_result_t result;
|
||||||
|
dns_difftuple_t *t;
|
||||||
|
char *mem = NULL;
|
||||||
|
unsigned int size = 2048;
|
||||||
|
|
||||||
|
REQUIRE(DNS_DIFF_VALID(diff));
|
||||||
|
|
||||||
|
mem = isc_mem_get(diff->mctx, size);
|
||||||
|
if (mem == NULL)
|
||||||
|
return (ISC_R_NOMEMORY);
|
||||||
|
|
||||||
|
for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;
|
||||||
|
t = ISC_LIST_NEXT(t, link))
|
||||||
|
{
|
||||||
|
isc_buffer_t buf;
|
||||||
|
isc_region_t r;
|
||||||
|
|
||||||
|
dns_rdatalist_t rdl;
|
||||||
|
dns_rdataset_t rds;
|
||||||
|
dns_rdata_t rd = DNS_RDATA_INIT;
|
||||||
|
|
||||||
|
result = diff_tuple_tordataset(t, &rd, &rdl, &rds);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||||
|
"diff_tuple_tordataset failed: %s",
|
||||||
|
dns_result_totext(result));
|
||||||
|
result = ISC_R_UNEXPECTED;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
again:
|
||||||
|
isc_buffer_init(&buf, mem, size);
|
||||||
|
result = dns_rdataset_totext(&rds, &t->name,
|
||||||
|
ISC_FALSE, ISC_FALSE, &buf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get rid of final newline.
|
||||||
|
*/
|
||||||
|
INSIST(buf.used >= 1 &&
|
||||||
|
((char *) buf.base)[buf.used-1] == '\n');
|
||||||
|
buf.used--;
|
||||||
|
|
||||||
|
if (result == ISC_R_NOSPACE) {
|
||||||
|
isc_mem_put(diff->mctx, mem, size);
|
||||||
|
size += 1024;
|
||||||
|
mem = isc_mem_get(diff->mctx, size);
|
||||||
|
if (mem == NULL) {
|
||||||
|
result = ISC_R_NOMEMORY;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
isc_buffer_usedregion(&buf, &r);
|
||||||
|
if (file != NULL)
|
||||||
|
fprintf(file, "%s %.*s\n",
|
||||||
|
t->op == DNS_DIFFOP_ADD ?
|
||||||
|
"add" : "del", (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);
|
||||||
|
} else
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
result = ISC_R_SUCCESS;
|
||||||
|
cleanup:
|
||||||
|
if (mem != NULL)
|
||||||
|
isc_mem_put(diff->mctx, mem, size);
|
||||||
|
return (result);
|
||||||
|
}
|
272
lib/dns/include/dns/diff.h
Normal file
272
lib/dns/include/dns/diff.h
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2000 Internet Software Consortium.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and 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 INTERNET SOFTWARE CONSORTIUM
|
||||||
|
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||||
|
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||||
|
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* $Id: diff.h,v 1.1 2000/12/09 02:17:12 bwelling Exp $ */
|
||||||
|
|
||||||
|
#ifndef DNS_DIFF_H
|
||||||
|
#define DNS_DIFF_H 1
|
||||||
|
|
||||||
|
/*****
|
||||||
|
***** Module Info
|
||||||
|
*****/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A diff is a convenience type representing a list of changes to be
|
||||||
|
* made to a database.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***
|
||||||
|
*** Imports
|
||||||
|
***/
|
||||||
|
|
||||||
|
#include <isc/lang.h>
|
||||||
|
#include <isc/magic.h>
|
||||||
|
|
||||||
|
#include <dns/name.h>
|
||||||
|
#include <dns/rdata.h>
|
||||||
|
#include <dns/types.h>
|
||||||
|
|
||||||
|
/***
|
||||||
|
*** Types
|
||||||
|
***/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A dns_difftuple_t represents a single RR being added or deleted.
|
||||||
|
* The RR type and class are in the 'rdata' member; the class is always
|
||||||
|
* the real one, not a DynDNS meta-class, so that the rdatas can be
|
||||||
|
* compared using dns_rdata_compare(). The TTL is significant
|
||||||
|
* even for deletions, because a deletion/addition pair cannot
|
||||||
|
* be canceled out if the TTL differs (it might be an explicit
|
||||||
|
* TTL update).
|
||||||
|
*
|
||||||
|
* Tuples are also used to represent complete RRs with owner
|
||||||
|
* names for a couple of other purposes, such as the
|
||||||
|
* individual RRs of a "RRset exists (value dependent)"
|
||||||
|
* prerequisite set. In this case, op==DNS_DIFFOP_EXISTS,
|
||||||
|
* and the TTL is ignored.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DNS_DIFFOP_ADD, /* Add an RR. */
|
||||||
|
DNS_DIFFOP_DEL, /* Delete an RR. */
|
||||||
|
DNS_DIFFOP_EXISTS /* Assert RR existence. */
|
||||||
|
} dns_diffop_t;
|
||||||
|
|
||||||
|
typedef struct dns_difftuple dns_difftuple_t;
|
||||||
|
|
||||||
|
#define DNS_DIFFTUPLE_MAGIC 0x44494654U /* DIFT. */
|
||||||
|
#define DNS_DIFFTUPLE_VALID(t) ISC_MAGIC_VALID(t, DNS_DIFFTUPLE_MAGIC)
|
||||||
|
|
||||||
|
struct dns_difftuple {
|
||||||
|
unsigned int magic;
|
||||||
|
isc_mem_t *mctx;
|
||||||
|
dns_diffop_t op;
|
||||||
|
dns_name_t name;
|
||||||
|
dns_ttl_t ttl;
|
||||||
|
dns_rdata_t rdata;
|
||||||
|
ISC_LINK(dns_difftuple_t) link;
|
||||||
|
/* Variable-size name data and rdata follows. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A dns_diff_t represents a set of changes being applied to
|
||||||
|
* a zone. Diffs are also used to represent "RRset exists
|
||||||
|
* (value dependent)" prerequisites.
|
||||||
|
*/
|
||||||
|
typedef struct dns_diff dns_diff_t;
|
||||||
|
|
||||||
|
#define DNS_DIFF_MAGIC 0x44494646U /* DIFF. */
|
||||||
|
#define DNS_DIFF_VALID(t) ISC_MAGIC_VALID(t, DNS_DIFF_MAGIC)
|
||||||
|
|
||||||
|
struct dns_diff {
|
||||||
|
unsigned int magic;
|
||||||
|
isc_mem_t * mctx;
|
||||||
|
ISC_LIST(dns_difftuple_t) tuples;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Type of comparision function for sorting diffs. */
|
||||||
|
typedef int dns_diff_compare_func(const void *, const void *);
|
||||||
|
|
||||||
|
/***
|
||||||
|
*** Functions
|
||||||
|
***/
|
||||||
|
|
||||||
|
ISC_LANG_BEGINDECLS
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*
|
||||||
|
* Maniuplation of diffs and tuples.
|
||||||
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_difftuple_create(isc_mem_t *mctx,
|
||||||
|
dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
|
||||||
|
dns_rdata_t *rdata, dns_difftuple_t **tp);
|
||||||
|
/*
|
||||||
|
* Create a tuple. Deep copies are made of the name and rdata, so
|
||||||
|
* they need not remain valid after the call.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* *tp != NULL && *tp == NULL.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* ISC_R_SUCCESS
|
||||||
|
* ISC_R_NOMEMORY
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_difftuple_free(dns_difftuple_t **tp);
|
||||||
|
/*
|
||||||
|
* Free a tuple.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* **tp is a valid tuple.
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* *tp == NULL
|
||||||
|
* All memory used by the tuple is freed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_difftuple_copy(dns_difftuple_t *orig, dns_difftuple_t **copyp);
|
||||||
|
/*
|
||||||
|
* Copy a tuple.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* 'orig' points to a valid tuple
|
||||||
|
* copyp != NULL && *copyp == NULL
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_diff_init(isc_mem_t *mctx, dns_diff_t *diff);
|
||||||
|
/*
|
||||||
|
* Initialize a diff.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* 'diff' points to an uninitialized dns_diff_t
|
||||||
|
* allocated by the caller.
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* '*diff' is a valid, empty diff.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_diff_clear(dns_diff_t *diff);
|
||||||
|
/*
|
||||||
|
* Clear a diff, destroying all its tuples.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* 'diff' points to a valid dns_diff_t.
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* Any tuples in the diff are destroyed.
|
||||||
|
* The diff now empty, but it is still valid
|
||||||
|
* and may be reused without calling dns_diff_init
|
||||||
|
* again. The only memory used is that of the
|
||||||
|
* dns_diff_t structure itself.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* Managing the memory of the dns_diff_t structure itself
|
||||||
|
* is the caller's responsibility.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_diff_append(dns_diff_t *diff, dns_difftuple_t **tuple);
|
||||||
|
/*
|
||||||
|
* Append a single tuple to a diff.
|
||||||
|
*
|
||||||
|
* 'diff' is a valid diff.
|
||||||
|
* '*tuple' is a valid tuple.
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* *tuple is NULL.
|
||||||
|
* The tuple has been freed, or will be freed when the diff is cleared.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuple);
|
||||||
|
/*
|
||||||
|
* Append 'tuple' to 'diff', removing any duplicate
|
||||||
|
* or conflicting updates as needed to create a minimal diff.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* 'diff' is a minimal diff.
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* 'diff' is still a minimal diff.
|
||||||
|
* *tuple is NULL.
|
||||||
|
* The tuple has been freed, or will be freed when the diff is cleared.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_diff_sort(dns_diff_t *diff, dns_diff_compare_func *compare);
|
||||||
|
/*
|
||||||
|
* Sort 'diff' in-place according to the comparison function 'compare'.
|
||||||
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver);
|
||||||
|
/*
|
||||||
|
* Apply 'diff' to the database 'db'.
|
||||||
|
*
|
||||||
|
* For efficiency, the diff should be sorted by owner name.
|
||||||
|
* If it is not sorted, operation will still be correct,
|
||||||
|
* but less efficient.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* *diff is a valid diff (possibly empty), containing
|
||||||
|
* tuples of type DNS_DIFFOP_ADD and/or
|
||||||
|
* For DNS_DIFFOP_DEL tuples, the TTL is ignored.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
|
||||||
|
void *add_private);
|
||||||
|
/*
|
||||||
|
* Like dns_diff_apply, but for use when loading a new database
|
||||||
|
* instead of modifying an existing one. This bypasses the
|
||||||
|
* database transaction mechanisms.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* 'addfunc' is a valid dns_addradatasetfunc_t obtained from
|
||||||
|
* dns_db_beginload()
|
||||||
|
*
|
||||||
|
* 'add_private' points to a corresponding dns_dbload_t *
|
||||||
|
* (XXX why is it a void pointer, then?)
|
||||||
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_diff_print(dns_diff_t *diff, FILE *file);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print the differences to 'file' or if 'file' is NULL via the
|
||||||
|
* logging system.
|
||||||
|
*
|
||||||
|
* Require:
|
||||||
|
* 'diff' to be valid.
|
||||||
|
* 'file' to refer to a open file or NULL.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* ISC_R_SUCCESS
|
||||||
|
* ISC_R_NOMEMORY
|
||||||
|
* ISC_R_UNEXPECTED
|
||||||
|
* any error from dns_rdataset_totext()
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* DNS_DIFF_H */
|
@@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: journal.h,v 1.20 2000/08/03 21:31:41 marka Exp $ */
|
/* $Id: journal.h,v 1.21 2000/12/09 02:17:10 bwelling Exp $ */
|
||||||
|
|
||||||
#ifndef DNS_JOURNAL_H
|
#ifndef DNS_JOURNAL_H
|
||||||
#define DNS_JOURNAL_H 1
|
#define DNS_JOURNAL_H 1
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <isc/magic.h>
|
#include <isc/magic.h>
|
||||||
|
|
||||||
#include <dns/name.h>
|
#include <dns/name.h>
|
||||||
|
#include <dns/diff.h>
|
||||||
#include <dns/rdata.h>
|
#include <dns/rdata.h>
|
||||||
#include <dns/types.h>
|
#include <dns/types.h>
|
||||||
|
|
||||||
@@ -43,63 +44,6 @@
|
|||||||
*** Types
|
*** Types
|
||||||
***/
|
***/
|
||||||
|
|
||||||
/*
|
|
||||||
* A dns_difftuple_t represents a single RR being added or deleted.
|
|
||||||
* The RR type and class are in the 'rdata' member; the class is always
|
|
||||||
* the real one, not a DynDNS meta-class, so that the rdatas can be
|
|
||||||
* compared using dns_rdata_compare(). The TTL is significant
|
|
||||||
* even for deletions, because a deletion/addition pair cannot
|
|
||||||
* be canceled out if the TTL differs (it might be an explicit
|
|
||||||
* TTL update).
|
|
||||||
*
|
|
||||||
* Tuples are also used to represent complete RRs with owner
|
|
||||||
* names for a couple of other purposes, such as the
|
|
||||||
* individual RRs of a "RRset exists (value dependent)"
|
|
||||||
* prerequisite set. In this case, op==DNS_DIFFOP_EXISTS,
|
|
||||||
* and the TTL is ignored.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
DNS_DIFFOP_ADD, /* Add an RR. */
|
|
||||||
DNS_DIFFOP_DEL, /* Delete an RR. */
|
|
||||||
DNS_DIFFOP_EXISTS /* Assert RR existence. */
|
|
||||||
} dns_diffop_t;
|
|
||||||
|
|
||||||
typedef struct dns_difftuple dns_difftuple_t;
|
|
||||||
|
|
||||||
#define DNS_DIFFTUPLE_MAGIC 0x44494654U /* DIFT. */
|
|
||||||
#define DNS_DIFFTUPLE_VALID(t) ISC_MAGIC_VALID(t, DNS_DIFFTUPLE_MAGIC)
|
|
||||||
|
|
||||||
struct dns_difftuple {
|
|
||||||
unsigned int magic;
|
|
||||||
isc_mem_t *mctx;
|
|
||||||
dns_diffop_t op;
|
|
||||||
dns_name_t name;
|
|
||||||
dns_ttl_t ttl;
|
|
||||||
dns_rdata_t rdata;
|
|
||||||
ISC_LINK(dns_difftuple_t) link;
|
|
||||||
/* Variable-size name data and rdata follows. */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A dns_diff_t represents a set of changes being applied to
|
|
||||||
* a zone. Diffs are also used to represent "RRset exists
|
|
||||||
* (value dependent)" prerequisites.
|
|
||||||
*/
|
|
||||||
typedef struct dns_diff dns_diff_t;
|
|
||||||
|
|
||||||
#define DNS_DIFF_MAGIC 0x44494646U /* DIFF. */
|
|
||||||
#define DNS_DIFF_VALID(t) ISC_MAGIC_VALID(t, DNS_DIFF_MAGIC)
|
|
||||||
|
|
||||||
struct dns_diff {
|
|
||||||
unsigned int magic;
|
|
||||||
isc_mem_t * mctx;
|
|
||||||
ISC_LIST(dns_difftuple_t) tuples;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Type of comparision function for sorting diffs. */
|
|
||||||
typedef int dns_diff_compare_func(const void *, const void *);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A dns_journal_t represents an open journal file. This is an opaque type.
|
* A dns_journal_t represents an open journal file. This is an opaque type.
|
||||||
*
|
*
|
||||||
@@ -118,168 +62,6 @@ typedef struct dns_journal dns_journal_t;
|
|||||||
|
|
||||||
ISC_LANG_BEGINDECLS
|
ISC_LANG_BEGINDECLS
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*
|
|
||||||
* Maniuplation of diffs and tuples.
|
|
||||||
*/
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
dns_difftuple_create(isc_mem_t *mctx,
|
|
||||||
dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
|
|
||||||
dns_rdata_t *rdata, dns_difftuple_t **tp);
|
|
||||||
/*
|
|
||||||
* Create a tuple. Deep copies are made of the name and rdata, so
|
|
||||||
* they need not remain valid after the call.
|
|
||||||
*
|
|
||||||
* Requires:
|
|
||||||
* *tp != NULL && *tp == NULL.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* ISC_R_SUCCESS
|
|
||||||
* ISC_R_NOMEMORY
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
dns_difftuple_free(dns_difftuple_t **tp);
|
|
||||||
/*
|
|
||||||
* Free a tuple.
|
|
||||||
*
|
|
||||||
* Requires:
|
|
||||||
* **tp is a valid tuple.
|
|
||||||
*
|
|
||||||
* Ensures:
|
|
||||||
* *tp == NULL
|
|
||||||
* All memory used by the tuple is freed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
dns_difftuple_copy(dns_difftuple_t *orig, dns_difftuple_t **copyp);
|
|
||||||
/*
|
|
||||||
* Copy a tuple.
|
|
||||||
*
|
|
||||||
* Requires:
|
|
||||||
* 'orig' points to a valid tuple
|
|
||||||
* copyp != NULL && *copyp == NULL
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
dns_diff_init(isc_mem_t *mctx, dns_diff_t *diff);
|
|
||||||
/*
|
|
||||||
* Initialize a diff.
|
|
||||||
*
|
|
||||||
* Requires:
|
|
||||||
* 'diff' points to an uninitialized dns_diff_t
|
|
||||||
* allocated by the caller.
|
|
||||||
*
|
|
||||||
* Ensures:
|
|
||||||
* '*diff' is a valid, empty diff.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
dns_diff_clear(dns_diff_t *diff);
|
|
||||||
/*
|
|
||||||
* Clear a diff, destroying all its tuples.
|
|
||||||
*
|
|
||||||
* Requires:
|
|
||||||
* 'diff' points to a valid dns_diff_t.
|
|
||||||
*
|
|
||||||
* Ensures:
|
|
||||||
* Any tuples in the diff are destroyed.
|
|
||||||
* The diff now empty, but it is still valid
|
|
||||||
* and may be reused without calling dns_diff_init
|
|
||||||
* again. The only memory used is that of the
|
|
||||||
* dns_diff_t structure itself.
|
|
||||||
*
|
|
||||||
* Notes:
|
|
||||||
* Managing the memory of the dns_diff_t structure itself
|
|
||||||
* is the caller's responsibility.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
dns_diff_append(dns_diff_t *diff, dns_difftuple_t **tuple);
|
|
||||||
/*
|
|
||||||
* Append a single tuple to a diff.
|
|
||||||
*
|
|
||||||
* 'diff' is a valid diff.
|
|
||||||
* '*tuple' is a valid tuple.
|
|
||||||
*
|
|
||||||
* Ensures:
|
|
||||||
* *tuple is NULL.
|
|
||||||
* The tuple has been freed, or will be freed when the diff is cleared.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuple);
|
|
||||||
/*
|
|
||||||
* Append 'tuple' to 'diff', removing any duplicate
|
|
||||||
* or conflicting updates as needed to create a minimal diff.
|
|
||||||
*
|
|
||||||
* Requires:
|
|
||||||
* 'diff' is a minimal diff.
|
|
||||||
*
|
|
||||||
* Ensures:
|
|
||||||
* 'diff' is still a minimal diff.
|
|
||||||
* *tuple is NULL.
|
|
||||||
* The tuple has been freed, or will be freed when the diff is cleared.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
dns_diff_sort(dns_diff_t *diff, dns_diff_compare_func *compare);
|
|
||||||
/*
|
|
||||||
* Sort 'diff' in-place according to the comparison function 'compare'.
|
|
||||||
*/
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
dns_diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver);
|
|
||||||
/*
|
|
||||||
* Apply 'diff' to the database 'db'.
|
|
||||||
*
|
|
||||||
* For efficiency, the diff should be sorted by owner name.
|
|
||||||
* If it is not sorted, operation will still be correct,
|
|
||||||
* but less efficient.
|
|
||||||
*
|
|
||||||
* Requires:
|
|
||||||
* *diff is a valid diff (possibly empty), containing
|
|
||||||
* tuples of type DNS_DIFFOP_ADD and/or
|
|
||||||
* For DNS_DIFFOP_DEL tuples, the TTL is ignored.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
|
|
||||||
void *add_private);
|
|
||||||
/*
|
|
||||||
* Like dns_diff_apply, but for use when loading a new database
|
|
||||||
* instead of modifying an existing one. This bypasses the
|
|
||||||
* database transaction mechanisms.
|
|
||||||
*
|
|
||||||
* Requires:
|
|
||||||
* 'addfunc' is a valid dns_addradatasetfunc_t obtained from
|
|
||||||
* dns_db_beginload()
|
|
||||||
*
|
|
||||||
* 'add_private' points to a corresponding dns_dbload_t *
|
|
||||||
* (XXX why is it a void pointer, then?)
|
|
||||||
*/
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
dns_diff_print(dns_diff_t *diff, FILE *file);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print the differences to 'file' or if 'file' is NULL via the
|
|
||||||
* logging system.
|
|
||||||
*
|
|
||||||
* Require:
|
|
||||||
* 'diff' to be valid.
|
|
||||||
* 'file' to refer to a open file or NULL.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* ISC_R_SUCCESS
|
|
||||||
* ISC_R_NOMEMORY
|
|
||||||
* ISC_R_UNEXPECTED
|
|
||||||
* any error from dns_rdataset_totext()
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*
|
/*
|
||||||
* Misc. utilities
|
* Misc. utilities
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: log.h,v 1.25 2000/11/23 02:25:02 gson Exp $ */
|
/* $Id: log.h,v 1.26 2000/12/09 02:17:11 bwelling Exp $ */
|
||||||
|
|
||||||
/* Principal Authors: DCL */
|
/* Principal Authors: DCL */
|
||||||
|
|
||||||
@@ -65,6 +65,7 @@ extern isc_logmodule_t dns_modules[];
|
|||||||
#define DNS_LOGMODULE_TSIG (&dns_modules[20])
|
#define DNS_LOGMODULE_TSIG (&dns_modules[20])
|
||||||
#define DNS_LOGMODULE_TKEY (&dns_modules[21])
|
#define DNS_LOGMODULE_TKEY (&dns_modules[21])
|
||||||
#define DNS_LOGMODULE_SDB (&dns_modules[22])
|
#define DNS_LOGMODULE_SDB (&dns_modules[22])
|
||||||
|
#define DNS_LOGMODULE_DIFF (&dns_modules[23])
|
||||||
|
|
||||||
ISC_LANG_BEGINDECLS
|
ISC_LANG_BEGINDECLS
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: journal.c,v 1.66 2000/12/07 19:51:55 marka Exp $ */
|
/* $Id: journal.c,v 1.67 2000/12/09 02:17:05 bwelling Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
#include <dns/compress.h>
|
#include <dns/compress.h>
|
||||||
#include <dns/db.h>
|
#include <dns/db.h>
|
||||||
#include <dns/dbiterator.h>
|
#include <dns/dbiterator.h>
|
||||||
|
#include <dns/diff.h>
|
||||||
#include <dns/fixedname.h>
|
#include <dns/fixedname.h>
|
||||||
#include <dns/journal.h>
|
#include <dns/journal.h>
|
||||||
#include <dns/log.h>
|
#include <dns/log.h>
|
||||||
@@ -88,12 +89,6 @@ encode_uint32(isc_uint32_t val, unsigned char *p) {
|
|||||||
p[3] = (isc_uint8_t)(val >> 0);
|
p[3] = (isc_uint8_t)(val >> 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static dns_rdatatype_t
|
|
||||||
rdata_covers(dns_rdata_t *rdata) {
|
|
||||||
return (rdata->type == dns_rdatatype_sig ?
|
|
||||||
dns_rdata_covers(rdata) : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
isc_uint32_t
|
isc_uint32_t
|
||||||
dns_soa_getserial(dns_rdata_t *rdata) {
|
dns_soa_getserial(dns_rdata_t *rdata) {
|
||||||
INSIST(rdata->type == dns_rdatatype_soa);
|
INSIST(rdata->type == dns_rdatatype_soa);
|
||||||
@@ -163,492 +158,6 @@ dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*
|
|
||||||
* Diffs, aka Pending Journal Entries.
|
|
||||||
*/
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
dns_difftuple_create(isc_mem_t *mctx,
|
|
||||||
dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
|
|
||||||
dns_rdata_t *rdata, dns_difftuple_t **tp)
|
|
||||||
{
|
|
||||||
dns_difftuple_t *t;
|
|
||||||
unsigned int size;
|
|
||||||
unsigned char *datap;
|
|
||||||
|
|
||||||
REQUIRE(tp != NULL && *tp == NULL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a new tuple. The variable-size wire-format name data and
|
|
||||||
* rdata immediately follow the dns_difftuple_t structure
|
|
||||||
* in memory.
|
|
||||||
*/
|
|
||||||
size = sizeof(*t) + name->length + rdata->length;
|
|
||||||
t = isc_mem_allocate(mctx, size);
|
|
||||||
if (t == NULL)
|
|
||||||
return (ISC_R_NOMEMORY);
|
|
||||||
t->mctx = mctx;
|
|
||||||
t->op = op;
|
|
||||||
|
|
||||||
datap = (unsigned char *)(t + 1);
|
|
||||||
|
|
||||||
memcpy(datap, name->ndata, name->length);
|
|
||||||
dns_name_init(&t->name, NULL);
|
|
||||||
dns_name_clone(name, &t->name);
|
|
||||||
t->name.ndata = datap;
|
|
||||||
datap += name->length;
|
|
||||||
|
|
||||||
t->ttl = ttl;
|
|
||||||
|
|
||||||
memcpy(datap, rdata->data, rdata->length);
|
|
||||||
dns_rdata_init(&t->rdata);
|
|
||||||
dns_rdata_clone(rdata, &t->rdata);
|
|
||||||
t->rdata.data = datap;
|
|
||||||
datap += rdata->length;
|
|
||||||
|
|
||||||
ISC_LINK_INIT(&t->rdata, link);
|
|
||||||
ISC_LINK_INIT(t, link);
|
|
||||||
t->magic = DNS_DIFFTUPLE_MAGIC;
|
|
||||||
|
|
||||||
INSIST(datap == (unsigned char *)t + size);
|
|
||||||
|
|
||||||
*tp = t;
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
dns_difftuple_free(dns_difftuple_t **tp) {
|
|
||||||
dns_difftuple_t *t = *tp;
|
|
||||||
REQUIRE(DNS_DIFFTUPLE_VALID(t));
|
|
||||||
dns_name_invalidate(&t->name);
|
|
||||||
t->magic = 0;
|
|
||||||
isc_mem_free(t->mctx, t);
|
|
||||||
*tp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
dns_difftuple_copy(dns_difftuple_t *orig, dns_difftuple_t **copyp) {
|
|
||||||
return (dns_difftuple_create(orig->mctx, orig->op, &orig->name,
|
|
||||||
orig->ttl, &orig->rdata, copyp));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
dns_diff_init(isc_mem_t *mctx, dns_diff_t *diff) {
|
|
||||||
diff->mctx = mctx;
|
|
||||||
ISC_LIST_INIT(diff->tuples);
|
|
||||||
diff->magic = DNS_DIFF_MAGIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
dns_diff_clear(dns_diff_t *diff) {
|
|
||||||
dns_difftuple_t *t;
|
|
||||||
REQUIRE(DNS_DIFF_VALID(diff));
|
|
||||||
while ((t = ISC_LIST_HEAD(diff->tuples)) != NULL) {
|
|
||||||
ISC_LIST_UNLINK(diff->tuples, t, link);
|
|
||||||
dns_difftuple_free(&t);
|
|
||||||
}
|
|
||||||
ENSURE(ISC_LIST_EMPTY(diff->tuples));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
dns_diff_append(dns_diff_t *diff, dns_difftuple_t **tuplep)
|
|
||||||
{
|
|
||||||
ISC_LIST_APPEND(diff->tuples, *tuplep, link);
|
|
||||||
*tuplep = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX this is O(N) */
|
|
||||||
|
|
||||||
void
|
|
||||||
dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuplep)
|
|
||||||
{
|
|
||||||
dns_difftuple_t *ot, *next_ot;
|
|
||||||
|
|
||||||
REQUIRE(DNS_DIFF_VALID(diff));
|
|
||||||
REQUIRE(DNS_DIFFTUPLE_VALID(*tuplep));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Look for an existing tuple with the same owner name,
|
|
||||||
* rdata, and TTL. If we are doing an addition and find a
|
|
||||||
* deletion or vice versa, remove both the old and the
|
|
||||||
* new tuple since they cancel each other out (assuming
|
|
||||||
* that we never delete nonexistent data or add existing
|
|
||||||
* data).
|
|
||||||
*
|
|
||||||
* If we find an old update of the same kind as
|
|
||||||
* the one we are doing, there must be a programming
|
|
||||||
* error. We report it but try to continue anyway.
|
|
||||||
*/
|
|
||||||
for (ot = ISC_LIST_HEAD(diff->tuples); ot != NULL;
|
|
||||||
ot = next_ot)
|
|
||||||
{
|
|
||||||
next_ot = ISC_LIST_NEXT(ot, link);
|
|
||||||
if (dns_name_equal(&ot->name, &(*tuplep)->name) &&
|
|
||||||
dns_rdata_compare(&ot->rdata, &(*tuplep)->rdata) == 0 &&
|
|
||||||
ot->ttl == (*tuplep)->ttl)
|
|
||||||
{
|
|
||||||
ISC_LIST_UNLINK(diff->tuples, ot, link);
|
|
||||||
if ((*tuplep)->op == ot->op) {
|
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
||||||
"unexpected non-minimal diff");
|
|
||||||
} else {
|
|
||||||
dns_difftuple_free(tuplep);
|
|
||||||
}
|
|
||||||
dns_difftuple_free(&ot);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*tuplep != NULL) {
|
|
||||||
ISC_LIST_APPEND(diff->tuples, *tuplep, link);
|
|
||||||
*tuplep = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ENSURE(*tuplep == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
dns_diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver)
|
|
||||||
{
|
|
||||||
dns_difftuple_t *t;
|
|
||||||
dns_dbnode_t *node = NULL;
|
|
||||||
isc_result_t result;
|
|
||||||
|
|
||||||
REQUIRE(DNS_DIFF_VALID(diff));
|
|
||||||
REQUIRE(DNS_DB_VALID(db));
|
|
||||||
|
|
||||||
t = ISC_LIST_HEAD(diff->tuples);
|
|
||||||
while (t != NULL) {
|
|
||||||
dns_name_t *name;
|
|
||||||
|
|
||||||
INSIST(node == NULL);
|
|
||||||
name = &t->name;
|
|
||||||
/*
|
|
||||||
* Find the node.
|
|
||||||
* We create the node if it does not exist.
|
|
||||||
* This will cause an empty node to be created if the diff
|
|
||||||
* contains a deletion of an RR at a nonexistent name,
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
op = t->op;
|
|
||||||
type = t->rdata.type;
|
|
||||||
covers = rdata_covers(&t->rdata);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Collect a contiguous set of updates with
|
|
||||||
* the same operation (add/delete) and RR type
|
|
||||||
* into a single rdatalist so that the
|
|
||||||
* database rrset merging/subtraction code
|
|
||||||
* can work more efficiently than if each
|
|
||||||
* RR were merged into / subtracted from
|
|
||||||
* the database separately.
|
|
||||||
*
|
|
||||||
* This is done by linking rdata structures from the
|
|
||||||
* diff into "rdatalist". This uses the rdata link
|
|
||||||
* field, not the diff link field, so the structure
|
|
||||||
* of the diff itself is not affected.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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 &&
|
|
||||||
rdata_covers(&t->rdata) == covers)
|
|
||||||
{
|
|
||||||
if (t->ttl != rdl.ttl) {
|
|
||||||
isc_log_write(JOURNAL_COMMON_LOGARGS,
|
|
||||||
ISC_LOG_WARNING,
|
|
||||||
"TTL differs in rdataset, "
|
|
||||||
"adjusting %lu -> %lu",
|
|
||||||
(unsigned long) t->ttl,
|
|
||||||
(unsigned long) rdl.ttl);
|
|
||||||
}
|
|
||||||
ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
|
|
||||||
t = ISC_LIST_NEXT(t, link);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert the rdatalist into a rdataset.
|
|
||||||
*/
|
|
||||||
dns_rdataset_init(&rds);
|
|
||||||
CHECK(dns_rdatalist_tordataset(&rdl, &rds));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Merge the rdataset into the database.
|
|
||||||
*/
|
|
||||||
if (op == DNS_DIFFOP_ADD) {
|
|
||||||
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) {
|
|
||||||
result = dns_db_subtractrdataset(db, node, ver,
|
|
||||||
&rds,
|
|
||||||
DNS_DBSUB_EXACT,
|
|
||||||
NULL);
|
|
||||||
} else {
|
|
||||||
INSIST(0);
|
|
||||||
}
|
|
||||||
if (result == DNS_R_UNCHANGED) {
|
|
||||||
/*
|
|
||||||
* This will not happen when executing a
|
|
||||||
* dynamic update, because that code will
|
|
||||||
* generate strictly minimal diffs.
|
|
||||||
* It may happen when receiving an IXFR
|
|
||||||
* from a server that is not as careful.
|
|
||||||
* Issue a warning and continue.
|
|
||||||
*/
|
|
||||||
isc_log_write(JOURNAL_COMMON_LOGARGS,
|
|
||||||
ISC_LOG_WARNING,
|
|
||||||
"update with no effect");
|
|
||||||
} else if (result == ISC_R_SUCCESS ||
|
|
||||||
result == DNS_R_NXRRSET) {
|
|
||||||
/*
|
|
||||||
* OK.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
CHECK(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dns_db_detachnode(db, &node);
|
|
||||||
}
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
|
|
||||||
failure:
|
|
||||||
if (node != NULL)
|
|
||||||
dns_db_detachnode(db, &node);
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX this duplicates lots of code in dns_diff_apply(). */
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
|
|
||||||
void *add_private)
|
|
||||||
{
|
|
||||||
dns_difftuple_t *t;
|
|
||||||
isc_result_t result;
|
|
||||||
|
|
||||||
REQUIRE(DNS_DIFF_VALID(diff));
|
|
||||||
|
|
||||||
t = ISC_LIST_HEAD(diff->tuples);
|
|
||||||
while (t != NULL) {
|
|
||||||
dns_name_t *name;
|
|
||||||
|
|
||||||
name = &t->name;
|
|
||||||
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;
|
|
||||||
|
|
||||||
op = t->op;
|
|
||||||
type = t->rdata.type;
|
|
||||||
covers = rdata_covers(&t->rdata);
|
|
||||||
|
|
||||||
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 &&
|
|
||||||
rdata_covers(&t->rdata) == covers)
|
|
||||||
{
|
|
||||||
ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
|
|
||||||
t = ISC_LIST_NEXT(t, link);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert the rdatalist into a rdataset.
|
|
||||||
*/
|
|
||||||
dns_rdataset_init(&rds);
|
|
||||||
CHECK(dns_rdatalist_tordataset(&rdl, &rds));
|
|
||||||
rds.trust = dns_trust_ultimate;
|
|
||||||
|
|
||||||
INSIST(op == DNS_DIFFOP_ADD);
|
|
||||||
result = (*addfunc)(add_private, name, &rds);
|
|
||||||
if (result == DNS_R_UNCHANGED) {
|
|
||||||
isc_log_write(JOURNAL_COMMON_LOGARGS,
|
|
||||||
ISC_LOG_WARNING,
|
|
||||||
"update with no effect");
|
|
||||||
} else if (result == ISC_R_SUCCESS ||
|
|
||||||
result == DNS_R_NXRRSET) {
|
|
||||||
/*
|
|
||||||
* OK.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
CHECK(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = ISC_R_SUCCESS;
|
|
||||||
failure:
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX uses qsort(); a merge sort would be more natural for lists,
|
|
||||||
* and perhaps safer wrt thread stack overflow.
|
|
||||||
*/
|
|
||||||
isc_result_t
|
|
||||||
dns_diff_sort(dns_diff_t *diff, dns_diff_compare_func *compare) {
|
|
||||||
unsigned int length = 0;
|
|
||||||
unsigned int i;
|
|
||||||
dns_difftuple_t **v;
|
|
||||||
dns_difftuple_t *p;
|
|
||||||
REQUIRE(DNS_DIFF_VALID(diff));
|
|
||||||
|
|
||||||
for (p = ISC_LIST_HEAD(diff->tuples);
|
|
||||||
p != NULL;
|
|
||||||
p = ISC_LIST_NEXT(p, link))
|
|
||||||
length++;
|
|
||||||
if (length == 0)
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
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;
|
|
||||||
ISC_LIST_UNLINK(diff->tuples, p, link);
|
|
||||||
}
|
|
||||||
INSIST(ISC_LIST_HEAD(diff->tuples) == NULL);
|
|
||||||
qsort(v, length, sizeof(v[0]), compare);
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
ISC_LIST_APPEND(diff->tuples, v[i], link);
|
|
||||||
}
|
|
||||||
isc_mem_put(diff->mctx, v, length * sizeof(dns_difftuple_t *));
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create an rdataset containing the single RR of the given
|
|
||||||
* tuple. The caller must allocate the the rdata, rdataset and
|
|
||||||
* an rdatalist structure for it to refer to.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static isc_result_t
|
|
||||||
diff_tuple_tordataset(dns_difftuple_t *t, dns_rdata_t *rdata,
|
|
||||||
dns_rdatalist_t *rdl, dns_rdataset_t *rds)
|
|
||||||
{
|
|
||||||
REQUIRE(DNS_DIFFTUPLE_VALID(t));
|
|
||||||
REQUIRE(rdl != NULL);
|
|
||||||
REQUIRE(rds != NULL);
|
|
||||||
|
|
||||||
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);
|
|
||||||
ISC_LIST_APPEND(rdl->rdata, rdata, link);
|
|
||||||
return (dns_rdatalist_tordataset(rdl, rds));
|
|
||||||
}
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
dns_diff_print(dns_diff_t *diff, FILE *file) {
|
|
||||||
isc_result_t result;
|
|
||||||
dns_difftuple_t *t;
|
|
||||||
char *mem = NULL;
|
|
||||||
unsigned int size = 2048;
|
|
||||||
|
|
||||||
REQUIRE(DNS_DIFF_VALID(diff));
|
|
||||||
|
|
||||||
mem = isc_mem_get(diff->mctx, size);
|
|
||||||
if (mem == NULL)
|
|
||||||
return (ISC_R_NOMEMORY);
|
|
||||||
|
|
||||||
for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;
|
|
||||||
t = ISC_LIST_NEXT(t, link))
|
|
||||||
{
|
|
||||||
isc_buffer_t buf;
|
|
||||||
isc_region_t r;
|
|
||||||
|
|
||||||
dns_rdatalist_t rdl;
|
|
||||||
dns_rdataset_t rds;
|
|
||||||
dns_rdata_t rd = DNS_RDATA_INIT;
|
|
||||||
|
|
||||||
result = diff_tuple_tordataset(t, &rd, &rdl, &rds);
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
||||||
"diff_tuple_tordataset failed: %s",
|
|
||||||
dns_result_totext(result));
|
|
||||||
result = ISC_R_UNEXPECTED;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
again:
|
|
||||||
isc_buffer_init(&buf, mem, size);
|
|
||||||
result = dns_rdataset_totext(&rds, &t->name,
|
|
||||||
ISC_FALSE, ISC_FALSE, &buf);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get rid of final newline.
|
|
||||||
*/
|
|
||||||
INSIST(buf.used >= 1 &&
|
|
||||||
((char *) buf.base)[buf.used-1] == '\n');
|
|
||||||
buf.used--;
|
|
||||||
|
|
||||||
if (result == ISC_R_NOSPACE) {
|
|
||||||
isc_mem_put(diff->mctx, mem, size);
|
|
||||||
size += 1024;
|
|
||||||
mem = isc_mem_get(diff->mctx, size);
|
|
||||||
if (mem == NULL) {
|
|
||||||
result = ISC_R_NOMEMORY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
if (result == ISC_R_SUCCESS) {
|
|
||||||
isc_buffer_usedregion(&buf, &r);
|
|
||||||
if (file != NULL)
|
|
||||||
fprintf(file, "%s %.*s\n",
|
|
||||||
t->op == DNS_DIFFOP_ADD ?
|
|
||||||
"add" : "del", (int) r.length,
|
|
||||||
(char *) r.base);
|
|
||||||
else
|
|
||||||
isc_log_write(JOURNAL_COMMON_LOGARGS,
|
|
||||||
ISC_LOG_DEBUG(7),
|
|
||||||
"%s %.*s",
|
|
||||||
t->op == DNS_DIFFOP_ADD ?
|
|
||||||
"add" : "del",
|
|
||||||
(int) r.length, (char *) r.base);
|
|
||||||
} else
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
result = ISC_R_SUCCESS;
|
|
||||||
cleanup:
|
|
||||||
if (mem != NULL)
|
|
||||||
isc_mem_put(diff->mctx, mem, size);
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*
|
/*
|
||||||
* Journalling.
|
* Journalling.
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: log.c,v 1.28 2000/11/23 02:25:01 gson Exp $ */
|
/* $Id: log.c,v 1.29 2000/12/09 02:17:07 bwelling Exp $ */
|
||||||
|
|
||||||
/* Principal Authors: DCL */
|
/* Principal Authors: DCL */
|
||||||
|
|
||||||
@@ -70,6 +70,7 @@ isc_logmodule_t dns_modules[] = {
|
|||||||
{ "dns/tsig", 0 },
|
{ "dns/tsig", 0 },
|
||||||
{ "dns/tkey", 0 },
|
{ "dns/tkey", 0 },
|
||||||
{ "dns/sdb", 0 },
|
{ "dns/sdb", 0 },
|
||||||
|
{ "dns/diff", 0 },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: xfrin.c,v 1.106 2000/11/17 19:04:47 gson Exp $ */
|
/* $Id: xfrin.c,v 1.107 2000/12/09 02:17:08 bwelling Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
#include <dns/db.h>
|
#include <dns/db.h>
|
||||||
|
#include <dns/diff.h>
|
||||||
#include <dns/events.h>
|
#include <dns/events.h>
|
||||||
#include <dns/journal.h>
|
#include <dns/journal.h>
|
||||||
#include <dns/log.h>
|
#include <dns/log.h>
|
||||||
|
@@ -898,6 +898,7 @@
|
|||||||
./lib/dns/db.c C 1999,2000
|
./lib/dns/db.c C 1999,2000
|
||||||
./lib/dns/dbiterator.c C 1999,2000
|
./lib/dns/dbiterator.c C 1999,2000
|
||||||
./lib/dns/dbtable.c C 1999,2000
|
./lib/dns/dbtable.c C 1999,2000
|
||||||
|
./lib/dns/diff.c C 2000
|
||||||
./lib/dns/dispatch.c C 1999,2000
|
./lib/dns/dispatch.c C 1999,2000
|
||||||
./lib/dns/dnssec.c C 1999,2000
|
./lib/dns/dnssec.c C 1999,2000
|
||||||
./lib/dns/forward.c C 2000
|
./lib/dns/forward.c C 2000
|
||||||
@@ -937,6 +938,7 @@
|
|||||||
./lib/dns/include/dns/db.h C 1999,2000
|
./lib/dns/include/dns/db.h C 1999,2000
|
||||||
./lib/dns/include/dns/dbiterator.h C 1999,2000
|
./lib/dns/include/dns/dbiterator.h C 1999,2000
|
||||||
./lib/dns/include/dns/dbtable.h C 1999,2000
|
./lib/dns/include/dns/dbtable.h C 1999,2000
|
||||||
|
./lib/dns/include/dns/diff.h C 2000
|
||||||
./lib/dns/include/dns/dispatch.h C 1999,2000
|
./lib/dns/include/dns/dispatch.h C 1999,2000
|
||||||
./lib/dns/include/dns/dnssec.h C 1999,2000
|
./lib/dns/include/dns/dnssec.h C 1999,2000
|
||||||
./lib/dns/include/dns/events.h C 1999,2000
|
./lib/dns/include/dns/events.h C 1999,2000
|
||||||
|
Reference in New Issue
Block a user