summaryrefslogtreecommitdiff
path: root/lib/dns/ncache.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/ncache.c')
-rw-r--r--lib/dns/ncache.c332
1 files changed, 270 insertions, 62 deletions
diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c
index 89106dad7c06..5ee79bfc9ffc 100644
--- a/lib/dns/ncache.c
+++ b/lib/dns/ncache.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ncache.c,v 1.36.18.5 2010/02/26 23:46:36 tbox Exp $ */
+/* $Id: ncache.c,v 1.36.18.8 2010/06/03 23:46:10 tbox Exp $ */
/*! \file */
@@ -30,6 +30,9 @@
#include <dns/rdata.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+
+#define DNS_NCACHE_RDATA 20U
/*
* The format of an ncache rdata is a sequence of one or more records of
@@ -37,6 +40,7 @@
*
* owner name
* type
+ * trust
* rdata count
* rdata length These two occur 'rdata count'
* rdata times.
@@ -100,10 +104,11 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
dns_name_t *name;
dns_ttl_t ttl;
dns_trust_t trust;
- dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_t rdata[DNS_NCACHE_RDATA];
dns_rdataset_t ncrdataset;
dns_rdatalist_t ncrdatalist;
unsigned char data[4096];
+ unsigned int next = 0;
/*
* Convert the authority data from 'message' into a negative cache
@@ -118,7 +123,17 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
*/
/*
- * First, build an ncache rdata in buffer.
+ * Initialize the list.
+ */
+ ncrdatalist.rdclass = dns_db_class(cache);
+ ncrdatalist.type = 0;
+ ncrdatalist.covers = covers;
+ ncrdatalist.ttl = maxttl;
+ ISC_LIST_INIT(ncrdatalist.rdata);
+ ISC_LINK_INIT(&ncrdatalist, link);
+
+ /*
+ * Build an ncache rdatas into buffer.
*/
ttl = maxttl;
trust = 0xffff;
@@ -164,6 +179,8 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
return (ISC_R_NOSPACE);
isc_buffer_putuint16(&buffer,
rdataset->type);
+ isc_buffer_putuint8(&buffer,
+ rdataset->trust);
/*
* Copy the rdataset into the buffer.
*/
@@ -171,6 +188,21 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
&buffer);
if (result != ISC_R_SUCCESS)
return (result);
+
+ if (next >= DNS_NCACHE_RDATA)
+ return (ISC_R_NOSPACE);
+ dns_rdata_init(&rdata[next]);
+ isc_buffer_remainingregion(&buffer, &r);
+ rdata[next].data = r.base;
+ rdata[next].length = r.length;
+ rdata[next].rdclass =
+ ncrdatalist.rdclass;
+ rdata[next].type = 0;
+ rdata[next].flags = 0;
+ ISC_LIST_APPEND(ncrdatalist.rdata,
+ &rdata[next], link);
+ isc_buffer_forward(&buffer, r.length);
+ next++;
}
}
}
@@ -205,10 +237,9 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
* Copy the type and a zero rdata count to the buffer.
*/
isc_buffer_availableregion(&buffer, &r);
- if (r.length < 4)
+ if (r.length < 5)
return (ISC_R_NOSPACE);
- isc_buffer_putuint16(&buffer, 0);
- isc_buffer_putuint16(&buffer, 0);
+ isc_buffer_putuint16(&buffer, 0); /* type */
/*
* RFC2308, section 5, says that negative answers without
* SOAs should not be cached.
@@ -226,27 +257,27 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
trust = dns_trust_authauthority;
} else
trust = dns_trust_additional;
+ isc_buffer_putuint8(&buffer, trust); /* trust */
+ isc_buffer_putuint16(&buffer, 0); /* count */
+
+ /*
+ * Now add it to the cache.
+ */
+ if (next >= DNS_NCACHE_RDATA)
+ return (ISC_R_NOSPACE);
+ dns_rdata_init(&rdata[next]);
+ isc_buffer_remainingregion(&buffer, &r);
+ rdata[next].data = r.base;
+ rdata[next].length = r.length;
+ rdata[next].rdclass = ncrdatalist.rdclass;
+ rdata[next].type = 0;
+ rdata[next].flags = 0;
+ ISC_LIST_APPEND(ncrdatalist.rdata, &rdata[next], link);
}
- /*
- * Now add it to the cache.
- */
INSIST(trust != 0xffff);
- isc_buffer_usedregion(&buffer, &r);
- rdata.data = r.base;
- rdata.length = r.length;
- rdata.rdclass = dns_db_class(cache);
- rdata.type = 0;
- rdata.flags = 0;
-
- ncrdatalist.rdclass = rdata.rdclass;
- ncrdatalist.type = 0;
- ncrdatalist.covers = covers;
- ncrdatalist.ttl = ttl;
- ISC_LIST_INIT(ncrdatalist.rdata);
- ISC_LINK_INIT(&ncrdatalist, link);
- ISC_LIST_APPEND(ncrdatalist.rdata, &rdata, link);
+ ncrdatalist.ttl = ttl;
dns_rdataset_init(&ncrdataset);
RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset)
@@ -281,18 +312,14 @@ dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
REQUIRE(rdataset != NULL);
REQUIRE(rdataset->type == 0);
- result = dns_rdataset_first(rdataset);
- if (result != ISC_R_SUCCESS)
- return (result);
- dns_rdataset_current(rdataset, &rdata);
- INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE);
- isc_buffer_init(&source, rdata.data, rdata.length);
- isc_buffer_add(&source, rdata.length);
-
savedbuffer = *target;
-
count = 0;
- do {
+
+ result = dns_rdataset_first(rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
dns_name_init(&name, NULL);
isc_buffer_remainingregion(&source, &remaining);
dns_name_fromregion(&name, &remaining);
@@ -300,8 +327,9 @@ dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
isc_buffer_forward(&source, name.length);
remaining.length -= name.length;
- INSIST(remaining.length >= 4);
+ INSIST(remaining.length >= 5);
type = isc_buffer_getuint16(&source);
+ isc_buffer_forward(&source, 1);
rcount = isc_buffer_getuint16(&source);
for (i = 0; i < rcount; i++) {
@@ -370,8 +398,12 @@ dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
count++;
}
- isc_buffer_remainingregion(&source, &remaining);
- } while (remaining.length > 0);
+ INSIST(isc_buffer_remaininglength(&source) == 0);
+ result = dns_rdataset_next(rdataset);
+ dns_rdata_reset(&rdata);
+ }
+ if (result != ISC_R_NOMORE)
+ goto rollback;
*countp = count;
@@ -467,6 +499,13 @@ rdataset_count(dns_rdataset_t *rdataset) {
return (count);
}
+static void
+rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
+ unsigned char *raw = rdataset->private3;
+
+ raw[-1] = trust;
+}
+
static dns_rdatasetmethods_t rdataset_methods = {
rdataset_disassociate,
rdataset_first,
@@ -479,8 +518,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
NULL,
NULL,
NULL,
+ rdataset_settrust,
NULL,
- NULL
};
isc_result_t
@@ -493,8 +532,8 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
isc_buffer_t source;
dns_name_t tname;
dns_rdatatype_t ttype;
- unsigned int i, rcount;
- isc_uint16_t length;
+ dns_trust_t trust = dns_trust_none;
+ dns_rdataset_t clone;
REQUIRE(ncacherdataset != NULL);
REQUIRE(ncacherdataset->type == 0);
@@ -502,15 +541,13 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
REQUIRE(!dns_rdataset_isassociated(rdataset));
REQUIRE(type != dns_rdatatype_rrsig);
- result = dns_rdataset_first(ncacherdataset);
- if (result != ISC_R_SUCCESS)
- return (result);
- dns_rdataset_current(ncacherdataset, &rdata);
- INSIST(dns_rdataset_next(ncacherdataset) == ISC_R_NOMORE);
- isc_buffer_init(&source, rdata.data, rdata.length);
- isc_buffer_add(&source, rdata.length);
-
- do {
+ dns_rdataset_init(&clone);
+ dns_rdataset_clone(ncacherdataset, &clone);
+ result = dns_rdataset_first(&clone);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&clone, &rdata);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
dns_name_init(&tname, NULL);
isc_buffer_remainingregion(&source, &remaining);
dns_name_fromregion(&tname, &remaining);
@@ -518,35 +555,133 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
isc_buffer_forward(&source, tname.length);
remaining.length -= tname.length;
- INSIST(remaining.length >= 4);
+ INSIST(remaining.length >= 3);
ttype = isc_buffer_getuint16(&source);
if (ttype == type && dns_name_equal(&tname, name)) {
+ trust = isc_buffer_getuint8(&source);
+ INSIST(trust <= dns_trust_ultimate);
isc_buffer_remainingregion(&source, &remaining);
break;
}
+ result = dns_rdataset_next(&clone);
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&clone);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_NOTFOUND);
+ if (result != ISC_R_SUCCESS)
+ return (result);
- rcount = isc_buffer_getuint16(&source);
- for (i = 0; i < rcount; i++) {
- isc_buffer_remainingregion(&source, &remaining);
- INSIST(remaining.length >= 2);
- length = isc_buffer_getuint16(&source);
+ INSIST(remaining.length != 0);
+
+ rdataset->methods = &rdataset_methods;
+ rdataset->rdclass = ncacherdataset->rdclass;
+ rdataset->type = type;
+ rdataset->covers = 0;
+ rdataset->ttl = ncacherdataset->ttl;
+ rdataset->trust = trust;
+ rdataset->private1 = NULL;
+ rdataset->private2 = NULL;
+
+ rdataset->private3 = remaining.base;
+
+ /*
+ * Reset iterator state.
+ */
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+ rdataset->private6 = NULL;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
+ dns_rdatatype_t covers, dns_rdataset_t *rdataset)
+{
+ dns_name_t tname;
+ dns_rdata_rrsig_t rrsig;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t clone;
+ dns_rdatatype_t type;
+ dns_trust_t trust = dns_trust_none;
+ isc_buffer_t source;
+ isc_region_t remaining, sigregion;
+ isc_result_t result;
+ unsigned char *raw;
+ unsigned int count;
+
+ REQUIRE(ncacherdataset != NULL);
+ REQUIRE(ncacherdataset->type == 0);
+ REQUIRE(name != NULL);
+ REQUIRE(!dns_rdataset_isassociated(rdataset));
+
+ dns_rdataset_init(&clone);
+ dns_rdataset_clone(ncacherdataset, &clone);
+ result = dns_rdataset_first(&clone);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&clone, &rdata);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
+ dns_name_init(&tname, NULL);
+ isc_buffer_remainingregion(&source, &remaining);
+ dns_name_fromregion(&tname, &remaining);
+ INSIST(remaining.length >= tname.length);
+ isc_buffer_forward(&source, tname.length);
+ remaining.length -= tname.length;
+ remaining.base += tname.length;
+
+ INSIST(remaining.length >= 2);
+ type = isc_buffer_getuint16(&source);
+ remaining.length -= 2;
+ remaining.base += 2;
+
+ if (type != dns_rdatatype_rrsig ||
+ !dns_name_equal(&tname, name)) {
+ result = dns_rdataset_next(&clone);
+ dns_rdata_reset(&rdata);
+ continue;
+ }
+
+ INSIST(remaining.length >= 1);
+ trust = isc_buffer_getuint8(&source);
+ INSIST(trust <= dns_trust_ultimate);
+ remaining.length -= 1;
+ remaining.base += 1;
+
+ raw = remaining.base;
+ count = raw[0] * 256 + raw[1];
+ INSIST(count > 0);
+ raw += 2;
+ sigregion.length = raw[0] * 256 + raw[1];
+ raw += 2;
+ sigregion.base = raw;
+ dns_rdata_reset(&rdata);
+ dns_rdata_fromregion(&rdata, rdataset->rdclass,
+ dns_rdatatype_rrsig, &sigregion);
+ (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
+ if (rrsig.covered == covers) {
isc_buffer_remainingregion(&source, &remaining);
- INSIST(remaining.length >= length);
- isc_buffer_forward(&source, length);
+ break;
}
- isc_buffer_remainingregion(&source, &remaining);
- } while (remaining.length > 0);
- if (remaining.length == 0)
+ result = dns_rdataset_next(&clone);
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&clone);
+ if (result == ISC_R_NOMORE)
return (ISC_R_NOTFOUND);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ INSIST(remaining.length != 0);
rdataset->methods = &rdataset_methods;
rdataset->rdclass = ncacherdataset->rdclass;
- rdataset->type = type;
- rdataset->covers = 0;
+ rdataset->type = dns_rdatatype_rrsig;
+ rdataset->covers = covers;
rdataset->ttl = ncacherdataset->ttl;
- rdataset->trust = ncacherdataset->trust;
+ rdataset->trust = trust;
rdataset->private1 = NULL;
rdataset->private2 = NULL;
@@ -557,5 +692,78 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
*/
rdataset->privateuint4 = 0;
rdataset->private5 = NULL;
+ rdataset->private6 = NULL;
return (ISC_R_SUCCESS);
}
+
+void
+dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
+ dns_rdataset_t *rdataset)
+{
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_trust_t trust;
+ isc_region_t remaining, sigregion;
+ isc_buffer_t source;
+ dns_name_t tname;
+ dns_rdatatype_t type;
+ unsigned int count;
+ dns_rdata_rrsig_t rrsig;
+ unsigned char *raw;
+
+ REQUIRE(ncacherdataset != NULL);
+ REQUIRE(ncacherdataset->type == 0);
+ REQUIRE(found != NULL);
+ REQUIRE(!dns_rdataset_isassociated(rdataset));
+
+ dns_rdataset_current(ncacherdataset, &rdata);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
+
+ dns_name_init(&tname, NULL);
+ isc_buffer_remainingregion(&source, &remaining);
+ dns_name_fromregion(found, &remaining);
+ INSIST(remaining.length >= found->length);
+ isc_buffer_forward(&source, found->length);
+ remaining.length -= found->length;
+
+ INSIST(remaining.length >= 5);
+ type = isc_buffer_getuint16(&source);
+ trust = isc_buffer_getuint8(&source);
+ INSIST(trust <= dns_trust_ultimate);
+ isc_buffer_remainingregion(&source, &remaining);
+
+ rdataset->methods = &rdataset_methods;
+ rdataset->rdclass = ncacherdataset->rdclass;
+ rdataset->type = type;
+ if (type == dns_rdatatype_rrsig) {
+ /*
+ * Extract covers from RRSIG.
+ */
+ raw = remaining.base;
+ count = raw[0] * 256 + raw[1];
+ INSIST(count > 0);
+ raw += 2;
+ sigregion.length = raw[0] * 256 + raw[1];
+ raw += 2;
+ sigregion.base = raw;
+ dns_rdata_reset(&rdata);
+ dns_rdata_fromregion(&rdata, rdataset->rdclass,
+ rdataset->type, &sigregion);
+ (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
+ rdataset->covers = rrsig.covered;
+ } else
+ rdataset->covers = 0;
+ rdataset->ttl = ncacherdataset->ttl;
+ rdataset->trust = trust;
+ rdataset->private1 = NULL;
+ rdataset->private2 = NULL;
+
+ rdataset->private3 = remaining.base;
+
+ /*
+ * Reset iterator state.
+ */
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+ rdataset->private6 = NULL;
+}