|
|
900526 |
diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h
|
|
|
900526 |
index a6862fa..d999e75 100644
|
|
|
900526 |
--- a/lib/dns/include/dns/message.h
|
|
|
900526 |
+++ b/lib/dns/include/dns/message.h
|
|
|
900526 |
@@ -210,6 +210,8 @@ struct dns_message {
|
|
|
900526 |
unsigned int verify_attempted : 1;
|
|
|
900526 |
unsigned int free_query : 1;
|
|
|
900526 |
unsigned int free_saved : 1;
|
|
|
900526 |
+ unsigned int tkey : 1;
|
|
|
900526 |
+ unsigned int rdclass_set : 1;
|
|
|
900526 |
|
|
|
900526 |
unsigned int opt_reserved;
|
|
|
900526 |
unsigned int sig_reserved;
|
|
|
900526 |
@@ -1374,6 +1376,15 @@ dns_message_buildopt(dns_message_t *msg, dns_rdataset_t **opt,
|
|
|
900526 |
* \li other.
|
|
|
900526 |
*/
|
|
|
900526 |
|
|
|
900526 |
+void
|
|
|
900526 |
+dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass);
|
|
|
900526 |
+/*%<
|
|
|
900526 |
+ * Set the expected class of records in the response.
|
|
|
900526 |
+ *
|
|
|
900526 |
+ * Requires:
|
|
|
900526 |
+ * \li msg be a valid message with parsing intent.
|
|
|
900526 |
+ */
|
|
|
900526 |
+
|
|
|
900526 |
ISC_LANG_ENDDECLS
|
|
|
900526 |
|
|
|
900526 |
#endif /* DNS_MESSAGE_H */
|
|
|
900526 |
diff --git a/lib/dns/message.c b/lib/dns/message.c
|
|
|
900526 |
index 53efc5a..73def73 100644
|
|
|
900526 |
--- a/lib/dns/message.c
|
|
|
900526 |
+++ b/lib/dns/message.c
|
|
|
900526 |
@@ -436,6 +436,8 @@ msginit(dns_message_t *m) {
|
|
|
900526 |
m->saved.base = NULL;
|
|
|
900526 |
m->saved.length = 0;
|
|
|
900526 |
m->free_saved = 0;
|
|
|
900526 |
+ m->tkey = 0;
|
|
|
900526 |
+ m->rdclass_set = 0;
|
|
|
900526 |
m->querytsig = NULL;
|
|
|
900526 |
}
|
|
|
900526 |
|
|
|
900526 |
@@ -1086,13 +1088,19 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|
|
900526 |
* If this class is different than the one we already read,
|
|
|
900526 |
* this is an error.
|
|
|
900526 |
*/
|
|
|
900526 |
- if (msg->state == DNS_SECTION_ANY) {
|
|
|
900526 |
- msg->state = DNS_SECTION_QUESTION;
|
|
|
900526 |
+ if (msg->rdclass_set == 0) {
|
|
|
900526 |
msg->rdclass = rdclass;
|
|
|
900526 |
+ msg->rdclass_set = 1;
|
|
|
900526 |
} else if (msg->rdclass != rdclass)
|
|
|
900526 |
DO_FORMERR;
|
|
|
900526 |
|
|
|
900526 |
/*
|
|
|
900526 |
+ * Is this a TKEY query?
|
|
|
900526 |
+ */
|
|
|
900526 |
+ if (rdtype == dns_rdatatype_tkey)
|
|
|
900526 |
+ msg->tkey = 1;
|
|
|
900526 |
+
|
|
|
900526 |
+ /*
|
|
|
900526 |
* Can't ask the same question twice.
|
|
|
900526 |
*/
|
|
|
900526 |
result = dns_message_find(name, rdclass, rdtype, 0, NULL);
|
|
|
900526 |
@@ -1236,12 +1244,12 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|
|
900526 |
* If there was no question section, we may not yet have
|
|
|
900526 |
* established a class. Do so now.
|
|
|
900526 |
*/
|
|
|
900526 |
- if (msg->state == DNS_SECTION_ANY &&
|
|
|
900526 |
+ if (msg->rdclass_set == 0 &&
|
|
|
900526 |
rdtype != dns_rdatatype_opt && /* class is UDP SIZE */
|
|
|
900526 |
rdtype != dns_rdatatype_tsig && /* class is ANY */
|
|
|
900526 |
rdtype != dns_rdatatype_tkey) { /* class is undefined */
|
|
|
900526 |
msg->rdclass = rdclass;
|
|
|
900526 |
- msg->state = DNS_SECTION_QUESTION;
|
|
|
900526 |
+ msg->rdclass_set = 1;
|
|
|
900526 |
}
|
|
|
900526 |
|
|
|
900526 |
/*
|
|
|
900526 |
@@ -1251,7 +1259,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|
|
900526 |
if (msg->opcode != dns_opcode_update
|
|
|
900526 |
&& rdtype != dns_rdatatype_tsig
|
|
|
900526 |
&& rdtype != dns_rdatatype_opt
|
|
|
900526 |
- && rdtype != dns_rdatatype_dnskey /* in a TKEY query */
|
|
|
900526 |
+ && rdtype != dns_rdatatype_key /* in a TKEY query */
|
|
|
900526 |
&& rdtype != dns_rdatatype_sig /* SIG(0) */
|
|
|
900526 |
&& rdtype != dns_rdatatype_tkey /* Win2000 TKEY */
|
|
|
900526 |
&& msg->rdclass != dns_rdataclass_any
|
|
|
900526 |
@@ -1259,6 +1267,16 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|
|
900526 |
DO_FORMERR;
|
|
|
900526 |
|
|
|
900526 |
/*
|
|
|
900526 |
+ * If this is not a TKEY query/response then the KEY
|
|
|
900526 |
+ * record's class needs to match.
|
|
|
900526 |
+ */
|
|
|
900526 |
+ if (msg->opcode != dns_opcode_update && !msg->tkey &&
|
|
|
900526 |
+ rdtype == dns_rdatatype_key &&
|
|
|
900526 |
+ msg->rdclass != dns_rdataclass_any &&
|
|
|
900526 |
+ msg->rdclass != rdclass)
|
|
|
900526 |
+ DO_FORMERR;
|
|
|
900526 |
+
|
|
|
900526 |
+ /*
|
|
|
900526 |
* Special type handling for TSIG, OPT, and TKEY.
|
|
|
900526 |
*/
|
|
|
900526 |
if (rdtype == dns_rdatatype_tsig) {
|
|
|
900526 |
@@ -1372,6 +1390,10 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|
|
900526 |
skip_name_search = ISC_TRUE;
|
|
|
900526 |
skip_type_search = ISC_TRUE;
|
|
|
900526 |
issigzero = ISC_TRUE;
|
|
|
900526 |
+ } else {
|
|
|
900526 |
+ if (msg->rdclass != dns_rdataclass_any &&
|
|
|
900526 |
+ msg->rdclass != rdclass)
|
|
|
900526 |
+ DO_FORMERR;
|
|
|
900526 |
}
|
|
|
900526 |
} else
|
|
|
900526 |
covers = 0;
|
|
|
900526 |
@@ -1610,6 +1632,7 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
|
|
|
900526 |
msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
|
|
|
900526 |
|
|
|
900526 |
msg->header_ok = 1;
|
|
|
900526 |
+ msg->state = DNS_SECTION_QUESTION;
|
|
|
900526 |
|
|
|
900526 |
/*
|
|
|
900526 |
* -1 means no EDNS.
|
|
|
900526 |
@@ -3550,3 +3573,15 @@ dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp,
|
|
|
900526 |
dns_message_puttemprdatalist(message, &rdatalist);
|
|
|
900526 |
return (result);
|
|
|
900526 |
}
|
|
|
900526 |
+
|
|
|
900526 |
+void
|
|
|
900526 |
+dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass) {
|
|
|
900526 |
+
|
|
|
900526 |
+ REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
900526 |
+ REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
|
|
|
900526 |
+ REQUIRE(msg->state == DNS_SECTION_ANY);
|
|
|
900526 |
+ REQUIRE(msg->rdclass_set == 0);
|
|
|
900526 |
+
|
|
|
900526 |
+ msg->rdclass = rdclass;
|
|
|
900526 |
+ msg->rdclass_set = 1;
|
|
|
900526 |
+}
|
|
|
900526 |
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
|
|
|
900526 |
index aa23b11..d220986 100644
|
|
|
900526 |
--- a/lib/dns/resolver.c
|
|
|
900526 |
+++ b/lib/dns/resolver.c
|
|
|
900526 |
@@ -6964,6 +6964,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
|
|
900526 |
goto done;
|
|
|
900526 |
}
|
|
|
900526 |
|
|
|
900526 |
+ dns_message_setclass(message, fctx->res->rdclass);
|
|
|
900526 |
+
|
|
|
900526 |
result = dns_message_parse(message, &devent->buffer, 0);
|
|
|
900526 |
if (result != ISC_R_SUCCESS) {
|
|
|
900526 |
switch (result) {
|
|
|
900526 |
@@ -7036,6 +7038,12 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
|
|
900526 |
*/
|
|
|
900526 |
log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx);
|
|
|
900526 |
|
|
|
900526 |
+ if (message->rdclass != fctx->res->rdclass) {
|
|
|
900526 |
+ resend = ISC_TRUE;
|
|
|
900526 |
+ FCTXTRACE("bad class");
|
|
|
900526 |
+ goto done;
|
|
|
900526 |
+ }
|
|
|
900526 |
+
|
|
|
900526 |
/*
|
|
|
900526 |
* Process receive opt record.
|
|
|
900526 |
*/
|
|
|
900526 |
diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c
|
|
|
900526 |
index 9ad8960..938373a 100644
|
|
|
900526 |
--- a/lib/dns/xfrin.c
|
|
|
900526 |
+++ b/lib/dns/xfrin.c
|
|
|
900526 |
@@ -1241,6 +1241,8 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
|
|
|
900526 |
msg->tsigctx = xfr->tsigctx;
|
|
|
900526 |
xfr->tsigctx = NULL;
|
|
|
900526 |
|
|
|
900526 |
+ dns_message_setclass(msg, xfr->rdclass);
|
|
|
900526 |
+
|
|
|
900526 |
if (xfr->nmsg > 0)
|
|
|
900526 |
msg->tcp_continuation = 1;
|
|
|
900526 |
|