Do not allow rdatasets of singleton type to have more than one rdata.
Check for CNAME and other data. [RT #154] [RT #279]
This commit is contained in:
117
lib/dns/rbtdb.c
117
lib/dns/rbtdb.c
@@ -15,7 +15,7 @@
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: rbtdb.c,v 1.132 2000/11/16 22:33:45 bwelling Exp $ */
|
||||
/* $Id: rbtdb.c,v 1.133 2000/11/22 00:18:33 halley Exp $ */
|
||||
|
||||
/*
|
||||
* Principal Author: Bob Halley
|
||||
@@ -3020,6 +3020,85 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
cname_and_other_data(dns_rbtnode_t *node, rbtdb_serial_t serial) {
|
||||
rdatasetheader_t *header, *header_next;
|
||||
isc_boolean_t cname, other_data;
|
||||
dns_rdatatype_t rdtype;
|
||||
|
||||
/*
|
||||
* The caller must hold the node lock.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Look for CNAME and "other data" rdatasets active in our version.
|
||||
*/
|
||||
cname = ISC_FALSE;
|
||||
other_data = ISC_FALSE;
|
||||
for (header = node->data; header != NULL; header = header_next) {
|
||||
header_next = header->next;
|
||||
if (header->type == dns_rdatatype_cname) {
|
||||
/*
|
||||
* Look for an active extant CNAME.
|
||||
*/
|
||||
do {
|
||||
if (header->serial <= serial &&
|
||||
!IGNORE(header)) {
|
||||
/*
|
||||
* Is this a "this rdataset doesn't
|
||||
* exist" record?
|
||||
*/
|
||||
if (NONEXISTENT(header))
|
||||
header = NULL;
|
||||
break;
|
||||
} else
|
||||
header = header->down;
|
||||
} while (header != NULL);
|
||||
if (header != NULL)
|
||||
cname = ISC_TRUE;
|
||||
} else {
|
||||
/*
|
||||
* Look for active extant "other data".
|
||||
*
|
||||
* "Other data" is any rdataset whose type is not
|
||||
* KEY, SIG KEY, NXT, SIG NXT, or SIG CNAME.
|
||||
*/
|
||||
rdtype = RBTDB_RDATATYPE_BASE(header->type);
|
||||
if (rdtype == dns_rdatatype_sig)
|
||||
rdtype = RBTDB_RDATATYPE_EXT(header->type);
|
||||
if (rdtype != dns_rdatatype_nxt &&
|
||||
rdtype != dns_rdatatype_key &&
|
||||
rdtype != dns_rdatatype_cname) {
|
||||
/*
|
||||
* We've found a type that isn't
|
||||
* NXT, KEY, CNAME, or one of their
|
||||
* signatures. Is it active and extant?
|
||||
*/
|
||||
do {
|
||||
if (header->serial <= serial &&
|
||||
!IGNORE(header)) {
|
||||
/*
|
||||
* Is this a "this rdataset
|
||||
* doesn't exist" record?
|
||||
*/
|
||||
if (NONEXISTENT(header))
|
||||
header = NULL;
|
||||
break;
|
||||
} else
|
||||
header = header->down;
|
||||
} while (header != NULL);
|
||||
if (header != NULL)
|
||||
other_data = ISC_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cname && other_data)
|
||||
return (ISC_TRUE);
|
||||
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
||||
rdatasetheader_t *newheader, unsigned int options, isc_boolean_t loading,
|
||||
@@ -3151,10 +3230,6 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
||||
topheader_prev = topheader;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXXRTH Need to check for CNAME and other data.
|
||||
*/
|
||||
|
||||
find_header:
|
||||
/*
|
||||
* If header isn't NULL, we've found the right type. There may be
|
||||
@@ -3189,15 +3264,24 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't merge if a nonexistent rdataset is involved.
|
||||
*/
|
||||
if (merge && (header_nx || newheader_nx))
|
||||
merge = ISC_FALSE;
|
||||
|
||||
/*
|
||||
* XXXRTH We need to turn off merging for rdata types that
|
||||
* cannot be merged, e.g. SOA, CNAME, WKS.
|
||||
* Turn off merging in certain cases.
|
||||
*/
|
||||
if (merge) {
|
||||
if (header_nx || newheader_nx) {
|
||||
/*
|
||||
* Don't merge if a nonexistent rdataset is
|
||||
* involved.
|
||||
*/
|
||||
merge = ISC_FALSE;
|
||||
} else {
|
||||
/*
|
||||
* Do not merge singleton types.
|
||||
*/
|
||||
rdtype = RBTDB_RDATATYPE_BASE(newheader->type);
|
||||
if (dns_rdatatype_issingleton(rdtype))
|
||||
merge = ISC_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If 'merge' is ISC_TRUE, we'll try to create a new rdataset
|
||||
@@ -3302,6 +3386,13 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the node now contains CNAME and other data.
|
||||
*/
|
||||
if (rbtversion != NULL &&
|
||||
cname_and_other_data(rbtnode, rbtversion->serial))
|
||||
return (DNS_R_CNAMEANDOTHER);
|
||||
|
||||
if (addedrdataset != NULL)
|
||||
bind_rdataset(rbtdb, rbtnode, newheader, now, addedrdataset);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: rdataslab.c,v 1.23 2000/10/31 03:21:58 marka Exp $ */
|
||||
/* $Id: rdataslab.c,v 1.24 2000/11/22 00:18:34 halley Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -55,6 +55,8 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
||||
|
||||
nalloc = dns_rdataset_count(rdataset);
|
||||
nitems = nalloc;
|
||||
if (nitems == 0)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
rdatas = isc_mem_get(mctx, nalloc * sizeof(dns_rdata_t));
|
||||
if (rdatas == NULL)
|
||||
@@ -64,44 +66,58 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
||||
* Save all of the rdata members into an array.
|
||||
*/
|
||||
result = dns_rdataset_first(rdataset);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
for (i = 0; i < nalloc; i++) {
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto free_rdatas;
|
||||
for (i = 0; i < nalloc && result == ISC_R_SUCCESS; i++) {
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_rdata_init(&rdatas[i]);
|
||||
dns_rdataset_current(rdataset, &rdatas[i]);
|
||||
result = dns_rdataset_next(rdataset);
|
||||
}
|
||||
INSIST(result == ISC_R_NOMORE);
|
||||
if (result != ISC_R_NOMORE)
|
||||
goto free_rdatas;
|
||||
if (i != nalloc) {
|
||||
/*
|
||||
* Somehow we iterated over fewer rdatas than
|
||||
* dns_rdataset_count() said there were!
|
||||
*/
|
||||
result = ISC_R_FAILURE;
|
||||
goto free_rdatas;
|
||||
}
|
||||
|
||||
qsort(rdatas, nalloc, sizeof(dns_rdata_t), compare_rdata);
|
||||
|
||||
/*
|
||||
* Remove duplicates.
|
||||
* Remove duplicates and compute the total storage required.
|
||||
*
|
||||
* If an rdata is not a duplicate, accumulate the storage size
|
||||
* required for the rdata. We do not store the class, type, etc,
|
||||
* just the rdata, so our overhead is 2 bytes for the number of
|
||||
* records, and 2 for each rdata length, and then the rdata itself.
|
||||
*/
|
||||
for (i = 1; i < nalloc; i++) {
|
||||
if (compare_rdata(&rdatas[i-1], &rdatas[i]) == 0) {
|
||||
rdatas[i-1].data = NULL;
|
||||
rdatas[i-1].length = 0;
|
||||
nitems--;
|
||||
}
|
||||
} else
|
||||
buflen += (2 + rdatas[i-1].length);
|
||||
}
|
||||
/*
|
||||
* Don't forget the last item!
|
||||
*/
|
||||
buflen += (2 + rdatas[i-1].length);
|
||||
|
||||
/*
|
||||
* Run through the rdataset list once, counting up the size
|
||||
* of all the rdata members within it. We do not store the
|
||||
* class, type, etc, just the rdata, so our overhead is 2 bytes
|
||||
* for the number of records, and 2 for each rdata length, and
|
||||
* then the rdata itself.
|
||||
* Check that singleton types are actually singletons.
|
||||
*/
|
||||
for (i = 0; i < nalloc; i++) {
|
||||
if (rdatas[i].data != NULL)
|
||||
buflen += (2 + rdatas[i].length);
|
||||
result = dns_rdataset_next(rdataset);
|
||||
}
|
||||
|
||||
if (result != ISC_R_NOMORE) {
|
||||
isc_mem_put(mctx, rdatas, nalloc * sizeof(dns_rdata_t));
|
||||
return (result);
|
||||
if (nitems > 1 && dns_rdatatype_issingleton(rdataset->type)) {
|
||||
/*
|
||||
* We have a singleton type, but there's more than one
|
||||
* RR in the rdataset.
|
||||
*/
|
||||
result = DNS_R_SINGLETON;
|
||||
goto free_rdatas;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user