From c73c1c33ec9569c8f9ffd205b48f044f9b03795b Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 12 Feb 2002 02:10:33 +0000 Subject: [PATCH] 1193. [bug] dig +besteffort parsing didn't handle packet truncation. dns_message_parse() has new flag DNS_MESSAGE_IGNORETRUNCATION. --- CHANGES | 4 +++- bin/dig/dighost.c | 6 ++++-- lib/dns/include/dns/message.h | 7 ++++++- lib/dns/message.c | 27 ++++++++++++++------------- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/CHANGES b/CHANGES index 6044fd88e7..b2b8572a0f 100644 --- a/CHANGES +++ b/CHANGES @@ -19,7 +19,9 @@ 1194. [bug] Not all duplicate zone definitions were being detected at the named.conf checking stage. [RT #2431] -1193. [bug] Best effort parsing didn't handle packet truncation. +1193. [bug] dig +besteffort parsing didn't handle packet + truncation. dns_message_parse() has new flag + DNS_MESSAGE_IGNORETRUNCATION. 1192. [bug] The seconds fields in LOC records were restricted to three decimal places. More decimal places should diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 1c32a9ff07..55aca6f6ec 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dighost.c,v 1.238 2001/11/30 01:58:39 gson Exp $ */ +/* $Id: dighost.c,v 1.239 2002/02/12 02:10:30 marka Exp $ */ /* * Notice to programmers: Do not use this code as an example of how to @@ -2195,8 +2195,10 @@ recv_done(isc_task_t *task, isc_event_t *event) { debug("before parse starts"); parseflags = DNS_MESSAGEPARSE_PRESERVEORDER; - if (l->besteffort) + if (l->besteffort) { parseflags |= DNS_MESSAGEPARSE_BESTEFFORT; + parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION; + } result = dns_message_parse(msg, b, parseflags); if (result == DNS_R_RECOVERABLE) { printf(";; Warning: Message parser reports malformed " diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 06cf170827..4467fa0c75 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.106 2002/01/22 09:07:26 bwelling Exp $ */ +/* $Id: message.h,v 1.107 2002/02/12 02:10:33 marka Exp $ */ #ifndef DNS_MESSAGE_H #define DNS_MESSAGE_H 1 @@ -153,6 +153,8 @@ typedef int dns_messagetextflag_t; occurs */ #define DNS_MESSAGEPARSE_CLONEBUFFER 0x0004 /* save a copy of the source buffer */ +#define DNS_MESSAGEPARSE_IGNORETRUNCATION 0x0008 /* trucation errors are + * not fatal. */ /* * Control behavior of rendering @@ -401,6 +403,9 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, * not be considered FORMERRs. If the entire message can be parsed, it * will be returned and DNS_R_RECOVERABLE will be returned. * + * If DNS_MESSAGEPARSE_IGNORETRUNCATION is set then return as many complete + * RR's as possible, DNS_R_RECOVERABLE will be returned. + * * OPT and TSIG records are always handled specially, regardless of the * 'preserve_order' setting. * diff --git a/lib/dns/message.c b/lib/dns/message.c index 2011e9f294..beb7d4af56 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.206 2002/02/11 02:03:23 marka Exp $ */ +/* $Id: message.c,v 1.207 2002/02/12 02:10:32 marka Exp $ */ /*** *** Imports @@ -942,7 +942,6 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, isc_boolean_t free_name; isc_boolean_t best_effort; isc_boolean_t seen_problem; - isc_buffer_t save = *source; section = &msg->sections[DNS_SECTION_QUESTION]; @@ -954,7 +953,6 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, rdatalist = NULL; for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) { - save = *source; name = isc_mempool_get(msg->namepool); if (name == NULL) return (ISC_R_NOMEMORY); @@ -1074,10 +1072,6 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, return (ISC_R_SUCCESS); cleanup: - if (result == ISC_R_UNEXPECTEDEND && best_effort) { - *source = save; - result = DNS_R_RECOVERABLE; - } if (rdataset != NULL) { INSIST(!dns_rdataset_isassociated(rdataset)); isc_mempool_put(msg->rdspool, rdataset); @@ -1122,7 +1116,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, isc_boolean_t free_name, free_rdataset; isc_boolean_t preserve_order, best_effort, seen_problem; isc_boolean_t issigzero; - isc_buffer_t save = *source; preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER); best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); @@ -1138,7 +1131,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, skip_type_search = ISC_FALSE; free_name = ISC_FALSE; free_rdataset = ISC_FALSE; - save = *source; name = isc_mempool_get(msg->namepool); if (name == NULL) @@ -1482,10 +1474,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, return (ISC_R_SUCCESS); cleanup: - if (result == ISC_R_UNEXPECTEDEND && best_effort) { - *source = save; - result = DNS_R_RECOVERABLE; - } if (free_name) isc_mempool_put(msg->namepool, name); if (free_rdataset) @@ -1504,12 +1492,14 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, isc_uint16_t tmpflags; isc_buffer_t origsource; isc_boolean_t seen_problem; + isc_boolean_t ignore_tc; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(source != NULL); REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); seen_problem = ISC_FALSE; + ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION); origsource = *source; @@ -1541,6 +1531,8 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14); ret = getquestions(source, msg, &dctx, options); + if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) + goto truncated; if (ret == DNS_R_RECOVERABLE) { seen_problem = ISC_TRUE; ret = ISC_R_SUCCESS; @@ -1550,6 +1542,8 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, msg->question_ok = 1; ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options); + if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) + goto truncated; if (ret == DNS_R_RECOVERABLE) { seen_problem = ISC_TRUE; ret = ISC_R_SUCCESS; @@ -1558,6 +1552,8 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, return (ret); ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options); + if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) + goto truncated; if (ret == DNS_R_RECOVERABLE) { seen_problem = ISC_TRUE; ret = ISC_R_SUCCESS; @@ -1566,6 +1562,8 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, return (ret); ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options); + if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) + goto truncated; if (ret == DNS_R_RECOVERABLE) { seen_problem = ISC_TRUE; ret = ISC_R_SUCCESS; @@ -1581,6 +1579,7 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, r.length); } + truncated: if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0) isc_buffer_usedregion(&origsource, &msg->saved); else { @@ -1593,6 +1592,8 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, msg->free_saved = 1; } + if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) + return (DNS_R_RECOVERABLE); if (seen_problem == ISC_TRUE) return (DNS_R_RECOVERABLE); return (ISC_R_SUCCESS);