]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1804. [bug] Ensure that if we are queried for glue that it fits
authorMark Andrews <marka@isc.org>
Tue, 15 Mar 2005 01:29:10 +0000 (01:29 +0000)
committerMark Andrews <marka@isc.org>
Tue, 15 Mar 2005 01:29:10 +0000 (01:29 +0000)
                        in the additional section or TC is set to tell the
                        client to retry using TCP. [RT #10114]

CHANGES
bin/named/query.c
lib/dns/include/dns/rdataset.h
lib/dns/message.c

diff --git a/CHANGES b/CHANGES
index b2fa4d3545438865740362138465893d4ca84dc9..a31feab48431571aab5880e29316bcafe09c95bd 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -54,7 +54,9 @@
 1805.  [bug]           Pending status was not being cleared when DLV was
                        active. [RT #13501]
 
-1804.  [placeholder]   rt10114
+1804.  [bug]           Ensure that if we are queried for glue that it fits
+                       in the additional section or TC is set to tell the
+                       client to retry using TCP. [RT #10114]
 
 1803.  [placeholder]   rt13483
 
index 62f9ffacea2e3142e263fea2a1686a5ddf6b2521..119ecbc4763acec9855d9ae09cbc96880abe3248 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: query.c,v 1.262 2004/12/21 10:45:15 jinmei Exp $ */
+/* $Id: query.c,v 1.263 2005/03/15 01:29:09 marka Exp $ */
 
 #include <config.h>
 
@@ -2886,6 +2886,34 @@ query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
                 query_releasename(client, &fname);
 }
 
+static inline void
+answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) {
+       dns_name_t *name;
+       dns_message_t *msg;
+       dns_section_t section = DNS_SECTION_ADDITIONAL;
+       dns_rdataset_t *rdataset = NULL;
+
+       msg = client->message;
+       for (name = ISC_LIST_HEAD(msg->sections[section]);
+            name != NULL;
+            name = ISC_LIST_NEXT(name, link))
+               if (dns_name_equal(name, client->query.qname)) {
+                       for (rdataset = ISC_LIST_HEAD(name->list);
+                            rdataset != NULL;
+                            rdataset = ISC_LIST_NEXT(rdataset, link))
+                               if (rdataset->type == qtype)
+                                       break;
+                       break;
+               }
+       if (rdataset != NULL) {
+               ISC_LIST_UNLINK(msg->sections[section], name, link);
+               ISC_LIST_PREPEND(msg->sections[section], name, link);
+               ISC_LIST_UNLINK(name->list, rdataset, link);
+               ISC_LIST_PREPEND(name->list, rdataset, link);
+               rdataset->attributes |= DNS_RDATASETATTR_REQUIREDGLUE;
+       }
+}
+
 /*
  * Do the bulk of query processing for the current query of 'client'.
  * If 'event' is non-NULL, we are returning from recursion and 'qtype'
@@ -3906,6 +3934,16 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                 */
                setup_query_sortlist(client);
 
+               /*
+                * If this is a referral and the answer to the question
+                * is in the glue sort it to the start of the additional
+                * section.
+                */
+               if (client->message->counts[DNS_SECTION_ANSWER] == 0 &&
+                   client->message->rcode == dns_rcode_noerror &&
+                   (qtype == dns_rdatatype_a || qtype == dns_rdatatype_aaaa))
+                       answer_in_glue(client, qtype);
+
                if (client->message->rcode == dns_rcode_nxdomain &&
                    client->view->auth_nxdomain == ISC_TRUE)
                        client->message->flags |= DNS_MESSAGEFLAG_AA;
index a286600bad54b09fd76ef2de3877d538408acba6..1b932d8e19fcd5ea0c414e959b47c04b9d74dd8a 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rdataset.h,v 1.52 2004/12/21 10:45:19 jinmei Exp $ */
+/* $Id: rdataset.h,v 1.53 2005/03/15 01:29:10 marka Exp $ */
 
 #ifndef DNS_RDATASET_H
 #define DNS_RDATASET_H 1
@@ -161,22 +161,23 @@ struct dns_rdataset {
  *     Used by message.c to indicate that the rdataset's rdata had differing
  *     TTL values, and the rdataset->ttl holds the smallest.
  */
-#define DNS_RDATASETATTR_QUESTION      0x0001
-#define DNS_RDATASETATTR_RENDERED      0x0002          /* Used by message.c */
-#define DNS_RDATASETATTR_ANSWERED      0x0004          /* Used by server. */
-#define DNS_RDATASETATTR_CACHE         0x0008          /* Used by resolver. */
-#define DNS_RDATASETATTR_ANSWER                0x0010          /* Used by resolver. */
-#define DNS_RDATASETATTR_ANSWERSIG     0x0020          /* Used by resolver. */
-#define DNS_RDATASETATTR_EXTERNAL      0x0040          /* Used by resolver. */
-#define DNS_RDATASETATTR_NCACHE                0x0080          /* Used by resolver. */
-#define DNS_RDATASETATTR_CHAINING      0x0100          /* Used by resolver. */
-#define DNS_RDATASETATTR_TTLADJUSTED   0x0200          /* Used by message.c */
-#define DNS_RDATASETATTR_FIXEDORDER    0x0400
-#define DNS_RDATASETATTR_RANDOMIZE     0x0800
-#define DNS_RDATASETATTR_CHASE         0x1000          /* Used by resolver. */
-#define DNS_RDATASETATTR_NXDOMAIN      0x2000
-#define DNS_RDATASETATTR_NOQNAME       0x4000
-#define DNS_RDATASETATTR_CHECKNAMES    0x8000          /* Used by resolver. */
+#define DNS_RDATASETATTR_QUESTION      0x00000001
+#define DNS_RDATASETATTR_RENDERED      0x00000002      /* Used by message.c */
+#define DNS_RDATASETATTR_ANSWERED      0x00000004      /* Used by server. */
+#define DNS_RDATASETATTR_CACHE         0x00000008      /* Used by resolver. */
+#define DNS_RDATASETATTR_ANSWER                0x00000010      /* Used by resolver. */
+#define DNS_RDATASETATTR_ANSWERSIG     0x00000020      /* Used by resolver. */
+#define DNS_RDATASETATTR_EXTERNAL      0x00000040      /* Used by resolver. */
+#define DNS_RDATASETATTR_NCACHE                0x00000080      /* Used by resolver. */
+#define DNS_RDATASETATTR_CHAINING      0x00000100      /* Used by resolver. */
+#define DNS_RDATASETATTR_TTLADJUSTED   0x00000200      /* Used by message.c */
+#define DNS_RDATASETATTR_FIXEDORDER    0x00000400
+#define DNS_RDATASETATTR_RANDOMIZE     0x00000800
+#define DNS_RDATASETATTR_CHASE         0x00001000      /* Used by resolver. */
+#define DNS_RDATASETATTR_NXDOMAIN      0x00002000
+#define DNS_RDATASETATTR_NOQNAME       0x00004000
+#define DNS_RDATASETATTR_CHECKNAMES    0x00008000      /* Used by resolver. */
+#define DNS_RDATASETATTR_REQUIREDGLUE  0x00010000
 
 /*
  * _OMITDNSSEC:
index e13c544f983abe13fe87617ef7d4e4a4c5ee831f..735e72b03826f344de80dc0a81b8e98e8ef281ff 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: message.c,v 1.223 2004/05/05 01:32:58 marka Exp $ */
+/* $Id: message.c,v 1.224 2005/03/15 01:29:09 marka Exp $ */
 
 /***
  *** Imports
@@ -1783,6 +1783,57 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
        if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0)
                partial = ISC_TRUE;
 
+       /*
+        * Render required glue first.  Set TC if it won't fit.
+        */
+       name = ISC_LIST_HEAD(*section);
+       if (name != NULL) {
+               rdataset = ISC_LIST_HEAD(name->list);
+               if (rdataset != NULL &&
+                   (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 &&
+                   (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) {
+                       void *order_arg = msg->order_arg;
+                       st = *(msg->buffer);
+                       count = 0;
+                       if (partial)
+                               result = dns_rdataset_towirepartial(rdataset,
+                                                                   name,
+                                                                   msg->cctx,
+                                                                   msg->buffer,
+                                                                   msg->order,
+                                                                   order_arg,
+                                                                   rd_options,
+                                                                   &count,
+                                                                   NULL);
+                       else
+                               result = dns_rdataset_towiresorted(rdataset,
+                                                                  name,
+                                                                  msg->cctx,
+                                                                  msg->buffer,
+                                                                  msg->order,
+                                                                  order_arg,
+                                                                  rd_options,
+                                                                  &count);
+                       total += count;
+                       if (partial && result == ISC_R_NOSPACE) {
+                               msg->flags |= DNS_MESSAGEFLAG_TC;
+                               msg->buffer->length += msg->reserved;
+                               msg->counts[sectionid] += total;
+                               return (result);
+                       }
+                       if (result != ISC_R_SUCCESS) {
+                               INSIST(st.used < 65536);
+                               dns_compress_rollback(msg->cctx,
+                                                     (isc_uint16_t)st.used);
+                               *(msg->buffer) = st;  /* rollback */
+                               msg->buffer->length += msg->reserved;
+                               msg->counts[sectionid] += total;
+                               return (result);
+                       }
+                       rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
+               }
+       }
+
        do {
                name = ISC_LIST_HEAD(*section);
                if (name == NULL) {