Commit 383665e4 authored by Bob Halley's avatar Bob Halley
Browse files

Do not allow rdatasets of singleton type to have more than one rdata.

Check for CNAME and other data.
[RT #154] [RT #279]
parent 15af30df
571. [bug] It was possible to create an rdataset of singleton
type which had more than one rdata. [RT #154]
[RT #279]
570. [bug] rbtdb.c allowed zones containing nodes which had
both a CNAME and "other data". [RT #154]
569. [func] The DNSSEC AD bit will not be set on queries which
have not requested a DNSSEC response.
......
......@@ -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);
}
/*
* 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.
* Don't forget the last item!
*/
for (i = 0; i < nalloc; i++) {
if (rdatas[i].data != NULL)
buflen += (2 + rdatas[i].length);
result = dns_rdataset_next(rdataset);
}
buflen += (2 + rdatas[i-1].length);
if (result != ISC_R_NOMORE) {
isc_mem_put(mctx, rdatas, nalloc * sizeof(dns_rdata_t));
return (result);
/*
* Check that singleton types are actually singletons.
*/
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;
}
/*
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment