mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
untested dns_db_subtractrdataset()
This commit is contained in:
121
lib/dns/rbtdb.c
121
lib/dns/rbtdb.c
@@ -2296,8 +2296,10 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
|||||||
* simplifies the code.
|
* simplifies the code.
|
||||||
*/
|
*/
|
||||||
changed = add_changed(rbtdb, rbtversion, rbtnode);
|
changed = add_changed(rbtdb, rbtversion, rbtnode);
|
||||||
if (changed == NULL)
|
if (changed == NULL) {
|
||||||
|
free_rdataset(rbtdb->common.mctx, newheader);
|
||||||
return (DNS_R_NOMEMORY);
|
return (DNS_R_NOMEMORY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newheader_nx = ((newheader->attributes & RDATASET_ATTR_NONEXISTENT)
|
newheader_nx = ((newheader->attributes & RDATASET_ATTR_NONEXISTENT)
|
||||||
@@ -2510,14 +2512,117 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
|||||||
|
|
||||||
static dns_result_t
|
static dns_result_t
|
||||||
subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||||
dns_rdataset_t *rdataset, dns_rdataset_t *newrdataset) {
|
dns_rdataset_t *rdataset, dns_rdataset_t *newrdataset)
|
||||||
(void)db;
|
{
|
||||||
(void)node;
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||||
(void)version;
|
dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
|
||||||
(void)rdataset;
|
rbtdb_version_t *rbtversion = version;
|
||||||
(void)newrdataset;
|
rdatasetheader_t *header, *header_prev, *newheader;
|
||||||
|
unsigned char *subresult;
|
||||||
|
isc_region_t region;
|
||||||
|
dns_result_t result;
|
||||||
|
rbtdb_changed_t *changed;
|
||||||
|
|
||||||
return (DNS_R_NOTIMPLEMENTED);
|
REQUIRE(VALID_RBTDB(rbtdb));
|
||||||
|
|
||||||
|
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
||||||
|
®ion,
|
||||||
|
sizeof (rdatasetheader_t));
|
||||||
|
if (result != DNS_R_SUCCESS)
|
||||||
|
return (result);
|
||||||
|
|
||||||
|
newheader = (rdatasetheader_t *)region.base;
|
||||||
|
newheader->ttl = 0;
|
||||||
|
newheader->type = rdataset->type;
|
||||||
|
newheader->attributes = 0;
|
||||||
|
newheader->serial = rbtversion->serial;
|
||||||
|
newheader->trust = 0;
|
||||||
|
|
||||||
|
LOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
|
||||||
|
|
||||||
|
changed = add_changed(rbtdb, rbtversion, rbtnode);
|
||||||
|
if (changed == NULL) {
|
||||||
|
free_rdataset(rbtdb->common.mctx, newheader);
|
||||||
|
return (DNS_R_NOMEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
header_prev = NULL;
|
||||||
|
for (header = rbtnode->data; header != NULL; header = header->next) {
|
||||||
|
if (header->type == newheader->type)
|
||||||
|
break;
|
||||||
|
header_prev = header;
|
||||||
|
}
|
||||||
|
if (header != NULL) {
|
||||||
|
result = dns_rdataslab_subtract(
|
||||||
|
(unsigned char *)header,
|
||||||
|
(unsigned char *)newheader,
|
||||||
|
(unsigned int)(sizeof *newheader),
|
||||||
|
rbtdb->common.mctx,
|
||||||
|
rbtdb->common.rdclass,
|
||||||
|
header->type,
|
||||||
|
&subresult);
|
||||||
|
if (result == DNS_R_SUCCESS) {
|
||||||
|
free_rdataset(rbtdb->common.mctx, newheader);
|
||||||
|
newheader = (rdatasetheader_t *)subresult;
|
||||||
|
/*
|
||||||
|
* We have to set the serial since the rdataslab
|
||||||
|
* subtraction routine copies the reserved portion of
|
||||||
|
* header, not newheader.
|
||||||
|
*/
|
||||||
|
newheader->serial = rbtversion->serial;
|
||||||
|
} else if (result == DNS_R_NXRDATASET) {
|
||||||
|
/*
|
||||||
|
* This subtraction would remove all of the rdata;
|
||||||
|
* add a nonexistent header instead.
|
||||||
|
*/
|
||||||
|
free_rdataset(rbtdb->common.mctx, newheader);
|
||||||
|
newheader = isc_mem_get(rbtdb->common.mctx,
|
||||||
|
sizeof *newheader);
|
||||||
|
if (newheader == NULL) {
|
||||||
|
result = DNS_R_NOMEMORY;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
newheader->ttl = 0;
|
||||||
|
newheader->type = rdataset->type;
|
||||||
|
newheader->attributes = RDATASET_ATTR_NONEXISTENT;
|
||||||
|
newheader->trust = 0;
|
||||||
|
newheader->serial = rbtversion->serial;
|
||||||
|
} else {
|
||||||
|
free_rdataset(rbtdb->common.mctx, newheader);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're here, we want to link newheader in front of
|
||||||
|
* header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
INSIST(rbtversion->serial >= header->serial);
|
||||||
|
if (header_prev != NULL)
|
||||||
|
header_prev->next = newheader;
|
||||||
|
else
|
||||||
|
rbtnode->data = newheader;
|
||||||
|
newheader->next = header->next;
|
||||||
|
newheader->down = header;
|
||||||
|
header->next = newheader;
|
||||||
|
rbtnode->dirty = 1;
|
||||||
|
changed->dirty = ISC_TRUE;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* The rdataset doesn't exist, so we don't need to do anything
|
||||||
|
* to satisfy the deletion request.
|
||||||
|
*/
|
||||||
|
free_rdataset(rbtdb->common.mctx, newheader);
|
||||||
|
result = DNS_R_UNCHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == DNS_R_SUCCESS && newrdataset != NULL)
|
||||||
|
bind_rdataset(rbtdb, rbtnode, newheader, 0, newrdataset);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
|
||||||
|
|
||||||
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static dns_result_t
|
static dns_result_t
|
||||||
|
Reference in New Issue
Block a user