diff options
Diffstat (limited to 'lib/dns/message.c')
| -rw-r--r-- | lib/dns/message.c | 127 |
1 files changed, 62 insertions, 65 deletions
diff --git a/lib/dns/message.c b/lib/dns/message.c index d3ae609a6de1f..869d25823eead 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2016 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -36,6 +36,7 @@ #include <dns/masterdump.h> #include <dns/message.h> #include <dns/opcode.h> +#include <dns/rcode.h> #include <dns/rdata.h> #include <dns/rdatalist.h> #include <dns/rdataset.h> @@ -145,27 +146,6 @@ static const char *opcodetext[] = { "RESERVED15" }; -static const char *rcodetext[] = { - "NOERROR", - "FORMERR", - "SERVFAIL", - "NXDOMAIN", - "NOTIMP", - "REFUSED", - "YXDOMAIN", - "YXRRSET", - "NXRRSET", - "NOTAUTH", - "NOTZONE", - "RESERVED11", - "RESERVED12", - "RESERVED13", - "RESERVED14", - "RESERVED15", - "BADVERS" -}; - - /*% * "helper" type, which consists of a block of some type, and is linkable. * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer @@ -850,9 +830,8 @@ dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass, { dns_rdataset_t *curr; - if (rdataset != NULL) { - REQUIRE(*rdataset == NULL); - } + REQUIRE(name != NULL); + REQUIRE(rdataset == NULL || *rdataset == NULL); for (curr = ISC_LIST_TAIL(name->list); curr != NULL; @@ -875,15 +854,13 @@ dns_message_findtype(dns_name_t *name, dns_rdatatype_t type, dns_rdataset_t *curr; REQUIRE(name != NULL); - if (rdataset != NULL) { - REQUIRE(*rdataset == NULL); - } + REQUIRE(rdataset == NULL || *rdataset == NULL); for (curr = ISC_LIST_TAIL(name->list); curr != NULL; curr = ISC_LIST_PREV(curr, link)) { if (curr->type == type && curr->covers == covers) { - if (rdataset != NULL) + if (ISC_UNLIKELY(rdataset != NULL)) *rdataset = curr; return (ISC_R_SUCCESS); } @@ -1300,6 +1277,7 @@ 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) DO_FORMERR; skip_name_search = ISC_TRUE; @@ -1541,9 +1519,12 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, ISC_LIST_APPEND(rdatalist->rdata, rdata, link); /* - * If this is an OPT record, remember it. Also, set - * the extended rcode. Note that msg->opt will only be set - * if best-effort parsing is enabled. + * If this is an OPT, SIG(0) or TSIG record, remember it. + * Also, set the extended rcode for TSIG. + * + * Note msg->opt, msg->sig0 and msg->tsig will only be + * already set if best-effort parsing is enabled otherwise + * there will only be at most one of each. */ if (rdtype == dns_rdatatype_opt && msg->opt == NULL) { dns_rcode_t ercode; @@ -1557,14 +1538,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, msg->rcode |= ercode; isc_mempool_put(msg->namepool, name); free_name = ISC_FALSE; - } - - /* - * If this is an SIG(0) or TSIG record, remember it. Note - * that msg->sig0 or msg->tsig will only be set if best-effort - * parsing is enabled. - */ - if (issigzero && msg->sig0 == NULL) { + } else if (issigzero && msg->sig0 == NULL) { msg->sig0 = rdataset; msg->sig0name = name; rdataset = NULL; @@ -1748,7 +1722,7 @@ dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, if (r.length < DNS_MESSAGE_HEADERLEN) return (ISC_R_NOSPACE); - if (r.length < msg->reserved) + if (r.length - DNS_MESSAGE_HEADERLEN < msg->reserved) return (ISC_R_NOSPACE); /* @@ -1889,8 +1863,29 @@ norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options, return (ISC_TRUE); } - #endif + +static isc_result_t +renderset(dns_rdataset_t *rdataset, dns_name_t *owner_name, + dns_compress_t *cctx, isc_buffer_t *target, + unsigned int reserved, unsigned int options, unsigned int *countp) +{ + isc_result_t result; + + /* + * Shrink the space in the buffer by the reserved amount. + */ + if (target->length - target->used < reserved) + return (ISC_R_NOSPACE); + + target->length -= reserved; + result = dns_rdataset_towire(rdataset, owner_name, + cctx, target, options, countp); + target->length += reserved; + + return (result); +} + isc_result_t dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, unsigned int options) @@ -1933,6 +1928,8 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, /* * Shrink the space in the buffer by the reserved amount. */ + if (msg->buffer->length - msg->buffer->used < msg->reserved) + return (ISC_R_NOSPACE); msg->buffer->length -= msg->reserved; total = 0; @@ -2208,9 +2205,8 @@ dns_message_renderend(dns_message_t *msg) { * Render. */ count = 0; - result = dns_rdataset_towire(msg->opt, dns_rootname, - msg->cctx, msg->buffer, 0, - &count); + result = renderset(msg->opt, dns_rootname, msg->cctx, + msg->buffer, msg->reserved, 0, &count); msg->counts[DNS_SECTION_ADDITIONAL] += count; if (result != ISC_R_SUCCESS) return (result); @@ -2226,9 +2222,8 @@ dns_message_renderend(dns_message_t *msg) { if (result != ISC_R_SUCCESS) return (result); count = 0; - result = dns_rdataset_towire(msg->tsig, msg->tsigname, - msg->cctx, msg->buffer, 0, - &count); + result = renderset(msg->tsig, msg->tsigname, msg->cctx, + msg->buffer, msg->reserved, 0, &count); msg->counts[DNS_SECTION_ADDITIONAL] += count; if (result != ISC_R_SUCCESS) return (result); @@ -2249,9 +2244,8 @@ dns_message_renderend(dns_message_t *msg) { * the owner name of a SIG(0) is irrelevant, and will not * be set in a message being rendered. */ - result = dns_rdataset_towire(msg->sig0, dns_rootname, - msg->cctx, msg->buffer, 0, - &count); + result = renderset(msg->sig0, dns_rootname, msg->cctx, + msg->buffer, msg->reserved, 0, &count); msg->counts[DNS_SECTION_ADDITIONAL] += count; if (result != ISC_R_SUCCESS) return (result); @@ -2364,13 +2358,12 @@ dns_message_findname(dns_message_t *msg, dns_section_t section, REQUIRE(msg != NULL); REQUIRE(VALID_SECTION(section)); REQUIRE(target != NULL); - if (name != NULL) - REQUIRE(*name == NULL); + REQUIRE(name == NULL || *name == NULL); + if (type == dns_rdatatype_any) { REQUIRE(rdataset == NULL); } else { - if (rdataset != NULL) - REQUIRE(*rdataset == NULL); + REQUIRE(rdataset == NULL || *rdataset == NULL); } result = findname(&foundname, target, @@ -2387,7 +2380,7 @@ dns_message_findname(dns_message_t *msg, dns_section_t section, /* * And now look for the type. */ - if (type == dns_rdatatype_any) + if (ISC_UNLIKELY(type == dns_rdatatype_any)) return (ISC_R_SUCCESS); result = dns_message_findtype(foundname, type, covers, rdataset); @@ -3277,7 +3270,7 @@ dns_message_pseudosectiontotext(dns_message_t *msg, mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */ if (mbz != 0) { ADD_STRING(target, "; MBZ: "); - snprintf(buf, sizeof(buf), "%.4x ", mbz); + snprintf(buf, sizeof(buf), "0x%.4x", mbz); ADD_STRING(target, buf); ADD_STRING(target, ", udp: "); } else @@ -3313,11 +3306,17 @@ dns_message_pseudosectiontotext(dns_message_t *msg, snprintf(buf, sizeof(buf), "%u", secs); ADD_STRING(target, buf); ADD_STRING(target, " ("); - dns_ttl_totext(secs, ISC_TRUE, target); + result = dns_ttl_totext(secs, + ISC_TRUE, + target); + if (result != ISC_R_SUCCESS) + return (result); ADD_STRING(target, ")\n"); continue; } ADD_STRING(target, "; EXPIRE"); + } else if (optcode == DNS_OPT_PAD) { + ADD_STRING(target, "; PAD"); } else { ADD_STRING(target, "; OPT="); snprintf(buf, sizeof(buf), "%u", optcode); @@ -3399,7 +3398,8 @@ dns_message_pseudosectiontotext(dns_message_t *msg, isc_result_t dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, - dns_messagetextflag_t flags, isc_buffer_t *target) { + dns_messagetextflag_t flags, isc_buffer_t *target) +{ char buf[sizeof("1234567890")]; isc_result_t result; @@ -3410,12 +3410,9 @@ dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, ADD_STRING(target, ";; ->>HEADER<<- opcode: "); ADD_STRING(target, opcodetext[msg->opcode]); ADD_STRING(target, ", status: "); - if (msg->rcode < (sizeof(rcodetext)/sizeof(rcodetext[0]))) { - ADD_STRING(target, rcodetext[msg->rcode]); - } else { - snprintf(buf, sizeof(buf), "%4u", msg->rcode); - ADD_STRING(target, buf); - } + result = dns_rcode_totext(msg->rcode, target); + if (result != ISC_R_SUCCESS) + return (result); ADD_STRING(target, ", id: "); snprintf(buf, sizeof(buf), "%6u", msg->id); ADD_STRING(target, buf); |
