diff options
Diffstat (limited to 'lib/dns/message.c')
-rw-r--r-- | lib/dns/message.c | 79 |
1 files changed, 64 insertions, 15 deletions
diff --git a/lib/dns/message.c b/lib/dns/message.c index b95e48ea2641..cd0e89b8d20e 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -42,6 +42,7 @@ #include <dns/rdatastruct.h> #include <dns/result.h> #include <dns/tsig.h> +#include <dns/ttl.h> #include <dns/view.h> #ifdef SKAN_MSG_DEBUG @@ -329,7 +330,7 @@ newrdatalist(dns_message_t *msg) { rdatalist = ISC_LIST_HEAD(msg->freerdatalist); if (rdatalist != NULL) { ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link); - return (rdatalist); + goto out; } msgblock = ISC_LIST_TAIL(msg->rdatalists); @@ -345,6 +346,9 @@ newrdatalist(dns_message_t *msg) { rdatalist = msgblock_get(msgblock, dns_rdatalist_t); } + out: + if (rdatalist != NULL) + dns_rdatalist_init(rdatalist); return (rdatalist); } @@ -1825,9 +1829,19 @@ wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) { * Decide whether to not answer with an AAAA record and its RRSIG */ static inline isc_boolean_t -norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options) +norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options, + dns_section_t sectionid) { + if (sectionid == DNS_SECTION_QUESTION) + return (ISC_FALSE); + switch (rdataset->type) { + case dns_rdatatype_ns: + if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 || + sectionid != DNS_SECTION_AUTHORITY) + return (ISC_FALSE); + break; + case dns_rdatatype_aaaa: if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0) return (ISC_FALSE); @@ -1835,7 +1849,11 @@ norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options) case dns_rdatatype_rrsig: if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 || - rdataset->covers != dns_rdatatype_aaaa) + (rdataset->covers != dns_rdatatype_ns && + rdataset->covers != dns_rdatatype_aaaa)) + return (ISC_FALSE); + if ((rdataset->covers == dns_rdatatype_ns) && + (sectionid != DNS_SECTION_AUTHORITY)) return (ISC_FALSE); break; @@ -1983,8 +2001,7 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, * not doing DNSSEC or are breaking DNSSEC. * Say so in the AD bit if we break DNSSEC. */ - if (norender_rdataset(rdataset, options) && - sectionid != DNS_SECTION_QUESTION) { + if (norender_rdataset(rdataset, options, sectionid)) { if (sectionid == DNS_SECTION_ANSWER || sectionid == DNS_SECTION_AUTHORITY) msg->flags &= ~DNS_MESSAGEFLAG_AD; @@ -2532,7 +2549,7 @@ dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp, isc_result_t dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { - unsigned int clear_after; + unsigned int clear_from; isc_result_t result; REQUIRE(DNS_MESSAGE_VALID(msg)); @@ -2544,15 +2561,15 @@ dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { msg->opcode != dns_opcode_notify) want_question_section = ISC_FALSE; if (msg->opcode == dns_opcode_update) - clear_after = DNS_SECTION_PREREQUISITE; + clear_from = DNS_SECTION_PREREQUISITE; else if (want_question_section) { if (!msg->question_ok) return (DNS_R_FORMERR); - clear_after = DNS_SECTION_ANSWER; + clear_from = DNS_SECTION_ANSWER; } else - clear_after = DNS_SECTION_QUESTION; + clear_from = DNS_SECTION_QUESTION; msg->from_to_wire = DNS_MESSAGE_INTENTRENDER; - msgresetnames(msg, clear_after); + msgresetnames(msg, clear_from); msgresetopt(msg); msgresetsigs(msg, ISC_TRUE); msginitprivate(msg); @@ -2752,7 +2769,6 @@ dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) { dns_rdata_init(rdata); dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r); dns_message_takebuffer(msg, &buf); - ISC_LIST_INIT(list->rdata); ISC_LIST_APPEND(list->rdata, rdata, link); result = dns_rdatalist_tordataset(list, set); if (result != ISC_R_SUCCESS) @@ -3264,6 +3280,21 @@ dns_message_pseudosectiontotext(dns_message_t *msg, if (optcode == DNS_OPT_NSID) { ADD_STRING(target, "; NSID"); + } else if (optcode == DNS_OPT_COOKIE) { + ADD_STRING(target, "; COOKIE"); + } else if (optcode == DNS_OPT_EXPIRE) { + if (optlen == 4) { + isc_uint32_t secs; + secs = isc_buffer_getuint32(&optbuf); + ADD_STRING(target, "; EXPIRE: "); + snprintf(buf, sizeof(buf), "%u", secs); + ADD_STRING(target, buf); + ADD_STRING(target, " ("); + dns_ttl_totext(secs, ISC_TRUE, target); + ADD_STRING(target, ")\n"); + continue; + } + ADD_STRING(target, "; EXPIRE"); } else { ADD_STRING(target, "; OPT="); snprintf(buf, sizeof(buf), "%u", optcode); @@ -3276,10 +3307,31 @@ dns_message_pseudosectiontotext(dns_message_t *msg, optdata = isc_buffer_current(&optbuf); for (i = 0; i < optlen; i++) { - sprintf(buf, "%02x ", optdata[i]); + const char *sep; + switch (optcode) { + case DNS_OPT_COOKIE: + sep = ""; + break; + default: + sep = " "; + break; + } + snprintf(buf, sizeof(buf), "%02x%s", + optdata[i], sep); ADD_STRING(target, buf); } + isc_buffer_forward(&optbuf, optlen); + + if (optcode == DNS_OPT_COOKIE) { + ADD_STRING(target, "\n"); + continue; + } + + /* + * For non-COOKIE options, add a printable + * version + */ for (i = 0; i < optlen; i++) { ADD_STRING(target, " ("); if (!isc_buffer_availablelength(target)) @@ -3292,7 +3344,6 @@ dns_message_pseudosectiontotext(dns_message_t *msg, isc_buffer_putstr(target, "."); ADD_STRING(target, ")"); } - isc_buffer_forward(&optbuf, optlen); } ADD_STRING(target, "\n"); } @@ -3497,7 +3548,6 @@ dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp, dns_rdataset_init(rdataset); rdatalist->type = dns_rdatatype_opt; - rdatalist->covers = 0; /* * Set Maximum UDP buffer size. @@ -3545,7 +3595,6 @@ dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp, rdata->type = rdatalist->type; rdata->flags = 0; - ISC_LIST_INIT(rdatalist->rdata); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); result = dns_rdatalist_tordataset(rdatalist, rdataset); RUNTIME_CHECK(result == ISC_R_SUCCESS); |