2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-01 06:55:30 +00:00

856. [func] Allow partial rdatasets to be returned in answer and

authority sections to help non-TCP capable clients
                        recover from truncation.  [RT #1301]
This commit is contained in:
Mark Andrews
2001-06-05 09:02:16 +00:00
parent 7e93abafe6
commit 03f91269f5
6 changed files with 108 additions and 19 deletions

View File

@@ -1,3 +1,7 @@
856. [func] Allow partial rdatasets to be returned in answer and
authority sections to help non-TCP capable clients
recover from truncation. [RT #1301]
855. [bug] Stop spurious "using RFC 1035 TTL semantics" warnings. 855. [bug] Stop spurious "using RFC 1035 TTL semantics" warnings.
854. [bug] The config parser didn't properly handle config 854. [bug] The config parser didn't properly handle config

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: client.c,v 1.170 2001/06/04 19:32:52 tale Exp $ */ /* $Id: client.c,v 1.171 2001/06/05 09:02:10 marka Exp $ */
#include <config.h> #include <config.h>
@@ -865,7 +865,8 @@ ns_client_send(ns_client_t *client) {
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto done; goto done;
result = dns_message_rendersection(client->message, result = dns_message_rendersection(client->message,
DNS_SECTION_ANSWER, 0); DNS_SECTION_ANSWER,
DNS_MESSAGERENDER_PARTIAL);
if (result == ISC_R_NOSPACE) { if (result == ISC_R_NOSPACE) {
client->message->flags |= DNS_MESSAGEFLAG_TC; client->message->flags |= DNS_MESSAGEFLAG_TC;
goto renderend; goto renderend;
@@ -873,7 +874,8 @@ ns_client_send(ns_client_t *client) {
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto done; goto done;
result = dns_message_rendersection(client->message, result = dns_message_rendersection(client->message,
DNS_SECTION_AUTHORITY, 0); DNS_SECTION_AUTHORITY,
DNS_MESSAGERENDER_PARTIAL);
if (result == ISC_R_NOSPACE) { if (result == ISC_R_NOSPACE) {
client->message->flags |= DNS_MESSAGEFLAG_TC; client->message->flags |= DNS_MESSAGEFLAG_TC;
goto renderend; goto renderend;

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: message.h,v 1.97 2001/03/28 02:42:56 bwelling Exp $ */ /* $Id: message.h,v 1.98 2001/06/05 09:02:14 marka Exp $ */
#ifndef DNS_MESSAGE_H #ifndef DNS_MESSAGE_H
#define DNS_MESSAGE_H 1 #define DNS_MESSAGE_H 1
@@ -157,6 +157,7 @@ typedef int dns_messagetextflag_t;
* Control behavior of rendering * Control behavior of rendering
*/ */
#define DNS_MESSAGERENDER_ORDERED 0x0001 /* don't change order */ #define DNS_MESSAGERENDER_ORDERED 0x0001 /* don't change order */
#define DNS_MESSAGERENDER_PARTIAL 0x0002 /* allow a partial rdataset */
typedef struct dns_msgblock dns_msgblock_t; typedef struct dns_msgblock dns_msgblock_t;

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: rdataset.h,v 1.39 2001/03/28 00:22:16 gson Exp $ */ /* $Id: rdataset.h,v 1.40 2001/06/05 09:02:16 marka Exp $ */
#ifndef DNS_RDATASET_H #ifndef DNS_RDATASET_H
#define DNS_RDATASET_H 1 #define DNS_RDATASET_H 1
@@ -355,6 +355,34 @@ dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
* that order_arg is NULL if and only if order is NULL. * that order_arg is NULL if and only if order is NULL.
*/ */
isc_result_t
dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
dns_name_t *owner_name,
dns_compress_t *cctx,
isc_buffer_t *target,
dns_rdatasetorderfunc_t order,
void *order_arg,
unsigned int *countp,
void **state);
/*
* Like dns_rdataset_towiresorted() except that a partial rdataset
* may be written.
*
* Requires:
* All the requirements of dns_rdataset_towiresorted().
* If 'state' is non NULL then the current position in the
* rdataset will be remembered if the rdataset in not
* completely written and should be passed on on subsequent
* calls (NOT CURRENTLY IMPLEMENTED).
*
* Returns:
* ISC_R_SUCCESS if all of the records were written.
* ISC_R_NOSPACE if unable to fit in all of the records. *countp
* will be updated to reflect the number of records
* written.
*/
isc_result_t isc_result_t
dns_rdataset_additionaldata(dns_rdataset_t *rdataset, dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
dns_additionaldatafunc_t add, void *arg); dns_additionaldatafunc_t add, void *arg);

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: message.c,v 1.190 2001/04/19 18:28:35 bwelling Exp $ */ /* $Id: message.c,v 1.191 2001/06/05 09:02:11 marka Exp $ */
/*** /***
*** Imports *** Imports
@@ -1723,6 +1723,7 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
isc_result_t result; isc_result_t result;
isc_buffer_t st; /* for rollbacks */ isc_buffer_t st; /* for rollbacks */
int pass; int pass;
isc_boolean_t partial = ISC_FALSE;
REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(DNS_MESSAGE_VALID(msg));
REQUIRE(msg->buffer != NULL); REQUIRE(msg->buffer != NULL);
@@ -1742,6 +1743,8 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
msg->buffer->length -= msg->reserved; msg->buffer->length -= msg->reserved;
total = 0; total = 0;
if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0)
partial = ISC_TRUE;
do { do {
name = ISC_LIST_HEAD(*section); name = ISC_LIST_HEAD(*section);
@@ -1771,7 +1774,19 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
st = *(msg->buffer); st = *(msg->buffer);
count = 0; count = 0;
result = dns_rdataset_towiresorted(rdataset, if (partial)
result = dns_rdataset_towirepartial(
rdataset,
name,
msg->cctx,
msg->buffer,
msg->order,
msg->order_arg,
&count,
NULL);
else
result = dns_rdataset_towiresorted(
rdataset,
name, name,
msg->cctx, msg->cctx,
msg->buffer, msg->buffer,
@@ -1794,6 +1809,11 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
* somewhere (probably in the message struct) * somewhere (probably in the message struct)
* to indicate where to continue from. * to indicate where to continue from.
*/ */
if (partial && result == ISC_R_NOSPACE) {
msg->buffer->length += msg->reserved;
msg->counts[sectionid] += total;
return (result);
}
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
INSIST(st.used < 65536); INSIST(st.used < 65536);
dns_compress_rollback(msg->cctx, dns_compress_rollback(msg->cctx,

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: rdataset.c,v 1.55 2001/01/09 21:51:23 bwelling Exp $ */ /* $Id: rdataset.c,v 1.56 2001/06/05 09:02:13 marka Exp $ */
#include <config.h> #include <config.h>
@@ -269,19 +269,17 @@ towire_compare(const void *av, const void *bv) {
return (a->key - b->key); return (a->key - b->key);
} }
isc_result_t static isc_result_t
dns_rdataset_towiresorted(dns_rdataset_t *rdataset, towiresorted(dns_rdataset_t *rdataset, dns_name_t *owner_name,
dns_name_t *owner_name, dns_compress_t *cctx, isc_buffer_t *target,
dns_compress_t *cctx, dns_rdatasetorderfunc_t order, void *order_arg,
isc_buffer_t *target, isc_boolean_t partial, unsigned int *countp,
dns_rdatasetorderfunc_t order, void **state)
void *order_arg,
unsigned int *countp)
{ {
dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_t rdata = DNS_RDATA_INIT;
isc_region_t r; isc_region_t r;
isc_result_t result; isc_result_t result;
unsigned int i, count; unsigned int i, count, added;
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;
@@ -289,6 +287,8 @@ dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
dns_rdata_t shuffled[MAX_SHUFFLE]; dns_rdata_t shuffled[MAX_SHUFFLE];
struct towire_sort sorted[MAX_SHUFFLE]; struct towire_sort sorted[MAX_SHUFFLE];
UNUSED(state);
/* /*
* Convert 'rdataset' to wire format, compressing names as specified * Convert 'rdataset' to wire format, compressing names as specified
* in cctx, and storing the result in 'target'. * in cctx, and storing the result in 'target'.
@@ -376,6 +376,7 @@ dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
savedbuffer = *target; savedbuffer = *target;
i = 0; i = 0;
added = 0;
do { do {
/* /*
@@ -422,6 +423,7 @@ dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
isc_buffer_putuint16(&rdlen, isc_buffer_putuint16(&rdlen,
(isc_uint16_t)(target->used - (isc_uint16_t)(target->used -
rdlen.used - 2)); rdlen.used - 2));
added++;
} }
if (shuffle) { if (shuffle) {
@@ -443,6 +445,10 @@ dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
rollback: rollback:
if (partial && result == ISC_R_NOSPACE) {
*countp += added;
return (result);
}
INSIST(savedbuffer.used < 65536); INSIST(savedbuffer.used < 65536);
dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used); dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
*countp = 0; *countp = 0;
@@ -451,6 +457,34 @@ dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
return (result); return (result);
} }
isc_result_t
dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
dns_name_t *owner_name,
dns_compress_t *cctx,
isc_buffer_t *target,
dns_rdatasetorderfunc_t order,
void *order_arg,
unsigned int *countp)
{
return (towiresorted(rdataset, owner_name, cctx, target,
order, order_arg, ISC_FALSE, countp, NULL));
}
isc_result_t
dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
dns_name_t *owner_name,
dns_compress_t *cctx,
isc_buffer_t *target,
dns_rdatasetorderfunc_t order,
void *order_arg,
unsigned int *countp,
void **state)
{
REQUIRE(state == NULL); /* XXX remove when implemented */
return (towiresorted(rdataset, owner_name, cctx, target,
order, order_arg, ISC_TRUE, countp, state));
}
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,
@@ -458,8 +492,8 @@ dns_rdataset_towire(dns_rdataset_t *rdataset,
isc_buffer_t *target, isc_buffer_t *target,
unsigned int *countp) unsigned int *countp)
{ {
return (dns_rdataset_towiresorted(rdataset, owner_name, cctx, target, return (towiresorted(rdataset, owner_name, cctx, target,
NULL, NULL, countp)); NULL, NULL, ISC_FALSE, countp, NULL));
} }
isc_result_t isc_result_t