mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 05:57:52 +00:00
Add dns_db_subtractrdataset().
Add DNS_R_UNCHANGED results for dns_db_{add,delete}rdataset(). Add merge flag to dns_db_addrdataset(). The way add and delete work should now match the .h file comments.
This commit is contained in:
parent
b683976fbc
commit
a7e185ff3f
31
lib/dns/db.c
31
lib/dns/db.c
@ -420,7 +420,7 @@ dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_result_t
|
||||
dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
isc_stdtime_t now, dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *addedrdataset)
|
||||
isc_boolean_t merge, dns_rdataset_t *addedrdataset)
|
||||
{
|
||||
/*
|
||||
* Add 'rdataset' to 'node' in version 'version' of 'db'.
|
||||
@ -429,7 +429,8 @@ dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
REQUIRE(node != NULL);
|
||||
REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL)||
|
||||
((db->attributes & DNS_DBATTR_CACHE) != 0 && version == NULL));
|
||||
((db->attributes & DNS_DBATTR_CACHE) != 0 &&
|
||||
version == NULL && !merge));
|
||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||
REQUIRE(rdataset->methods != NULL);
|
||||
REQUIRE(rdataset->rdclass == db->rdclass);
|
||||
@ -438,7 +439,31 @@ dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
addedrdataset->methods == NULL));
|
||||
|
||||
return ((db->methods->addrdataset)(db, node, version, now, rdataset,
|
||||
addedrdataset));
|
||||
merge, addedrdataset));
|
||||
}
|
||||
|
||||
dns_result_t
|
||||
dns_db_subtractrdataset(dns_db_t *db, dns_dbnode_t *node,
|
||||
dns_dbversion_t *version, dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *newrdataset)
|
||||
{
|
||||
/*
|
||||
* Remove any rdata in 'rdataset' from 'node' in version 'version' of
|
||||
* 'db'.
|
||||
*/
|
||||
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
REQUIRE(node != NULL);
|
||||
REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL));
|
||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||
REQUIRE(rdataset->methods != NULL);
|
||||
REQUIRE(rdataset->rdclass == db->rdclass);
|
||||
REQUIRE(newrdataset == NULL ||
|
||||
(DNS_RDATASET_VALID(newrdataset) &&
|
||||
newrdataset->methods == NULL));
|
||||
|
||||
return ((db->methods->subtractrdataset)(db, node, version, rdataset,
|
||||
newrdataset));
|
||||
}
|
||||
|
||||
dns_result_t
|
||||
|
@ -119,7 +119,12 @@ typedef struct dns_dbmethods {
|
||||
dns_dbversion_t *version,
|
||||
isc_stdtime_t now,
|
||||
dns_rdataset_t *rdataset,
|
||||
isc_boolean_t merge,
|
||||
dns_rdataset_t *addedrdataset);
|
||||
dns_result_t (*subtractrdataset)(dns_db_t *db, dns_dbnode_t *node,
|
||||
dns_dbversion_t *version,
|
||||
dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *newrdataset);
|
||||
dns_result_t (*deleterdataset)(dns_db_t *db, dns_dbnode_t *node,
|
||||
dns_dbversion_t *version,
|
||||
dns_rdatatype_t type);
|
||||
@ -794,12 +799,18 @@ dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_result_t
|
||||
dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
isc_stdtime_t now, dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *addedrdataset);
|
||||
isc_boolean_t merge, dns_rdataset_t *addedrdataset);
|
||||
/*
|
||||
* Add 'rdataset' to 'node' in version 'version' of 'db'.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* If the database has zone semantics, 'merge' is ISC_TRUE, and an
|
||||
* rdataset of the same type as 'rdataset' already exists at 'node',
|
||||
* then the contents of 'rdataset' will be merged with the existing
|
||||
* rdataset. If merge is ISC_FALSE, then rdataset will replace any
|
||||
* existing rdataset of the same type.
|
||||
*
|
||||
* The 'now' field is ignored if 'db' is a zone database. If 'db' is
|
||||
* a cache database, then the added rdataset will expire no later than
|
||||
* now + rdataset->ttl.
|
||||
@ -822,13 +833,52 @@ dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
* read-write version, or the database has cache semantics
|
||||
* and version is NULL.
|
||||
*
|
||||
* If the database has cache semantics, 'merge' must be ISC_FALSE.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* DNS_R_SUCCESS
|
||||
* DNS_R_UNCHANGED The operation did not change anything.
|
||||
* DNS_R_NOMEMORY
|
||||
* DNS_R_EXISTS An rdataset with the specified
|
||||
* rdataset's type and version's serial
|
||||
* number already exists.
|
||||
*
|
||||
* Other results are possible, depending upon the database
|
||||
* implementation used.
|
||||
*/
|
||||
|
||||
dns_result_t
|
||||
dns_db_subtractrdataset(dns_db_t *db, dns_dbnode_t *node,
|
||||
dns_dbversion_t *version, dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *newrdataset);
|
||||
/*
|
||||
* Remove any rdata in 'rdataset' from 'node' in version 'version' of
|
||||
* 'db'.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* If 'newrdataset' is not NULL, then it will be attached to the
|
||||
* rdataset added to the database, unless the rdataset has become
|
||||
* nonexistent.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* 'db' is a valid database.
|
||||
*
|
||||
* 'node' is a valid node.
|
||||
*
|
||||
* 'rdataset' is a valid, associated rdataset with the same class
|
||||
* as 'db'.
|
||||
*
|
||||
* 'newrdataset' is NULL, or a valid, unassociated rdataset.
|
||||
*
|
||||
* The database has zone semantics and 'version' is a valid
|
||||
* read-write version.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* DNS_R_SUCCESS
|
||||
* DNS_R_UNCHANGED The operation did not change anything.
|
||||
* DNS_R_NXRDATASET All rdata of the same type as those
|
||||
* in 'rdataset' have been deleted.
|
||||
*
|
||||
* Other results are possible, depending upon the database
|
||||
* implementation used.
|
||||
@ -867,7 +917,8 @@ dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
|
||||
* Returns:
|
||||
*
|
||||
* DNS_R_SUCCESS
|
||||
* DNS_R_NOTFOUND
|
||||
* DNS_R_UNCHANGED No rdatasets of 'type' existed before
|
||||
* the operation was attempted.
|
||||
*
|
||||
* Other results are possible, depending upon the database
|
||||
* implementation used.
|
||||
|
@ -2274,6 +2274,9 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
||||
rdatasetheader_t *header, *header_prev;
|
||||
unsigned char *merged;
|
||||
dns_result_t result;
|
||||
isc_boolean_t force = ISC_FALSE;
|
||||
isc_boolean_t header_nx;
|
||||
isc_boolean_t newheader_nx;
|
||||
|
||||
/*
|
||||
* Add an rdatasetheader_t to a node.
|
||||
@ -2284,11 +2287,19 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
||||
*/
|
||||
|
||||
if (rbtversion != NULL && !loading) {
|
||||
/*
|
||||
* We always add a changed record, even if no changes end up
|
||||
* being made to this node, because it's harmless and
|
||||
* simplifies the code.
|
||||
*/
|
||||
changed = add_changed(rbtdb, rbtversion, rbtnode);
|
||||
if (changed == NULL)
|
||||
return (DNS_R_NOMEMORY);
|
||||
}
|
||||
|
||||
newheader_nx = ((newheader->attributes & RDATASET_ATTR_NONEXISTENT)
|
||||
!= 0 ? ISC_TRUE : ISC_FALSE);
|
||||
|
||||
header_prev = NULL;
|
||||
for (header = rbtnode->data; header != NULL; header = header->next) {
|
||||
if (header->type == newheader->type)
|
||||
@ -2296,13 +2307,28 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
||||
header_prev = header;
|
||||
}
|
||||
if (header != NULL) {
|
||||
header_nx = ((header->attributes & RDATASET_ATTR_NONEXISTENT)
|
||||
!= 0 ? ISC_TRUE : ISC_FALSE);
|
||||
|
||||
/*
|
||||
* Deleting an already non-existent rdataset has no effect.
|
||||
*/
|
||||
if (header_nx && newheader_nx) {
|
||||
free_rdataset(rbtdb->common.mctx, newheader);
|
||||
return (DNS_R_UNCHANGED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't merge if a nonexistent rdataset is involved.
|
||||
*/
|
||||
if (merge &&
|
||||
((newheader->attributes & RDATASET_ATTR_NONEXISTENT) != 0
|
||||
|| (header->attributes & RDATASET_ATTR_NONEXISTENT) != 0))
|
||||
if (merge && (header_nx || newheader_nx))
|
||||
merge = ISC_FALSE;
|
||||
|
||||
/*
|
||||
* XXXRTH We should turn off merging for rdata types that
|
||||
* cannot be merged, e.g. SOA, CNAME, WKS.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If 'merge' is ISC_TRUE, we'll try to create a new rdataset
|
||||
* that is the union of 'newheader' and 'header'.
|
||||
@ -2310,6 +2336,12 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
||||
if (merge) {
|
||||
INSIST(rbtversion->serial >= header->serial);
|
||||
merged = NULL;
|
||||
if (newheader->ttl != header->ttl)
|
||||
force = ISC_TRUE;
|
||||
/*
|
||||
* XXXRTH we're going to have to deal with signatures
|
||||
* somehow here...
|
||||
*/
|
||||
result = dns_rdataslab_merge(
|
||||
(unsigned char *)header,
|
||||
(unsigned char *)newheader,
|
||||
@ -2317,6 +2349,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
||||
rbtdb->common.mctx,
|
||||
rbtdb->common.rdclass,
|
||||
header->type,
|
||||
force,
|
||||
&merged);
|
||||
if (result == DNS_R_SUCCESS) {
|
||||
/*
|
||||
@ -2331,13 +2364,6 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
||||
newheader = (rdatasetheader_t *)merged;
|
||||
} else {
|
||||
free_rdataset(rbtdb->common.mctx, newheader);
|
||||
if (result == DNS_R_UNCHANGED) {
|
||||
if (addedrdataset != NULL)
|
||||
bind_rdataset(rbtdb, rbtnode,
|
||||
header, now,
|
||||
addedrdataset);
|
||||
return (DNS_R_SUCCESS);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
@ -2368,6 +2394,15 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
||||
/*
|
||||
* The rdataset type doesn't exist at this node.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If we're trying to delete it, don't bother.
|
||||
*/
|
||||
if (newheader_nx) {
|
||||
free_rdataset(rbtdb->common.mctx, newheader);
|
||||
return (DNS_R_UNCHANGED);
|
||||
}
|
||||
|
||||
newheader->next = rbtnode->data;
|
||||
newheader->down = NULL;
|
||||
rbtnode->data = newheader;
|
||||
@ -2394,7 +2429,7 @@ delegating_type(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
|
||||
static dns_result_t
|
||||
addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
isc_stdtime_t now, dns_rdataset_t *rdataset,
|
||||
isc_stdtime_t now, dns_rdataset_t *rdataset, isc_boolean_t merge,
|
||||
dns_rdataset_t *addedrdataset)
|
||||
{
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
@ -2403,7 +2438,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
isc_region_t region;
|
||||
rdatasetheader_t *newheader;
|
||||
dns_result_t result;
|
||||
isc_boolean_t merge, delegating;
|
||||
isc_boolean_t delegating;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
@ -2459,6 +2494,18 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
return (result);
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_rdataset_t *rdataset, dns_rdataset_t *newrdataset) {
|
||||
(void)db;
|
||||
(void)node;
|
||||
(void)version;
|
||||
(void)rdataset;
|
||||
(void)newrdataset;
|
||||
|
||||
return (DNS_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
dns_rdatatype_t type)
|
||||
@ -2659,6 +2706,7 @@ static dns_dbmethods_t zone_methods = {
|
||||
zone_findrdataset,
|
||||
allrdatasets,
|
||||
addrdataset,
|
||||
subtractrdataset,
|
||||
deleterdataset
|
||||
};
|
||||
|
||||
@ -2681,6 +2729,7 @@ static dns_dbmethods_t cache_methods = {
|
||||
cache_findrdataset,
|
||||
allrdatasets,
|
||||
addrdataset,
|
||||
subtractrdataset,
|
||||
deleterdataset
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user