diff --git a/CHANGES b/CHANGES index 1fea3b8d8e..a3c0562bc8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ + 508. [func] dns_message_parse() can now do a best-effort + attempt, which should allow dig to print more invalid + messages. + 507. [func] New functions dns_zone_flush(), dns_zt_flushanddetach() and dns_view_flushanddetach(). diff --git a/bin/named/client.c b/bin/named/client.c index 83b69a1b1d..e052aa2362 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.c,v 1.116 2000/09/26 22:09:18 bwelling Exp $ */ +/* $Id: client.c,v 1.117 2000/10/06 18:58:29 bwelling Exp $ */ #include @@ -1032,7 +1032,7 @@ client_request(isc_task_t *task, isc_event_t *event) { #endif } - result = dns_message_parse(client->message, buffer, ISC_FALSE); + result = dns_message_parse(client->message, buffer, 0); if (result != ISC_R_SUCCESS) { ns_client_error(client, result); goto cleanup_serverlock; diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 4beaa8a5c8..e07b2782a4 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsupdate.c,v 1.54 2000/10/03 17:28:58 bwelling Exp $ */ +/* $Id: nsupdate.c,v 1.55 2000/10/06 18:58:30 bwelling Exp $ */ #include @@ -1104,7 +1104,8 @@ update_completed(isc_task_t *task, isc_event_t *event) { result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg); check_result(result, "dns_message_create"); - result = dns_request_getresponse(reqev->request, rcvmsg, ISC_TRUE); + result = dns_request_getresponse(reqev->request, rcvmsg, + DNS_MESSAGEPARSE_PRESERVEORDER); check_result(result, "dns_request_getresponse"); if (debugging) { isc_buffer_t *buf = NULL; @@ -1224,7 +1225,8 @@ recvsoa(isc_task_t *task, isc_event_t *event) { ddebug("About to create rcvmsg"); result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg); check_result(result, "dns_message_create"); - result = dns_request_getresponse(request, rcvmsg, ISC_TRUE); + result = dns_request_getresponse(request, rcvmsg, + DNS_MESSAGEPARSE_PRESERVEORDER); check_result(result, "dns_request_getresponse"); section = DNS_SECTION_ANSWER; if (debugging) { diff --git a/bin/tests/dispatch_tcp_test.c b/bin/tests/dispatch_tcp_test.c index 61ab27e4d8..e985580669 100644 --- a/bin/tests/dispatch_tcp_test.c +++ b/bin/tests/dispatch_tcp_test.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch_tcp_test.c,v 1.35 2000/08/01 01:12:42 tale Exp $ */ +/* $Id: dispatch_tcp_test.c,v 1.36 2000/10/06 18:58:10 bwelling Exp $ */ #include @@ -155,7 +155,7 @@ got_request(isc_task_t *task, isc_event_t *ev_in) { result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); CHECKRESULT(result, "dns_message_create() failed"); - result = dns_message_parse(msg, &ev->buffer, ISC_FALSE); + result = dns_message_parse(msg, &ev->buffer, 0); CHECKRESULT(result, "dns_message_parse() failed"); result = printmsg(msg, stderr); diff --git a/bin/tests/dispatch_test.c b/bin/tests/dispatch_test.c index 8d7a257604..79eb67c85a 100644 --- a/bin/tests/dispatch_test.c +++ b/bin/tests/dispatch_test.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch_test.c,v 1.46 2000/08/01 01:12:43 tale Exp $ */ +/* $Id: dispatch_test.c,v 1.47 2000/10/06 18:58:11 bwelling Exp $ */ #include @@ -277,7 +277,7 @@ got_response(isc_task_t *task, isc_event_t *ev_in) { result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); CHECKRESULT(result, "dns_message_create() failed"); - result = dns_message_parse(msg, &ev->buffer, ISC_FALSE); + result = dns_message_parse(msg, &ev->buffer, 0); CHECKRESULT(result, "dns_message_parse() failed"); result = printmsg(msg, stderr); @@ -330,7 +330,7 @@ got_request(isc_task_t *task, isc_event_t *ev_in) { result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); CHECKRESULT(result, "dns_message_create() failed"); - result = dns_message_parse(msg, &ev->buffer, ISC_FALSE); + result = dns_message_parse(msg, &ev->buffer, 0); CHECKRESULT(result, "dns_message_parse() failed"); result = printmsg(msg, stderr); diff --git a/bin/tests/sig0_test.c b/bin/tests/sig0_test.c index f37b5436c3..64e56dd8a8 100644 --- a/bin/tests/sig0_test.c +++ b/bin/tests/sig0_test.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sig0_test.c,v 1.3 2000/08/30 19:17:46 gson Exp $ */ +/* $Id: sig0_test.c,v 1.4 2000/10/06 18:58:12 bwelling Exp $ */ #include @@ -110,7 +110,7 @@ recvdone(isc_task_t *task, isc_event_t *event) { response = NULL; result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); CHECK("dns_message_create", result); - result = dns_message_parse(response, &source, ISC_FALSE); + result = dns_message_parse(response, &source, 0); CHECK("dns_message_parse", result); isc_buffer_init(&outbuf, output, sizeof(output)); diff --git a/bin/tests/tkey_test.c b/bin/tests/tkey_test.c index bd417a656b..1e5310a10c 100644 --- a/bin/tests/tkey_test.c +++ b/bin/tests/tkey_test.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tkey_test.c,v 1.32 2000/08/30 01:35:39 bwelling Exp $ */ +/* $Id: tkey_test.c,v 1.33 2000/10/06 18:58:13 bwelling Exp $ */ /* * Principal Author: Brian Wellington (core copied from res_test.c) @@ -120,7 +120,7 @@ recvdone(isc_task_t *task, isc_event_t *event) { response = NULL; result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); CHECK("dns_message_create", result); - result = dns_message_parse(response, &source, ISC_FALSE); + result = dns_message_parse(response, &source, 0); CHECK("dns_message_parse", result); isc_buffer_init(&outbuf, output, sizeof(output)); @@ -188,7 +188,7 @@ recvdone2(isc_task_t *task, isc_event_t *event) { isc_buffer_free(&tsigbuf); dns_message_settsigkey(response2, tsigkey); CHECK("dns_message_create", result); - result = dns_message_parse(response2, &source, ISC_FALSE); + result = dns_message_parse(response2, &source, 0); CHECK("dns_message_parse", result); isc_buffer_init(&outbuf, output, sizeof(output)); result = dns_message_totext(response2, 0, &outbuf); diff --git a/bin/tests/wire_test.c b/bin/tests/wire_test.c index 9e503df611..7016862d09 100644 --- a/bin/tests/wire_test.c +++ b/bin/tests/wire_test.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: wire_test.c,v 1.52 2000/08/01 01:13:29 tale Exp $ */ +/* $Id: wire_test.c,v 1.53 2000/10/06 18:58:14 bwelling Exp $ */ #include @@ -125,7 +125,7 @@ main(int argc, char *argv[]) { result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message); CHECKRESULT(result, "dns_message_create failed"); - result = dns_message_parse(message, &source, ISC_FALSE); + result = dns_message_parse(message, &source, 0); CHECKRESULT(result, "dns_message_parse failed"); result = printmessage(message); @@ -171,7 +171,7 @@ main(int argc, char *argv[]) { result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message); CHECKRESULT(result, "dns_message_create failed"); - result = dns_message_parse(message, &source, ISC_FALSE); + result = dns_message_parse(message, &source, 0); CHECKRESULT(result, "dns_message_parse failed"); result = printmessage(message); diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index e992e15f7b..cab773e2d9 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.77 2000/09/11 23:37:34 marka Exp $ */ +/* $Id: message.h,v 1.78 2000/10/06 18:58:24 bwelling Exp $ */ #ifndef DNS_MESSAGE_H #define DNS_MESSAGE_H 1 @@ -142,6 +142,14 @@ typedef int dns_messagetextflag_t; #define DNS_MESSAGE_INTENTPARSE 1 /* parsing messages */ #define DNS_MESSAGE_INTENTRENDER 2 /* rendering */ +/* + * Control behavior of parsing + */ +#define DNS_MESSAGEPARSE_PRESERVEORDER 0x0001 /* preserve rdata order */ +#define DNS_MESSAGEPARSE_BESTEFFORT 0x0002 /* return a message if a + recoverable parse error + occurs */ + /* * Control behavior of rendering */ @@ -360,7 +368,7 @@ dns_message_totext(dns_message_t *msg, dns_messagetextflag_t flags, isc_result_t dns_message_parse(dns_message_t *msg, isc_buffer_t *source, - isc_boolean_t preserve_order); + unsigned int options); /* * Parse raw wire data pointed to by "buffer" and bounded by "buflen" as a * DNS message. @@ -368,23 +376,22 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, * OPT records are detected and stored in the pseudo-section "opt". * TSIGs are detected and stored in the pseudo-section "tsig". * - * If 'preserve_order' is true, or if the opcode of the message is UPDATE, - * a separate dns_name_t object will be created for each RR in the message. - * Each such dns_name_t will have a single rdataset containing the single RR, - * and the order of the RRs in the message is preserved. + * If DNS_MESSAGEPARSE_PRESERVEORDER is set, or if the opcode of the message + * is UPDATE, a separate dns_name_t object will be created for each RR in the + * message. Each such dns_name_t will have a single rdataset containing the + * single RR, * and the order of the RRs in the message is preserved. * Otherwise, only one dns_name_t object will be created for each unique * owner name in the section, and each such dns_name_t will have a list * of rdatasets. To access the names and their data, use * dns_message_firstname() and dns_message_nextname(). * + * If DNS_MESSAGEPARSE_BESTEFFORT is set, errors in message content will + * not be considered FORMERRs. If the entire message can be parsed, it + * will be returned and DNS_R_RECOVERABLE will be returned. + * * OPT and TSIG records are always handled specially, regardless of the * 'preserve_order' setting. * - * If this is a multi-packet message (edns) and more data is required to - * build the full message state, DNS_R_MOREDATA is returned. In this case, - * this function should be repeated with all input buffers until ISC_R_SUCCESS - * (or an error) is returned. - * * Requires: * "msg" be valid. * @@ -399,7 +406,8 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, * Returns: * ISC_R_SUCCESS -- all is well * ISC_R_NOMEMORY -- no memory - * DNS_R_MOREDATA -- more packets needed for complete message + * DNS_R_RECOVERABLE -- the message parsed properly, but contained + * errors. * DNS_R_??? -- bad signature (XXXMLG need more of these) * Many other errors possible XXXMLG */ diff --git a/lib/dns/include/dns/request.h b/lib/dns/include/dns/request.h index 59ee2a58eb..8a5f0572f1 100644 --- a/lib/dns/include/dns/request.h +++ b/lib/dns/include/dns/request.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: request.h,v 1.14 2000/09/11 06:35:57 marka Exp $ */ +/* $Id: request.h,v 1.15 2000/10/06 18:58:25 bwelling Exp $ */ #ifndef DNS_REQUEST_H #define DNS_REQUEST_H 1 @@ -243,11 +243,11 @@ dns_request_cancel(dns_request_t *request); isc_result_t dns_request_getresponse(dns_request_t *request, dns_message_t *message, - isc_boolean_t preserve_order); + unsigned int options); /* * Get the response to 'request' by filling in 'message'. * - * 'preserve_order' is passed to dns_message_parse(). See dns_message_parse() + * 'options' is passed to dns_message_parse(). See dns_message_parse() * for more details. * * Requires: diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h index acac8bd473..23899286c8 100644 --- a/lib/dns/include/dns/result.h +++ b/lib/dns/include/dns/result.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.h,v 1.65 2000/08/08 22:50:34 bwelling Exp $ */ +/* $Id: result.h,v 1.66 2000/10/06 18:58:26 bwelling Exp $ */ #ifndef DNS_RESULT_H #define DNS_RESULT_H 1 @@ -99,8 +99,9 @@ #define DNS_R_NOVALIDNXT (ISC_RESULTCLASS_DNS + 60) #define DNS_R_NOTINSECURE (ISC_RESULTCLASS_DNS + 61) #define DNS_R_ZONETOOLARGE (ISC_RESULTCLASS_DNS + 62) +#define DNS_R_RECOVERABLE (ISC_RESULTCLASS_DNS + 63) -#define DNS_R_NRESULTS 63 /* Number of results */ +#define DNS_R_NRESULTS 64 /* Number of results */ /* * DNS wire format rcodes. diff --git a/lib/dns/message.c b/lib/dns/message.c index e39d5fd46b..5af086117f 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.146 2000/09/12 09:57:30 bwelling Exp $ */ +/* $Id: message.c,v 1.147 2000/10/06 18:58:16 bwelling Exp $ */ /*** *** Imports @@ -896,8 +896,19 @@ getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, } } +#define DO_FORMERR \ + do { \ + if (best_effort) \ + seen_problem = ISC_TRUE; \ + else { \ + result = DNS_R_FORMERR; \ + goto cleanup; \ + } \ + } while (0) + static isc_result_t -getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx) +getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + unsigned int options) { isc_region_t r; unsigned int count; @@ -910,9 +921,13 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx) dns_rdataclass_t rdclass; dns_namelist_t *section; isc_boolean_t free_name; + isc_boolean_t best_effort; + isc_boolean_t seen_problem; section = &msg->sections[DNS_SECTION_QUESTION]; + best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); + name = NULL; rdataset = NULL; rdatalist = NULL; @@ -954,10 +969,8 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx) if (ISC_LIST_EMPTY(*section)) { ISC_LIST_APPEND(*section, name, link); free_name = ISC_FALSE; - } else { - result = DNS_R_FORMERR; - goto cleanup; - } + } else + DO_FORMERR; } else { isc_mempool_put(msg->namepool, name); name = name2; @@ -983,19 +996,15 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx) if (msg->state == DNS_SECTION_ANY) { msg->state = DNS_SECTION_QUESTION; msg->rdclass = rdclass; - } else if (msg->rdclass != rdclass) { - result = DNS_R_FORMERR; - goto cleanup; - } + } else if (msg->rdclass != rdclass) + DO_FORMERR; /* * Can't ask the same question twice. */ result = dns_message_findtype(name, rdtype, 0, NULL); - if (result == ISC_R_SUCCESS) { - result = DNS_R_FORMERR; - goto cleanup; - } + if (result == ISC_R_SUCCESS) + DO_FORMERR; /* * Allocate a new rdatalist. @@ -1032,6 +1041,8 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx) rdataset = NULL; } + if (seen_problem) + return (DNS_R_RECOVERABLE); return (ISC_R_SUCCESS); cleanup: @@ -1051,7 +1062,7 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx) static isc_result_t getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - dns_section_t sectionid, isc_boolean_t preserve_order) + dns_section_t sectionid, unsigned int options) { isc_region_t r; unsigned int count, rdatalen; @@ -1066,6 +1077,10 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, dns_ttl_t ttl; dns_namelist_t *section; isc_boolean_t free_name, free_rdataset; + isc_boolean_t preserve_order, best_effort, seen_problem; + + preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER); + best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); for (count = 0 ; count < msg->counts[sectionid] ; count++) { int recstart = source->current; @@ -1111,10 +1126,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, */ if (msg->state == DNS_SECTION_ANY) { if ((msg->opcode != dns_opcode_update) && - (rdclass == 0 || rdclass == dns_rdataclass_any)) { - result = DNS_R_FORMERR; - goto cleanup; - } + (rdclass == 0 || rdclass == dns_rdataclass_any)) + DO_FORMERR; msg->rdclass = rdclass; msg->state = DNS_SECTION_QUESTION; } @@ -1128,10 +1141,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, && rdtype != dns_rdatatype_opt && rdtype != dns_rdatatype_key /* XXX in a TKEY query */ && rdtype != dns_rdatatype_sig /* XXX SIG(0) */ - && msg->rdclass != rdclass) { - result = DNS_R_FORMERR; - goto cleanup; - } + && msg->rdclass != rdclass) + DO_FORMERR; /* * Special type handling for TSIG, OPT, and TKEY. @@ -1143,10 +1154,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, * the rest of this rdata. */ if ((sectionid != DNS_SECTION_ADDITIONAL) - || (rdclass != dns_rdataclass_any)) { - result = DNS_R_FORMERR; - goto cleanup; - } + || (rdclass != dns_rdataclass_any)) + DO_FORMERR; if (msg->tsig != NULL) { result = DNS_R_FORMERR; goto cleanup; @@ -1161,8 +1170,9 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, * it must be the first OPT we've seen. */ if (!dns_name_equal(dns_rootname, name) || - sectionid != DNS_SECTION_ADDITIONAL || - msg->opt != NULL) { + msg->opt != NULL) + DO_FORMERR; + if (msg->opt != NULL) { result = DNS_R_FORMERR; goto cleanup; } @@ -1181,10 +1191,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, tkeysection = DNS_SECTION_ADDITIONAL; else tkeysection = DNS_SECTION_ANSWER; - if (sectionid != tkeysection) { - result = DNS_R_FORMERR; - goto cleanup; - } + if (sectionid != tkeysection) + DO_FORMERR; } /* @@ -1303,10 +1311,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, * the opcode is an update, or the type search is skipped. */ if (result == ISC_R_SUCCESS) { - if (dns_rdatatype_issingleton(rdtype)) { - result = DNS_R_FORMERR; - goto cleanup; - } + if (dns_rdatatype_issingleton(rdtype)) + DO_FORMERR; } if (result == ISC_R_NOTFOUND) { @@ -1403,6 +1409,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, INSIST(free_rdataset == ISC_FALSE); } + if (seen_problem) + return (DNS_R_RECOVERABLE); return (ISC_R_SUCCESS); cleanup: @@ -1416,18 +1424,22 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, isc_result_t dns_message_parse(dns_message_t *msg, isc_buffer_t *source, - isc_boolean_t preserve_order) + unsigned int options) { isc_region_t r; dns_decompress_t dctx; isc_result_t ret; isc_uint16_t tmpflags; isc_buffer_t origsource; + isc_boolean_t best_effort; + isc_boolean_t seen_problem; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(source != NULL); REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); + best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); + origsource = *source; msg->header_ok = 0; @@ -1457,23 +1469,36 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14); - ret = getquestions(source, msg, &dctx); + ret = getquestions(source, msg, &dctx, options); + if (ret == DNS_R_RECOVERABLE) { + seen_problem = ISC_TRUE; + ret = ISC_R_SUCCESS; + } if (ret != ISC_R_SUCCESS) return (ret); msg->question_ok = 1; - ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, - preserve_order); + ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options); + if (ret == DNS_R_RECOVERABLE) { + seen_problem = ISC_TRUE; + ret = ISC_R_SUCCESS; + } if (ret != ISC_R_SUCCESS) return (ret); - ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, - preserve_order); + ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options); + if (ret == DNS_R_RECOVERABLE) { + seen_problem = ISC_TRUE; + ret = ISC_R_SUCCESS; + } if (ret != ISC_R_SUCCESS) return (ret); - ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, - preserve_order); + ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options); + if (ret == DNS_R_RECOVERABLE) { + seen_problem = ISC_TRUE; + ret = ISC_R_SUCCESS; + } if (ret != ISC_R_SUCCESS) return (ret); @@ -1484,7 +1509,10 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, DNS_LOGMODULE_MESSAGE, ISC_LOG_INFO, "message has nonstandard Microsoft tag"); } else { - return (DNS_R_FORMERR); + if (best_effort) + seen_problem = ISC_TRUE; + else + return (DNS_R_FORMERR); } } @@ -1502,6 +1530,8 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, } memcpy(msg->saved->base, r.base, msg->saved->length); + if (seen_problem == ISC_TRUE) + return (DNS_R_RECOVERABLE); return (ISC_R_SUCCESS); } diff --git a/lib/dns/request.c b/lib/dns/request.c index a84abbb1db..95ecd2b6f0 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: request.c,v 1.37 2000/09/11 06:35:56 marka Exp $ */ +/* $Id: request.c,v 1.38 2000/10/06 18:58:17 bwelling Exp $ */ #include @@ -965,7 +965,7 @@ dns_request_cancel(dns_request_t *request) { isc_result_t dns_request_getresponse(dns_request_t *request, dns_message_t *message, - isc_boolean_t preserve_order) + unsigned int options) { isc_result_t result; @@ -977,7 +977,7 @@ dns_request_getresponse(dns_request_t *request, dns_message_t *message, dns_message_setquerytsig(message, request->tsig); dns_message_settsigkey(message, request->tsigkey); - result = dns_message_parse(message, request->answer, preserve_order); + result = dns_message_parse(message, request->answer, options); if (result != ISC_R_SUCCESS) return (result); if (request->tsigkey != NULL) diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 1597bda692..b05bc14c5f 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.169 2000/09/28 06:43:36 marka Exp $ */ +/* $Id: resolver.c,v 1.170 2000/10/06 18:58:18 bwelling Exp $ */ #include @@ -3808,7 +3808,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { goto done; } - result = dns_message_parse(message, &devent->buffer, ISC_FALSE); + result = dns_message_parse(message, &devent->buffer, 0); if (result != ISC_R_SUCCESS) { switch (result) { case ISC_R_UNEXPECTEDEND: diff --git a/lib/dns/result.c b/lib/dns/result.c index a304e0787d..272006a899 100644 --- a/lib/dns/result.c +++ b/lib/dns/result.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.c,v 1.71 2000/08/08 23:33:05 bwelling Exp $ */ +/* $Id: result.c,v 1.72 2000/10/06 18:58:20 bwelling Exp $ */ #include @@ -100,7 +100,8 @@ static const char *text[DNS_R_NRESULTS] = { "no valid NXT", /* 60 DNS_R_NOVALIDNXT */ "not insecure", /* 61 DNS_R_NOTINSECURE */ - "zone too large" /* 62 DNS_R_ZONETOOLARGE */ + "zone too large", /* 62 DNS_R_ZONETOOLARGE */ + "recoverable error occurred" /* 63 DNS_R_RECOVERABLE */ }; static const char *rcode_text[DNS_R_NRCODERESULTS] = { diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index f368b26a47..db50770d93 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: xfrin.c,v 1.98 2000/10/02 23:55:44 marka Exp $ */ +/* $Id: xfrin.c,v 1.99 2000/10/06 18:58:21 bwelling Exp $ */ #include @@ -1007,7 +1007,8 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { if (xfr->nmsg > 0) msg->tcp_continuation = 1; - result = dns_message_parse(msg, &tcpmsg->buffer, ISC_TRUE); + result = dns_message_parse(msg, &tcpmsg->buffer, + DNS_MESSAGEPARSE_PRESERVEORDER); if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror) { if (result == ISC_R_SUCCESS) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 338346edbf..11160e6fba 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.227 2000/10/05 06:39:21 marka Exp $ */ +/* $Id: zone.c,v 1.228 2000/10/06 18:58:22 bwelling Exp $ */ #include @@ -2648,7 +2648,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_SUCCESS) goto next_master; - result = dns_request_getresponse(revent->request, msg, ISC_FALSE); + result = dns_request_getresponse(revent->request, msg, 0); if (result != ISC_R_SUCCESS) goto next_master; @@ -2836,7 +2836,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg); if (result != ISC_R_SUCCESS) goto next_master; - result = dns_request_getresponse(revent->request, msg, ISC_FALSE); + result = dns_request_getresponse(revent->request, msg, 0); if (result != ISC_R_SUCCESS) { zone_log(zone, me, ISC_LOG_INFO, "failure in request to %s: %s", @@ -4163,7 +4163,7 @@ notify_done(isc_task_t *task, isc_event_t *event) { DNS_MESSAGE_INTENTPARSE, &message); if (result == ISC_R_SUCCESS) result = dns_request_getresponse(revent->request, message, - ISC_TRUE); + DNS_MESSAGEPARSE_PRESERVEORDER); if (result == ISC_R_SUCCESS) result = dns_rcode_totext(message->rcode, &buf); if (result == ISC_R_SUCCESS) @@ -4682,7 +4682,8 @@ forward_callback(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_SUCCESS) goto next_master; - result = dns_request_getresponse(revent->request, msg, ISC_TRUE); + result = dns_request_getresponse(revent->request, msg, + DNS_MESSAGEPARSE_PRESERVEORDER); if (result != ISC_R_SUCCESS) goto next_master;