* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.c,v 1.407 2009/10/27 23:05:53 marka Exp $ */
+/* $Id: resolver.c,v 1.408 2009/10/28 18:04:29 each Exp $ */
/*! \file */
}
static isc_result_t
-check_section(void *arg, dns_name_t *addname, dns_rdatatype_t type,
- dns_section_t section)
-{
+check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
fetchctx_t *fctx = arg;
isc_result_t result;
dns_name_t *name;
REQUIRE(VALID_FCTX(fctx));
-#if CHECK_FOR_GLUE_IN_ANSWER
- if (section == DNS_SECTION_ANSWER && type != dns_rdatatype_a)
- return (ISC_R_SUCCESS);
-#endif
-
if (GLUING(fctx))
gluing = ISC_TRUE;
else
gluing = ISC_FALSE;
name = NULL;
rdataset = NULL;
- result = dns_message_findname(fctx->rmessage, section, addname,
- dns_rdatatype_any, 0, &name, NULL);
+ result = dns_message_findname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
+ addname, dns_rdatatype_any, 0, &name,
+ NULL);
if (result == ISC_R_SUCCESS) {
external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
if (type == dns_rdatatype_a) {
return (ISC_R_SUCCESS);
}
-static isc_result_t
-check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
- return (check_section(arg, addname, type, DNS_SECTION_ADDITIONAL));
-}
-
-#ifndef CHECK_FOR_GLUE_IN_ANSWER
-#define CHECK_FOR_GLUE_IN_ANSWER 0
-#endif
-#if CHECK_FOR_GLUE_IN_ANSWER
-static isc_result_t
-check_answer(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
- return (check_section(arg, addname, type, DNS_SECTION_ANSWER));
-}
-#endif
-
static void
chase_additional(fetchctx_t *fctx) {
isc_boolean_t rescan;
/*
* Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
- * If look_in_answer is ISC_TRUE then we look in the answer section
- * for the NS RRset if the query type is NS or look for glue incorrectly
- * returned in the answer section for A and AAAA queries.
+ * If bind8_ns_resp is ISC_TRUE, this is a suspected BIND 8
+ * response to an NS query that should be treated as a referral
+ * even though the NS records occur in the answer section
+ * rather than the authority section.
*/
static isc_result_t
noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
- isc_boolean_t look_in_answer)
+ isc_boolean_t bind8_ns_resp)
{
isc_result_t result;
dns_message_t *message;
dns_rdataset_t *rdataset, *ns_rdataset;
isc_boolean_t aa, negative_response;
dns_rdatatype_t type;
- dns_section_t section;
+ dns_section_t section =
+ bind8_ns_resp ? DNS_SECTION_ANSWER : DNS_SECTION_AUTHORITY;
FCTXTRACE("noanswer_response");
- if (fctx->type == dns_rdatatype_ns && look_in_answer)
- section = DNS_SECTION_ANSWER;
- else
- section = DNS_SECTION_AUTHORITY;
-
message = fctx->rmessage;
/*
fctx->attributes |= FCTX_ATTR_GLUING;
(void)dns_rdataset_additionaldata(ns_rdataset, check_related,
fctx);
-#if CHECK_FOR_GLUE_IN_ANSWER
- /*
- * Look in the answer section for "glue" that is incorrectly
- * returned as a answer. This is needed if the server also
- * minimizes the response size by not adding records to the
- * additional section that are in the answer section or if
- * the record gets dropped due to message size constraints.
- */
- if (look_in_answer &&
- (fctx->type == dns_rdatatype_aaaa ||
- fctx->type == dns_rdatatype_a))
- (void)dns_rdataset_additionaldata(ns_rdataset,
- check_answer, fctx);
-#endif
fctx->attributes &= ~FCTX_ATTR_GLUING;
/*
* NS rdatasets with 0 TTL cause problems.
isc_mem_put(mctx, buf, len);
}
-static isc_boolean_t
-iscname(fetchctx_t *fctx) {
- isc_result_t result;
-
- result = dns_message_findname(fctx->rmessage, DNS_SECTION_ANSWER,
- &fctx->name, dns_rdatatype_cname, 0,
- NULL, NULL);
- return (result == ISC_R_SUCCESS ? ISC_TRUE : ISC_FALSE);
-}
-
static void
resquery_response(isc_task_t *task, isc_event_t *event) {
isc_result_t result = ISC_R_SUCCESS;
(message->rcode == dns_rcode_noerror ||
message->rcode == dns_rcode_nxdomain)) {
/*
- * [normal case]
- * We've got answers. If it has an authoritative answer or an
- * answer from a forwarder, we're done.
+ * We've got answers. However, if we sent
+ * a BIND 8 server an NS query, it may have
+ * incorrectly responded with a non-authoritative
+ * answer instead of a referral. Since this
+ * answer lacks the SIGs necessary to do DNSSEC
+ * validation, we must invoke the following special
+ * kludge to treat it as a referral.
*/
- if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 ||
- ISFORWARDER(query->addrinfo))
- result = answer_response(fctx);
- else if (iscname(fctx) &&
- fctx->type != dns_rdatatype_any &&
- fctx->type != dns_rdatatype_cname) {
- /*
- * A BIND8 server could return a non-authoritative
- * answer when a CNAME is followed. We should treat
- * it as a valid answer.
- */
- result = answer_response(fctx);
- } else {
- if (fctx->type == dns_rdatatype_ns) {
- /*
- * A BIND 8 server could incorrectly return a
- * non-authoritative answer to an NS query
- * instead of a referral. Since this answer
- * lacks the SIGs necessary to do DNSSEC
- * validation, we must invoke the following
- * special kludge to treat it as a referral.
- */
- result = noanswer_response(fctx, NULL,
- ISC_TRUE);
- } else {
- /*
- * Some other servers may still somehow include
- * an answer when it should return a referral
- * with an empty answer. Check to see if we can
- * treat this as a referral by ignoring the
- * answer.
- */
- result = noanswer_response(fctx, NULL,
- ISC_TRUE);
- }
+ if (fctx->type == dns_rdatatype_ns &&
+ (message->flags & DNS_MESSAGEFLAG_AA) == 0 &&
+ !ISFORWARDER(query->addrinfo))
+ {
+ result = noanswer_response(fctx, NULL, ISC_TRUE);
if (result != DNS_R_DELEGATION) {
/*
- * At this point, AA is not set, the response
- * is not a referral, and the server is not a
- * forwarder. It is technically lame and it's
- * easier to treat it as such than to figure out
+ * The answer section must have contained
+ * something other than the NS records
+ * we asked for. Since AA is not set
+ * and the server is not a forwarder,
+ * it is technically lame and it's easier
+ * to treat it as such than to figure out
* some more elaborate course of action.
*/
broken_server = DNS_R_LAME;
}
goto force_referral;
}
+ result = answer_response(fctx);
if (result != ISC_R_SUCCESS) {
if (result == DNS_R_FORMERR)
keep_trying = ISC_TRUE;