From 55f3daa4ea84859f9753089831a950a4fd9678c3 Mon Sep 17 00:00:00 2001 From: Brian Wellington Date: Tue, 13 Feb 2001 01:02:59 +0000 Subject: [PATCH] When parsing a message, add an offsets table to each name. Also allow callers rendering a message to get temporary offsets tables to attach to names added to the message. --- lib/dns/include/dns/message.h | 27 +++++++++-- lib/dns/message.c | 88 +++++++++++++++++++++++++++++++---- 2 files changed, 102 insertions(+), 13 deletions(-) diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 5fce936306..2b4bf54536 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: message.h,v 1.90 2001/02/02 22:05:04 gson Exp $ */ +/* $Id: message.h,v 1.91 2001/02/13 01:02:59 bwelling Exp $ */ #ifndef DNS_MESSAGE_H #define DNS_MESSAGE_H 1 @@ -59,11 +59,12 @@ * * The same applies to rdatasets. * - * On the other hand, rdatalists and rdatas allocated using + * On the other hand, offsets, rdatalists and rdatas allocated using * dns_message_gettemp*() will always be freed automatically * when the message is reset or destroyed; calling dns_message_puttemp*() - * on these is optional and serves only to enable the item to be reused - * multiple times during the lifetime of the message. + * on rdatalists and rdatas is optional and serves only to enable the item + * to be reused multiple times during the lifetime of the message; offsets + * cannot be reused. * * Buffers allocated using isc_buffer_allocate() can be automatically freed * as well by giving the buffer to the message using dns_message_takebuffer(). @@ -206,6 +207,7 @@ struct dns_message { ISC_LIST(dns_msgblock_t) rdatas; ISC_LIST(dns_msgblock_t) rdatalists; + ISC_LIST(dns_msgblock_t) offsets; ISC_LIST(dns_rdata_t) freerdata; ISC_LIST(dns_rdatalist_t) freerdatalist; @@ -745,6 +747,23 @@ dns_message_gettempname(dns_message_t *msg, dns_name_t **item); * ISC_R_NOMEMORY -- No item can be allocated. */ +isc_result_t +dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item); +/* + * Return an offsets array that can be used for any temporary purpose, + * such as attaching to a temporary name. The offsets will be freed + * when the message is destroyed or reset. + * + * Requires: + * msg be a valid message + * + * item != NULL && *item == NULL + * + * Returns: + * ISC_R_SUCCESS -- All is well. + * ISC_R_NOMEMORY -- No item can be allocated. + */ + isc_result_t dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item); /* diff --git a/lib/dns/message.c b/lib/dns/message.c index f5955650a5..00b3aa9bc1 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: message.c,v 1.174 2001/01/27 02:28:33 bwelling Exp $ */ +/* $Id: message.c,v 1.175 2001/02/13 01:02:57 bwelling Exp $ */ /*** *** Imports @@ -70,6 +70,7 @@ */ #define SCRATCHPAD_SIZE 512 #define NAME_COUNT 8 +#define OFFSET_COUNT NAME_COUNT #define RDATA_COUNT 8 #define RDATALIST_COUNT 8 #define RDATASET_COUNT RDATALIST_COUNT @@ -316,6 +317,28 @@ newrdatalist(dns_message_t *msg) { return (rdatalist); } +static inline dns_offsets_t * +newoffsets(dns_message_t *msg) { + dns_msgblock_t *msgblock; + dns_offsets_t *offsets; + + msgblock = ISC_LIST_TAIL(msg->offsets); + offsets = msgblock_get(msgblock, dns_offsets_t); + if (offsets == NULL) { + msgblock = msgblock_allocate(msg->mctx, + sizeof(dns_offsets_t), + OFFSET_COUNT); + if (msgblock == NULL) + return (NULL); + + ISC_LIST_APPEND(msg->offsets, msgblock, link); + + offsets = msgblock_get(msgblock, dns_offsets_t); + } + + return (offsets); +} + static inline void msginitheader(dns_message_t *m) { m->id = 0; @@ -552,6 +575,19 @@ msgreset(dns_message_t *msg, isc_boolean_t everything) { msgblock = next_msgblock; } + msgblock = ISC_LIST_HEAD(msg->offsets); + INSIST(msgblock != NULL); + if (!everything) { + msgblock_reset(msgblock); + msgblock = ISC_LIST_NEXT(msgblock, link); + } + while (msgblock != NULL) { + next_msgblock = ISC_LIST_NEXT(msgblock, link); + ISC_LIST_UNLINK(msg->offsets, msgblock, link); + msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t)); + msgblock = next_msgblock; + } + if (msg->need_cctx_cleanup == 1) dns_compress_invalidate(&msg->cctx); @@ -671,6 +707,7 @@ dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) m->rdspool = NULL; ISC_LIST_INIT(m->rdatas); ISC_LIST_INIT(m->rdatalists); + ISC_LIST_INIT(m->offsets); ISC_LIST_INIT(m->freerdata); ISC_LIST_INIT(m->freerdatalist); @@ -713,6 +750,12 @@ dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) ISC_LIST_APPEND(m->rdatalists, msgblock, link); } + msgblock = msgblock_allocate(mctx, sizeof(dns_offsets_t), + OFFSET_COUNT); + if (msgblock == NULL) + goto cleanup; + ISC_LIST_APPEND(m->offsets, msgblock, link); + *msgp = m; return (ISC_R_SUCCESS); @@ -723,6 +766,9 @@ dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) msgblock = ISC_LIST_HEAD(m->rdatas); if (msgblock != NULL) msgblock_free(mctx, msgblock, sizeof(dns_rdata_t)); + msgblock = ISC_LIST_HEAD(m->rdatalists); + if (msgblock != NULL) + msgblock_free(mctx, msgblock, sizeof(dns_rdatalist_t)); dynbuf = ISC_LIST_HEAD(m->scratchpad); if (dynbuf != NULL) { ISC_LIST_UNLINK(m->scratchpad, dynbuf, link); @@ -826,7 +872,6 @@ getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg, */ tries = 0; while (tries < 2) { - dns_name_init(name, NULL); result = dns_name_fromwire(name, source, dctx, ISC_FALSE, scratch); @@ -838,6 +883,7 @@ getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg, return (result); scratch = currentbuffer(msg); + dns_name_reset(name); } else { return (result); } @@ -918,6 +964,7 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, unsigned int count; dns_name_t *name; dns_name_t *name2; + dns_offsets_t *offsets; dns_rdataset_t *rdataset; dns_rdatalist_t *rdatalist; isc_result_t result; @@ -942,6 +989,11 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, if (name == NULL) return (ISC_R_NOMEMORY); free_name = ISC_TRUE; + + offsets = newoffsets(msg); + if (offsets == NULL) + goto cleanup; + dns_name_init(name, *offsets); /* * Parse the name out of this packet. @@ -1083,6 +1135,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, unsigned int count, rdatalen; dns_name_t *name; dns_name_t *name2; + dns_offsets_t *offsets; dns_rdataset_t *rdataset; dns_rdatalist_t *rdatalist; isc_result_t result; @@ -1114,6 +1167,11 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, return (ISC_R_NOMEMORY); free_name = ISC_TRUE; + offsets = newoffsets(msg); + if (offsets == NULL) + goto cleanup; + dns_name_init(name, *offsets); + /* * Parse the name out of this packet. */ @@ -2126,15 +2184,16 @@ dns_message_gettempname(dns_message_t *msg, dns_name_t **item) { return (ISC_R_SUCCESS); } -void -dns_message_puttempname(dns_message_t *msg, dns_name_t **item) { +isc_result_t +dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) { REQUIRE(DNS_MESSAGE_VALID(msg)); - REQUIRE(item != NULL && *item != NULL); + REQUIRE(item != NULL && *item == NULL); - if (dns_name_dynamic(*item)) - dns_name_free(*item, msg->mctx); - isc_mempool_put(msg->namepool, *item); - *item = NULL; + *item = newoffsets(msg); + if (*item == NULL) + return (ISC_R_NOMEMORY); + + return (ISC_R_SUCCESS); } isc_result_t @@ -2175,6 +2234,17 @@ dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { return (ISC_R_SUCCESS); } +void +dns_message_puttempname(dns_message_t *msg, dns_name_t **item) { + REQUIRE(DNS_MESSAGE_VALID(msg)); + REQUIRE(item != NULL && *item != NULL); + + if (dns_name_dynamic(*item)) + dns_name_free(*item, msg->mctx); + isc_mempool_put(msg->namepool, *item); + *item = NULL; +} + void dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) { REQUIRE(DNS_MESSAGE_VALID(msg));