summaryrefslogtreecommitdiff
path: root/lib/dns/message.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/message.c')
-rw-r--r--lib/dns/message.c79
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);