diff.c revision 0c27b3fe77ac1d5094ba3521e8142d9e7973133f
/*
* Copyright (C) 2000-2005, 2007-2009, 2011, 2013-2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/* $Id: diff.c,v 1.26 2011/03/25 23:53:02 each Exp $ */
/*! \file */
#include <config.h>
#include <stdlib.h>
#include <dns/rdataclass.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdatastruct.h>
#include <dns/rdatatype.h>
} while (0)
#define DIFF_COMMON_LOGARGS \
static dns_rdatatype_t
dns_rdata_covers(rdata) : 0);
}
{
dns_difftuple_t *t;
unsigned int size;
unsigned char *datap;
/*
* Create a new tuple. The variable-size wire-format name data and
* rdata immediately follow the dns_difftuple_t structure
* in memory.
*/
if (t == NULL)
return (ISC_R_NOMEMORY);
datap = (unsigned char *)(t + 1);
dns_rdata_init(&t->rdata);
ISC_LINK_INIT(t, link);
t->magic = DNS_DIFFTUPLE_MAGIC;
*tp = t;
return (ISC_R_SUCCESS);
}
void
dns_difftuple_t *t = *tp;
dns_name_invalidate(&t->name);
t->magic = 0;
isc_mem_free(mctx, t);
}
}
void
}
void
dns_difftuple_t *t;
dns_difftuple_free(&t);
}
}
void
{
}
/* XXX this is O(N) */
void
{
/*
* 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.
*/
{
{
"unexpected non-minimal diff");
} else {
}
break;
}
}
}
}
static isc_stdtime_t
when = 0;
else
while (result == ISC_R_SUCCESS) {
goto next_rr;
}
}
return (when);
}
static void
}
static void
}
static isc_result_t
{
dns_difftuple_t *t;
char namebuf[DNS_NAME_FORMATSIZE];
char typebuf[DNS_RDATATYPE_FORMATSIZE];
while (t != NULL) {
/*
* 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.
*/
unsigned int options;
/*
* Collect a contiguous set of updates with
* 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.
*/
if (type != dns_rdatatype_nsec3 &&
&node));
else
&node));
while (t != NULL &&
{
/*
* Remember the add name for
* dns_rdataset_setownercase.
*/
sizeof(namebuf));
sizeof(typebuf));
sizeof(classbuf));
"'%s/%s/%s': TTL differs in "
"rdataset, adjusting "
"%lu -> %lu",
(unsigned long) t->ttl,
}
t = ISC_LIST_NEXT(t, link);
}
/*
* Convert the rdatalist into a rdataset.
*/
/*
* Merge the rdataset into the database.
*/
switch (op) {
case DNS_DIFFOP_ADD:
case DNS_DIFFOP_ADDRESIGN:
&ardataset);
break;
case DNS_DIFFOP_DEL:
case DNS_DIFFOP_DELRESIGN:
&ardataset);
break;
default:
INSIST(0);
}
if (result == ISC_R_SUCCESS) {
(op == DNS_DIFFOP_DELRESIGN ||
op == DNS_DIFFOP_ADDRESIGN)) {
resign);
}
if (op == DNS_DIFFOP_ADD ||
if (op == DNS_DIFFOP_DEL ||
} else 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.
*/
if (warn) {
sizeof(namebuf));
sizeof(classbuf));
"%s/%s: dns_diff_apply: "
"update with no effect",
}
if (op == DNS_DIFFOP_ADD ||
if (op == DNS_DIFFOP_DEL ||
} else if (result == DNS_R_NXRRSET) {
/*
* OK.
*/
if (op == DNS_DIFFOP_DEL ||
} else {
}
}
}
return (ISC_R_SUCCESS);
return (result);
}
}
}
/* XXX this duplicates lots of code in diff_apply(). */
void *add_private)
{
dns_difftuple_t *t;
while (t != NULL) {
{
t = ISC_LIST_NEXT(t, link);
}
/*
* Convert the rdatalist into a rdataset.
*/
if (result == DNS_R_UNCHANGED) {
"dns_diff_load: "
"update with no effect");
} else if (result == ISC_R_SUCCESS ||
result == DNS_R_NXRRSET) {
/*
* OK.
*/
} else {
}
}
}
return (result);
}
/*
* XXX uses qsort(); a merge sort would be more natural for lists,
* and perhaps safer wrt thread stack overflow.
*/
unsigned int length = 0;
unsigned int i;
dns_difftuple_t **v;
dns_difftuple_t *p;
p != NULL;
p = ISC_LIST_NEXT(p, link))
length++;
if (length == 0)
return (ISC_R_SUCCESS);
if (v == NULL)
return (ISC_R_NOMEMORY);
for (i = 0; i < length; i++) {
v[i] = p;
}
for (i = 0; i < length; i++) {
}
return (ISC_R_SUCCESS);
}
/*
* Create an rdataset containing the single RR of the given
* tuple. The caller must allocate the rdata, rdataset and
* an rdatalist structure for it to refer to.
*/
static isc_result_t
{
}
dns_difftuple_t *t;
unsigned int size = 2048;
return (ISC_R_NOMEMORY);
t = ISC_LIST_NEXT(t, link))
{
isc_region_t r;
if (result != ISC_R_SUCCESS) {
"diff_tuple_tordataset failed: %s",
goto cleanup;
}
if (result == ISC_R_NOSPACE) {
size += 1024;
goto cleanup;
}
goto again;
}
if (result != ISC_R_SUCCESS)
goto cleanup;
/*
* Get rid of final newline.
*/
isc_buffer_usedregion(&buf, &r);
switch (t->op) {
}
(char *) r.base);
else
(char *) r.base);
}
return (result);
}