]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
extend:
authorMark Andrews <marka@isc.org>
Tue, 14 Feb 2012 00:24:56 +0000 (00:24 +0000)
committerMark Andrews <marka@isc.org>
Tue, 14 Feb 2012 00:24:56 +0000 (00:24 +0000)
3282.   [bug]           Restrict the TTL of NS RRset to no more than that
                        of the old NS RRset when replacing it.
                        [RT #27792] [RT #27884]

CHANGES
lib/dns/resolver.c

diff --git a/CHANGES b/CHANGES
index ded4d3f82e4f8009bf060d41db2368701d208750..7406916478a53ed9efaf1d864d308de96eae54ee 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,7 +2,8 @@
                        failed to load. [RT #27863]
 
 3282.  [bug]           Restrict the TTL of NS RRset to no more than that
-                       of the old NS RRset when replacing it. [RT #27792]
+                       of the old NS RRset when replacing it.
+                       [RT #27792] [RT #27884]
 
 3281.  [bug]           SOA refresh queries could be treated as cancelled
                        despite succeeding over the loopback interface.
index 66fa4f861c840c2684662eef07953ea321bd5950..e95845be14658d969ed6eeb34db6542485abac72 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.c,v 1.446 2011/12/07 23:08:42 marka Exp $ */
+/* $Id: resolver.c,v 1.446.38.1 2012/02/14 00:24:56 marka Exp $ */
 
 /*! \file */
 
@@ -216,6 +216,8 @@ struct fetchctx {
        ISC_LIST(dns_validator_t)       validators;
        dns_db_t *                      cache;
        dns_adb_t *                     adb;
+       isc_boolean_t                   ns_ttl_ok;
+       isc_uint32_t                    ns_ttl;
 
        /*%
         * The number of events we're waiting for.
@@ -3443,6 +3445,20 @@ fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
        return (ISC_R_SUCCESS);
 }
 
+static inline void
+log_ns_ttl(fetchctx_t *fctx, const char *where) {
+       char namebuf[DNS_NAME_FORMATSIZE];
+       char domainbuf[DNS_NAME_FORMATSIZE];
+
+       dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
+       dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
+       isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+                     DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
+                     "log_ns_ttl: fctx %p: %s: %s (in '%s'?): %u %u",
+                     fctx, where, namebuf, domainbuf,
+                     fctx->ns_ttl_ok, fctx->ns_ttl);
+}
+
 static isc_result_t
 fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
            dns_name_t *domain, dns_rdataset_t *nameservers,
@@ -3536,6 +3552,8 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
        fctx->timeout = ISC_FALSE;
        fctx->addrinfo = NULL;
        fctx->client = NULL;
+       fctx->ns_ttl = 0;
+       fctx->ns_ttl_ok = ISC_FALSE;
 
        dns_name_init(&fctx->nsname, NULL);
        fctx->nsfetch = NULL;
@@ -3585,6 +3603,8 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
                                dns_rdataset_disassociate(&fctx->nameservers);
                                goto cleanup_name;
                        }
+                       fctx->ns_ttl = fctx->nameservers.ttl;
+                       fctx->ns_ttl_ok = ISC_TRUE;
                } else {
                        /*
                         * We're in forward-only mode.  Set the query domain.
@@ -3602,8 +3622,12 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
                if (result != ISC_R_SUCCESS)
                        goto cleanup_name;
                dns_rdataset_clone(nameservers, &fctx->nameservers);
+               fctx->ns_ttl = fctx->nameservers.ttl;
+               fctx->ns_ttl_ok = ISC_TRUE;
        }
 
+       log_ns_ttl(fctx, "fctx_create");
+
        INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
 
        fctx->qmessage = NULL;
@@ -5280,6 +5304,26 @@ is_answertarget_allowed(dns_view_t *view, dns_name_t *name,
        return (ISC_TRUE);
 }
 
+static void
+trim_ns_ttl(fetchctx_t *fctx, dns_name_t *name, dns_rdataset_t *rdataset) {
+       char ns_namebuf[DNS_NAME_FORMATSIZE];
+       char namebuf[DNS_NAME_FORMATSIZE];
+       char tbuf[DNS_RDATATYPE_FORMATSIZE];
+
+       if (fctx->ns_ttl_ok && rdataset->ttl > fctx->ns_ttl) {
+               dns_name_format(name, ns_namebuf, sizeof(ns_namebuf));
+               dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
+               dns_rdatatype_format(fctx->type, tbuf, sizeof(tbuf));
+
+               isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+                             DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
+                             "fctx %p: trimming ttl of %s/NS for %s/%s: "
+                             "%u -> %u", fctx, ns_namebuf, namebuf, tbuf,
+                             rdataset->ttl, fctx->ns_ttl);
+               rdataset->ttl = fctx->ns_ttl;
+       }
+}
+
 /*
  * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
  * If look_in_options has LOOK_FOR_NS_IN_ANSWER then we look in the answer
@@ -5466,6 +5510,12 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
                        return (result);
        }
 
+       log_ns_ttl(fctx, "noanswer_response");
+
+       if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
+            !dns_name_equal(ns_name, dns_rootname))
+               trim_ns_ttl(fctx, ns_name, ns_rdataset);
+
        /*
         * A negative response has a SOA record (Type 2)
         * and a optional NS RRset (Type 1) or it has neither
@@ -5684,6 +5734,8 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
                if (result != ISC_R_SUCCESS)
                        return (result);
                fctx->attributes |= FCTX_ATTR_WANTCACHE;
+               fctx->ns_ttl_ok = ISC_FALSE;
+               log_ns_ttl(fctx, "DELEGATION");
                return (DNS_R_DELEGATION);
        }
 
@@ -5704,8 +5756,8 @@ static isc_result_t
 answer_response(fetchctx_t *fctx) {
        isc_result_t result;
        dns_message_t *message;
-       dns_name_t *name, *qname, tname;
-       dns_rdataset_t *rdataset;
+       dns_name_t *name, *qname, tname, *ns_name;
+       dns_rdataset_t *rdataset, *ns_rdataset;
        isc_boolean_t done, external, chaining, aa, found, want_chaining;
        isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
        unsigned int aflag;
@@ -6105,6 +6157,8 @@ answer_response(fetchctx_t *fctx) {
         * in this section, and we expect that it is not external.
         */
        done = ISC_FALSE;
+       ns_name = NULL;
+       ns_rdataset = NULL;
        result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
        while (!done && result == ISC_R_SUCCESS) {
                name = NULL;
@@ -6132,6 +6186,10 @@ answer_response(fetchctx_t *fctx) {
                                                rdataset->trust =
                                                    dns_trust_additional;
 
+                                       if (rdataset->type == dns_rdatatype_ns) {
+                                               ns_name = name;
+                                               ns_rdataset = rdataset;
+                                       }
                                        /*
                                         * Mark any additional data related
                                         * to this rdataset.
@@ -6149,6 +6207,12 @@ answer_response(fetchctx_t *fctx) {
        if (result == ISC_R_NOMORE)
                result = ISC_R_SUCCESS;
 
+       log_ns_ttl(fctx, "answer_response");
+
+       if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
+            !dns_name_equal(ns_name, dns_rootname))
+               trim_ns_ttl(fctx, ns_name, ns_rdataset);
+
        return (result);
 }
 
@@ -6220,6 +6284,9 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
                if (dns_rdataset_isassociated(&fctx->nameservers))
                        dns_rdataset_disassociate(&fctx->nameservers);
                dns_rdataset_clone(fevent->rdataset, &fctx->nameservers);
+               fctx->ns_ttl = fctx->nameservers.ttl;
+               fctx->ns_ttl_ok = ISC_TRUE;
+               log_ns_ttl(fctx, "resume_dslookup");
                dns_name_free(&fctx->domain,
                              fctx->res->buckets[bucketnum].mctx);
                dns_name_init(&fctx->domain, NULL);
@@ -7153,6 +7220,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
                                fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
                                return;
                        }
+                       fctx->ns_ttl = fctx->nameservers.ttl;
+                       fctx->ns_ttl_ok = ISC_TRUE;
                        fctx_cancelqueries(fctx, ISC_TRUE);
                        fctx_cleanupfinds(fctx);
                        fctx_cleanupaltfinds(fctx);