diff --git a/lib/dns/include/dns/rdataslab.h b/lib/dns/include/dns/rdataslab.h index 64a20cc29e..82f2a426b1 100644 --- a/lib/dns/include/dns/rdataslab.h +++ b/lib/dns/include/dns/rdataslab.h @@ -173,11 +173,17 @@ extern dns_rdatasetmethods_t dns_rdataslab_rdatasetmethods; isc_result_t dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, - isc_region_t *region, unsigned int reservelen, - uint32_t limit); + isc_region_t *region, uint32_t limit); +isc_result_t +dns_rdataslab_raw_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, + isc_region_t *region, uint32_t limit); /*%< - * Slabify a rdataset. The slab area will be allocated and returned - * in 'region'. + * Allocate space for a slab to hold the data in rdataset, and copy the + * data into it. The resulting slab will be returned in 'region'. + * + * The dns_rdataslab_raw_fromrdataset() function allocates and fills only + * the memory needed for a raw slab. dns_rdataslab_fromrdataset() also + * allocates space for a dns_slabheader object. * * Requires: *\li 'rdataset' is valid. diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index 8428451a21..b25bf45b6e 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -3090,12 +3090,13 @@ addnoqname(isc_mem_t *mctx, dns_slabheader_t *newheader, uint32_t maxrrperset, result = dns_rdataset_getnoqname(rdataset, &name, &neg, &negsig); RUNTIME_CHECK(result == ISC_R_SUCCESS); - result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0, maxrrperset); + result = dns_rdataslab_raw_fromrdataset(&neg, mctx, &r1, maxrrperset); if (result != ISC_R_SUCCESS) { goto cleanup; } - result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0, maxrrperset); + result = dns_rdataslab_raw_fromrdataset(&negsig, mctx, &r2, + maxrrperset); if (result != ISC_R_SUCCESS) { goto cleanup; } @@ -3129,12 +3130,13 @@ addclosest(isc_mem_t *mctx, dns_slabheader_t *newheader, uint32_t maxrrperset, result = dns_rdataset_getclosest(rdataset, &name, &neg, &negsig); RUNTIME_CHECK(result == ISC_R_SUCCESS); - result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0, maxrrperset); + result = dns_rdataslab_raw_fromrdataset(&neg, mctx, &r1, maxrrperset); if (result != ISC_R_SUCCESS) { goto cleanup; } - result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0, maxrrperset); + result = dns_rdataslab_raw_fromrdataset(&negsig, mctx, &r2, + maxrrperset); if (result != ISC_R_SUCCESS) { goto cleanup; } @@ -3184,8 +3186,7 @@ qpcache_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, REQUIRE(version == NULL); result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx, - ®ion, sizeof(dns_slabheader_t), - qpdb->maxrrperset); + ®ion, qpdb->maxrrperset); if (result != ISC_R_SUCCESS) { if (result == DNS_R_TOOMANYRECORDS) { dns__db_logtoomanyrecords((dns_db_t *)qpdb, diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index 067fc8711e..db5f6a0727 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -2241,8 +2241,7 @@ loading_addrdataset(void *arg, const dns_name_t *name, loading_addnode(loadctx, name, rdataset->type, rdataset->covers, &node); result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx, - ®ion, sizeof(dns_slabheader_t), - qpdb->maxrrperset); + ®ion, qpdb->maxrrperset); if (result != ISC_R_SUCCESS) { if (result == DNS_R_TOOMANYRECORDS) { dns__db_logtoomanyrecords((dns_db_t *)qpdb, name, @@ -4724,8 +4723,7 @@ qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, rdataset->covers != dns_rdatatype_nsec3)); result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx, - ®ion, sizeof(dns_slabheader_t), - qpdb->maxrrperset); + ®ion, qpdb->maxrrperset); if (result != ISC_R_SUCCESS) { if (result == DNS_R_TOOMANYRECORDS) { dns__db_logtoomanyrecords((dns_db_t *)qpdb, &node->name, @@ -4854,8 +4852,7 @@ qpzone_subtractrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_name_copy(&node->name, nodename); result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx, - ®ion, sizeof(dns_slabheader_t), - 0); + ®ion, 0); if (result != ISC_R_SUCCESS) { return result; } diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c index 42fe27fcb9..1430591405 100644 --- a/lib/dns/rdataslab.c +++ b/lib/dns/rdataslab.c @@ -47,7 +47,7 @@ * The rdataslab structure allows iteration to occur in both load order * and DNSSEC order. The structure is as follows: * - * header (reservelen bytes) + * header (dns_slabheader_t) * record count (2 bytes) * offset table (4 x record count bytes in load order) * data records @@ -56,6 +56,8 @@ * meta data (1 byte for RRSIG's) * data (data length bytes) * + * A "raw" rdataslab is the same but without the header. + * * DNSSEC order traversal is performed by walking the data records. * * The order is stored with record to allow for efficient reconstruction @@ -118,10 +120,9 @@ compare_rdata(const void *p1, const void *p2) { return dns_rdata_compare(p1, p2); } -isc_result_t -dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, - isc_region_t *region, unsigned int reservelen, - uint32_t maxrrperset) { +static isc_result_t +makeslab(dns_rdataset_t *rdataset, isc_mem_t *mctx, isc_region_t *region, + uint32_t maxrrperset, bool raw) { /* * Use &removed as a sentinel pointer for duplicate * rdata as rdata.data == NULL is valid. @@ -129,6 +130,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, static unsigned char removed; dns_rdata_t *rdata = NULL; unsigned char *rawbuf = NULL; + unsigned int headerlen = raw ? 0 : sizeof(dns_slabheader_t); unsigned int buflen; isc_result_t result; unsigned int nitems; @@ -136,7 +138,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, unsigned int length; unsigned int i; - buflen = reservelen + 2; + buflen = headerlen + 2; nitems = dns_rdataset_count(rdataset); @@ -151,7 +153,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, rawbuf = isc_mem_get(mctx, buflen); region->base = rawbuf; region->length = buflen; - rawbuf += reservelen; + rawbuf += headerlen; *rawbuf++ = 0; *rawbuf = 0; return ISC_R_SUCCESS; @@ -231,6 +233,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, * Don't forget the last item! */ buflen += (2 + rdata[i - 1].length); + /* * Provide space to store the per RR meta data. */ @@ -259,7 +262,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, region->base = rawbuf; region->length = buflen; - rawbuf += reservelen; + rawbuf += headerlen; put_uint16(rawbuf, nitems); @@ -272,6 +275,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, length++; } INSIST(length <= 0xffff); + put_uint16(rawbuf, length); /* @@ -295,6 +299,18 @@ free_rdatas: return result; } +isc_result_t +dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, + isc_region_t *region, uint32_t maxrrperset) { + return makeslab(rdataset, mctx, region, maxrrperset, false); +} + +isc_result_t +dns_rdataslab_raw_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, + isc_region_t *region, uint32_t maxrrperset) { + return makeslab(rdataset, mctx, region, maxrrperset, true); +} + unsigned int dns_rdataslab_sizeraw(unsigned char *slab) { REQUIRE(slab != NULL);