diff.c revision a76b380643a22f23a67a9df284e86cd7ef7608c1
/*
* Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: diff.c,v 1.15 2008/04/01 01:37:24 marka 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(t->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
unsigned int delta;
when = 0;
} else {
}
while (result == ISC_R_SUCCESS) {
goto next_rr;
}
switch (op) {
case DNS_DIFFOP_ADDRESIGN:
case DNS_DIFFOP_DELRESIGN:
break;
default:
INSIST(0);
}
}
return (when);
}
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.
*/
/*
* 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.
*/
while (t != NULL &&
{
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.
*/
switch (op) {
case DNS_DIFFOP_ADDRESIGN:
case DNS_DIFFOP_DELRESIGN:
break;
default:
break;
}
/*
* Merge the rdataset into the database.
*/
switch (op) {
case DNS_DIFFOP_ADD:
case DNS_DIFFOP_ADDRESIGN:
0, &rds,
modified);
break;
case DNS_DIFFOP_DEL:
case DNS_DIFFOP_DELRESIGN:
&rds,
modified);
break;
default:
INSIST(0);
}
if (result == ISC_R_SUCCESS) {
resign);
}
} 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)
"update with no effect");
} else if (result == DNS_R_NXRRSET) {
/*
* OK.
*/
} else {
}
if (offline)
}
}
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) {
"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);
i = 0;
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 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);
}