mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-02 15:45:25 +00:00
Implement rrset ordering. Default is cyclic.
If the rdataset iterator failed unexpectedly while rendering, we failed to rollback.
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <isc/assertions.h>
|
#include <isc/assertions.h>
|
||||||
@@ -251,6 +252,11 @@ dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
|
|||||||
(rdataset->methods->current)(rdataset, rdata);
|
(rdataset->methods->current)(rdataset, rdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_SHUFFLE 32
|
||||||
|
#define WANT_FIXED(r) (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0)
|
||||||
|
#define WANT_RANDOM(r) (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0)
|
||||||
|
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_rdataset_towire(dns_rdataset_t *rdataset,
|
dns_rdataset_towire(dns_rdataset_t *rdataset,
|
||||||
dns_name_t *owner_name,
|
dns_name_t *owner_name,
|
||||||
@@ -261,10 +267,12 @@ dns_rdataset_towire(dns_rdataset_t *rdataset,
|
|||||||
dns_rdata_t rdata;
|
dns_rdata_t rdata;
|
||||||
isc_region_t r;
|
isc_region_t r;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
unsigned int count;
|
unsigned int i, count, tcount, choice;
|
||||||
isc_buffer_t savedbuffer, rdlen;
|
isc_buffer_t savedbuffer, rdlen;
|
||||||
unsigned int headlen;
|
unsigned int headlen;
|
||||||
isc_boolean_t question = ISC_FALSE;
|
isc_boolean_t question = ISC_FALSE;
|
||||||
|
isc_boolean_t shuffle = ISC_FALSE;
|
||||||
|
dns_rdata_t shuffled[MAX_SHUFFLE];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert 'rdataset' to wire format, compressing names as specified
|
* Convert 'rdataset' to wire format, compressing names as specified
|
||||||
@@ -274,8 +282,10 @@ dns_rdataset_towire(dns_rdataset_t *rdataset,
|
|||||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||||
REQUIRE(countp != NULL);
|
REQUIRE(countp != NULL);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
|
if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
|
||||||
question = ISC_TRUE;
|
question = ISC_TRUE;
|
||||||
|
count = 1;
|
||||||
result = dns_rdataset_first(rdataset);
|
result = dns_rdataset_first(rdataset);
|
||||||
INSIST(result == DNS_R_NOMORE);
|
INSIST(result == DNS_R_NOMORE);
|
||||||
} else if (rdataset->type == 0) {
|
} else if (rdataset->type == 0) {
|
||||||
@@ -284,6 +294,7 @@ dns_rdataset_towire(dns_rdataset_t *rdataset,
|
|||||||
*/
|
*/
|
||||||
return (dns_ncache_towire(rdataset, cctx, target, countp));
|
return (dns_ncache_towire(rdataset, cctx, target, countp));
|
||||||
} else {
|
} else {
|
||||||
|
count = (rdataset->methods->count)(rdataset);
|
||||||
result = dns_rdataset_first(rdataset);
|
result = dns_rdataset_first(rdataset);
|
||||||
if (result == DNS_R_NOMORE)
|
if (result == DNS_R_NOMORE)
|
||||||
return (DNS_R_SUCCESS);
|
return (DNS_R_SUCCESS);
|
||||||
@@ -291,9 +302,60 @@ dns_rdataset_towire(dns_rdataset_t *rdataset,
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
savedbuffer = *target;
|
choice = 0;
|
||||||
|
if (!question && count > 1 && !WANT_FIXED(rdataset)) {
|
||||||
|
/*
|
||||||
|
* We'll only shuffle if we've got enough slots in our
|
||||||
|
* deck.
|
||||||
|
*
|
||||||
|
* There's no point to shuffling SIGs.
|
||||||
|
*/
|
||||||
|
if (count <= MAX_SHUFFLE &&
|
||||||
|
rdataset->type != dns_rdatatype_sig) {
|
||||||
|
shuffle = ISC_TRUE;
|
||||||
|
/*
|
||||||
|
* First we get handles to all of the rdata.
|
||||||
|
*/
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
INSIST(i < count);
|
||||||
|
dns_rdataset_current(rdataset, &shuffled[i]);
|
||||||
|
i++;
|
||||||
|
result = dns_rdataset_next(rdataset);
|
||||||
|
} while (result == ISC_R_SUCCESS);
|
||||||
|
if (result != DNS_R_NOMORE)
|
||||||
|
return (result);
|
||||||
|
INSIST(i == count);
|
||||||
|
/*
|
||||||
|
* Now we shuffle.
|
||||||
|
*/
|
||||||
|
if (WANT_RANDOM(rdataset)) {
|
||||||
|
/*
|
||||||
|
* "Random" order.
|
||||||
|
*/
|
||||||
|
tcount = count;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
choice = (((unsigned int)rand()) >> 3)
|
||||||
|
% tcount;
|
||||||
|
rdata = shuffled[i];
|
||||||
|
shuffled[i] = shuffled[i + choice];
|
||||||
|
shuffled[i + choice] = rdata;
|
||||||
|
tcount--;
|
||||||
|
}
|
||||||
|
choice = 0;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* "Cyclic" order.
|
||||||
|
*/
|
||||||
|
choice = (((unsigned int)rand()) >> 3) % count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
savedbuffer = *target;
|
||||||
|
i = choice;
|
||||||
|
tcount = 0;
|
||||||
|
|
||||||
count = 0;
|
|
||||||
do {
|
do {
|
||||||
/*
|
/*
|
||||||
* copy out the name, type, class, ttl.
|
* copy out the name, type, class, ttl.
|
||||||
@@ -328,6 +390,9 @@ dns_rdataset_towire(dns_rdataset_t *rdataset,
|
|||||||
/*
|
/*
|
||||||
* copy out the rdata
|
* copy out the rdata
|
||||||
*/
|
*/
|
||||||
|
if (shuffle)
|
||||||
|
rdata = shuffled[i];
|
||||||
|
else
|
||||||
dns_rdataset_current(rdataset, &rdata);
|
dns_rdataset_current(rdataset, &rdata);
|
||||||
result = dns_compress_localinit(cctx, owner_name,
|
result = dns_compress_localinit(cctx, owner_name,
|
||||||
target);
|
target);
|
||||||
@@ -344,13 +409,24 @@ dns_rdataset_towire(dns_rdataset_t *rdataset,
|
|||||||
rdlen.used - 2));
|
rdlen.used - 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
if (shuffle) {
|
||||||
|
i++;
|
||||||
|
/*
|
||||||
|
* Wrap around in case we're doing cyclic ordering.
|
||||||
|
*/
|
||||||
|
if (i == count)
|
||||||
|
i = 0;
|
||||||
|
tcount++;
|
||||||
|
if (tcount == count)
|
||||||
|
result = DNS_R_NOMORE;
|
||||||
|
else
|
||||||
|
result = ISC_R_SUCCESS;
|
||||||
|
} else
|
||||||
result = dns_rdataset_next(rdataset);
|
result = dns_rdataset_next(rdataset);
|
||||||
} while (result == DNS_R_SUCCESS);
|
} while (result == DNS_R_SUCCESS);
|
||||||
|
|
||||||
if (result != DNS_R_NOMORE)
|
if (result != DNS_R_NOMORE)
|
||||||
return (result);
|
goto rollback;
|
||||||
|
|
||||||
*countp += count;
|
*countp += count;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user