]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3911. [func] Implement EDNS EXPIRE option client side. [RT #35925]
authorMark Andrews <marka@isc.org>
Wed, 6 Aug 2014 01:50:40 +0000 (11:50 +1000)
committerMark Andrews <marka@isc.org>
Wed, 6 Aug 2014 01:50:40 +0000 (11:50 +1000)
17 files changed:
CHANGES
bin/named/config.c
bin/named/server.c
bin/named/zoneconf.c
bin/tests/system/xfer/clean.sh
bin/tests/system/xfer/ns1/named.conf
bin/tests/system/xfer/ns6/named.conf
bin/tests/system/xfer/ns7/named.conf
bin/tests/system/xfer/setup.sh
bin/tests/system/xfer/tests.sh
doc/arm/Bv9ARM-book.xml
lib/bind9/check.c
lib/dns/include/dns/peer.h
lib/dns/include/dns/zone.h
lib/dns/peer.c
lib/dns/zone.c
lib/isccfg/namedconf.c

diff --git a/CHANGES b/CHANGES
index 4b68841dfc7b636b6a0dee157d9e1089231d5b69..1ce4b71ffbc3116339be7d9894cd9d0330b42e18 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+3911.  [func]          Implement EDNS EXPIRE option client side. [RT #35925]
+
 3910.  [bug]           Fix races to free event during shutdown. [RT#36720]
 
 3909.  [bug]           When computing the number of elements required for a
index c841e31e097b95845bef69b95d1d594f6b9b2b42..f7647e76f77390285e784b0b87ae0a0ddd85fb8c 100644 (file)
@@ -143,6 +143,7 @@ options {\n\
        recursion true;\n\
        provide-ixfr true;\n\
        request-ixfr true;\n\
+       request-expire true;\n\
        fetch-glue no;\n\
        rfc2308-type1 no;\n\
        additional-from-auth true;\n\
index 24989cfb52f484aecd611b111c087a55cae5c367..ecb64b91d568cba218dd20170bcf31a1efb30080 100644 (file)
@@ -1177,6 +1177,11 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
        if (obj != NULL)
                CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)));
 
+       obj = NULL;
+       (void)cfg_map_get(cpeer, "request-expire", &obj);
+       if (obj != NULL)
+               CHECK(dns_peer_setrequestexpire(peer, cfg_obj_asboolean(obj)));
+
        obj = NULL;
        (void)cfg_map_get(cpeer, "request-ixfr", &obj);
        if (obj != NULL)
index b3143fa2c199183f08a786f5e9bd71b25547a3d4..18db36822fe1897e1e5082952ebc7fc5550ebd2c 100644 (file)
@@ -1256,6 +1256,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                        dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS,
                                           ixfrdiff);
 
+               obj = NULL;
+               result = ns_config_get(maps, "request-expire", &obj);
+               INSIST(result == ISC_R_SUCCESS);
+               dns_zone_setrequestexpire(zone, cfg_obj_asboolean(obj));
+
                obj = NULL;
                result = ns_config_get(maps, "request-ixfr", &obj);
                INSIST(result == ISC_R_SUCCESS);
index 48aa159137c14913de9122db2e843b9d7cdc08dd..3c9c1f76623ac26804edd03187b622c45295bf79 100644 (file)
@@ -26,6 +26,7 @@ rm -f dig.out.ns5 dig.out.ns6 dig.out.ns7
 rm -f dig.out.soa.ns3
 rm -f axfr.out
 rm -f ns1/slave.db ns2/slave.db
+rm -f ns1/edns-expire.db
 rm -f ns2/example.db ns2/tsigzone.db ns2/example.db.jnl
 rm -f ns3/example.bk ns3/tsigzone.bk ns3/example.bk.jnl
 rm -f ns3/master.bk ns3/master.bk.jnl
index 07dad85d9baa97b3c2bdbb571689457e64421aaa..7d20f12d6e7f4e50cd65b2c2e9cf83db50ff46c6 100644 (file)
@@ -44,3 +44,8 @@ zone "slave" {
        type master;
        file "slave.db";
 };
+
+zone "edns-expire" {
+       type master;
+       file "edns-expire.db";
+};
index c9421b1f6558a20062b29f43f070081711afbaaa..6cccbe4bcd17552d4babb201eee5b06d91cdabe5 100644 (file)
@@ -19,7 +19,7 @@
 include "../../common/rndc.key";
 
 controls {
-        inet 10.53.0.6 port 9953 allow { any; } keys { rndc_key; };
+       inet 10.53.0.6 port 9953 allow { any; } keys { rndc_key; };
 };
 
 options {
@@ -52,3 +52,9 @@ zone "slave" {
        masters { 10.53.0.1; };
        file "slave.bk";
 };
+
+zone "edns-expire" {
+       type slave;
+       masters { 10.53.0.1; };
+       file "edns-expire.bk";
+};
index dcacb08e641f89a695e0ef09cafdc08ccaf012d7..e8f1645b1edf7868650338a0347d794be7feada1 100644 (file)
@@ -51,3 +51,9 @@ zone "slave" {
        masters { 10.53.0.1; };
        file "slave.bk";
 };
+
+zone "edns-expire" {
+        type slave;
+        masters { 10.53.0.6; };
+        file "edns-expire.bk";
+};
index 56ca9018ec28d739a37fac1c20e999540985b2d6..7df04dd4e409a1ae9abd9f6019a3790aef1dbd3c 100644 (file)
@@ -21,6 +21,7 @@ SYSTEMTESTTOP=..
 $SHELL clean.sh
 
 $SHELL ../genzone.sh 1 6 7 >ns1/slave.db
+$SHELL ../genzone.sh 1 6 7 >ns1/edns-expire.db
 $SHELL ../genzone.sh 2 3 >ns2/example.db
 $SHELL ../genzone.sh 2 3 >ns2/tsigzone.db
 $SHELL ../genzone.sh 6 3 >ns6/master.db
index 2afaa0f20a053b6ba4b9285fb8e6079a9caf0152..232c351462674c681b1675f924bce8f8a2ff4104 100644 (file)
@@ -331,5 +331,17 @@ $DIGCMD nil. TXT | grep 'incorrect key AXFR' >/dev/null && {
     status=1
 }
 
+echo "I:check that we ask for and get a EDNS EXPIRE response"
+# force a refresh query
+$RNDC -s 10.53.0.7 -p 9953 -c ../common/rndc.conf refresh edns-expire 2>&1 | sed 's/^/I:ns7 /'
+sleep 10
+
+# there may be multiple log entries so get the last one.
+expire=`awk '/edns-expire\/IN: got EDNS EXPIRE of/ { x=$9 } END { print x }' ns7/named.run`
+test ${expire:-0} -gt 0 -a ${expire:-0} -lt 1814400 || {
+    echo "I:failed (expire=${expire:-0})"
+    status=1
+}
+
 echo "I:exit status: $status"
 exit $status
index bf99f22cc5cc66cdca0db6a1b38fb340c251a7a5..d2acb8e3183af81d0f64dd30506fc1981cf64a3d 100644 (file)
@@ -4934,6 +4934,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
     <optional> use-ixfr <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> provide-ixfr <replaceable>yes_or_no</replaceable>; </optional>
     <optional> request-ixfr <replaceable>yes_or_no</replaceable>; </optional>
+    <optional> request-expire <replaceable>yes_or_no</replaceable>; </optional>
     <optional> treat-cr-as-space <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> min-refresh-time <replaceable>number</replaceable> ; </optional>
     <optional> max-refresh-time <replaceable>number</replaceable> ; </optional>
@@ -6476,6 +6477,17 @@ options {
              </listitem>
            </varlistentry>
 
+           <varlistentry>
+             <term><command>request-expire</command></term>
+             <listitem>
+               <para>
+                 See the description of
+                 <command>request-expire</command> in
+                 <xref linkend="server_statement_definition_and_usage"/>.
+               </para>
+             </listitem>
+           </varlistentry>
+
            <varlistentry>
              <term><command>treat-cr-as-space</command></term>
              <listitem>
@@ -10390,6 +10402,7 @@ rate-limit {
     <optional> bogus <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> provide-ixfr <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> request-ixfr <replaceable>yes_or_no</replaceable> ; </optional>
+    <optional> request-expire <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> request-nsid <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> request-sit <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> edns <replaceable>yes_or_no</replaceable> ; </optional>
@@ -10494,6 +10507,12 @@ rate-limit {
            is buggy and crashes or corrupts data when IXFR is used.
          </para>
 
+         <para>
+           The <command>request-expire</command> clause determines
+           whether the local server, acting as a slave, will request
+           the EDNS EXPIRE value.
+         </para>
+
          <para>
            The <command>edns</command> clause determines whether
            the local server will attempt to use EDNS when communicating
index 0e814012325e7fdb37d87bd6059fc1804af85c66..a8d5e00aa61211cacb94b39ebe002decbc314444 100644 (file)
@@ -1513,6 +1513,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
        { "notify-source", MASTERZONE | SLAVEZONE },
        { "notify-source-v6", MASTERZONE | SLAVEZONE },
        { "pubkey", MASTERZONE | SLAVEZONE | STUBZONE },
+       { "request-expire", SLAVEZONE | REDIRECTZONE },
        { "request-ixfr", SLAVEZONE | REDIRECTZONE },
        { "server-addresses", STATICSTUBZONE },
        { "server-names", STATICSTUBZONE },
@@ -1534,8 +1535,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
        static optionstable dialups[] = {
        { "notify", MASTERZONE | SLAVEZONE | STREDIRECTZONE },
        { "notify-passive", SLAVEZONE | STREDIRECTZONE },
-       { "refresh", SLAVEZONE | STUBZONE | STREDIRECTZONE },
        { "passive", SLAVEZONE | STUBZONE | STREDIRECTZONE },
+       { "refresh", SLAVEZONE | STUBZONE | STREDIRECTZONE },
        };
 
        znamestr = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
index 4374db4570ccf2a8b8783d2b5c0799927c4e8ade..52ea86ef430fa7d08e39df0ef5fab96df654568c 100644 (file)
@@ -75,6 +75,7 @@ struct dns_peer {
        isc_boolean_t           support_edns;
        isc_boolean_t           request_nsid;
        isc_boolean_t           request_sit;
+       isc_boolean_t           request_expire;
        dns_name_t             *key;
        isc_sockaddr_t         *transfer_source;
        isc_dscp_t              transfer_dscp;
@@ -166,6 +167,12 @@ dns_peer_setrequestsit(dns_peer_t *peer, isc_boolean_t newval);
 isc_result_t
 dns_peer_getrequestsit(dns_peer_t *peer, isc_boolean_t *retval);
 
+isc_result_t
+dns_peer_setrequestexpire(dns_peer_t *peer, isc_boolean_t newval);
+
+isc_result_t
+dns_peer_getrequestexpire(dns_peer_t *peer, isc_boolean_t *retval);
+
 isc_result_t
 dns_peer_setsupportedns(dns_peer_t *peer, isc_boolean_t newval);
 
index 5a103636ea0eeb24d8210fc3414f31930c3ff015..3c5e2fd78b3ce7b706c49a4d678c024201bfc713 100644 (file)
@@ -2184,6 +2184,26 @@ dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval);
  * \li 'zone' to be valid.
  */
 
+isc_boolean_t
+dns_zone_getrequestexpire(dns_zone_t *zone);
+/*%
+ * Returns the true/false value of the request-expire option in the zone.
+ *
+ * Requires:
+ * \li 'zone' to be valid.
+ */
+
+void
+dns_zone_setrequestexpire(dns_zone_t *zone, isc_boolean_t flag);
+/*%
+ * Sets the request-expire option for the zone. Either true or false. The
+ * default value is determined by the setting of this option in the view.
+ *
+ * Requires:
+ * \li 'zone' to be valid.
+ */
+
+
 isc_boolean_t
 dns_zone_getrequestixfr(dns_zone_t *zone);
 /*%
index 40520d7614869239e19d60f48fdc85b2806f93cf..4f55f0cdbdbfbcef4093d44fc988b927582e8b9f 100644 (file)
@@ -47,6 +47,7 @@
 #define NOTIFY_DSCP_BIT                 10
 #define TRANSFER_DSCP_BIT               11
 #define QUERY_DSCP_BIT                         12
+#define REQUEST_EXPIRE_BIT              13
 
 static void
 peerlist_delete(dns_peerlist_t **list);
@@ -477,6 +478,32 @@ dns_peer_getrequestsit(dns_peer_t *peer, isc_boolean_t *retval) {
                return (ISC_R_NOTFOUND);
 }
 
+isc_result_t
+dns_peer_setrequestexpire(dns_peer_t *peer, isc_boolean_t newval) {
+       isc_boolean_t existed;
+
+       REQUIRE(DNS_PEER_VALID(peer));
+
+       existed = DNS_BIT_CHECK(REQUEST_EXPIRE_BIT, &peer->bitflags);
+
+       peer->request_expire = newval;
+       DNS_BIT_SET(REQUEST_EXPIRE_BIT, &peer->bitflags);
+
+       return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getrequestexpire(dns_peer_t *peer, isc_boolean_t *retval) {
+       REQUIRE(DNS_PEER_VALID(peer));
+       REQUIRE(retval != NULL);
+
+       if (DNS_BIT_CHECK(REQUEST_EXPIRE_BIT, &peer->bitflags)) {
+               *retval = peer->request_expire;
+               return (ISC_R_SUCCESS);
+       } else
+               return (ISC_R_NOTFOUND);
+}
+
 isc_result_t
 dns_peer_settransfers(dns_peer_t *peer, isc_uint32_t newval) {
        isc_boolean_t existed;
index 43f8b89a152c8cd6b50f74b87b4702223ef3fcbf..b1c0f544e8784ecd2b290c19bc85dc2cde4f9859 100644 (file)
@@ -392,6 +392,11 @@ struct dns_zone {
         */
        isc_boolean_t           requestixfr;
 
+       /*%
+        * whether EDNS EXPIRE is requested
+        */
+       isc_boolean_t           requestexpire;
+
        /*%
         * Outstanding forwarded UPDATE requests.
         */
@@ -999,6 +1004,8 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
        zone->secure = NULL;
        zone->sourceserial = 0;
        zone->sourceserialset = ISC_FALSE;
+       zone->requestixfr = ISC_TRUE;
+       zone->requestexpire = ISC_TRUE;
 
        zone->magic = ZONE_MAGIC;
 
@@ -10934,6 +10941,90 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
        return;
 }
 
+/*
+ * Get the EDNS EXPIRE option from the response and if it exists trim
+ * expire to be not more than it.
+ */
+static void
+get_edns_expire(dns_zone_t * zone, dns_message_t *message,
+               isc_uint32_t *expirep)
+{
+       isc_result_t result;
+       isc_uint32_t expire;
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       isc_buffer_t optbuf;
+       isc_uint16_t optcode;
+       isc_uint16_t optlen;
+
+       REQUIRE(expirep != NULL);
+       REQUIRE(message != NULL);
+
+       if (message->opt == NULL)
+               return;
+
+       result = dns_rdataset_first(message->opt);
+       if (result == ISC_R_SUCCESS) {
+               dns_rdataset_current(message->opt, &rdata);
+               isc_buffer_init(&optbuf, rdata.data, rdata.length);
+               isc_buffer_add(&optbuf, rdata.length);
+               while (isc_buffer_remaininglength(&optbuf) >= 4) {
+                       optcode = isc_buffer_getuint16(&optbuf);
+                       optlen = isc_buffer_getuint16(&optbuf);
+                       /*
+                        * A EDNS EXPIRE response has a length of 4.
+                        */
+                       if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
+                               isc_buffer_forward(&optbuf, optlen);
+                               continue;
+                       }
+                       expire = isc_buffer_getuint32(&optbuf);
+                       dns_zone_log(zone, ISC_LOG_DEBUG(1),
+                                    "got EDNS EXPIRE of %u\n", expire);
+                       /*
+                        * Trim *expirep?
+                        */
+                       if (expire < *expirep)
+                               *expirep = expire;
+                       break;
+               }
+       }
+}
+
+/*
+ * Set the file modification time zone->expire seconds before expiretime.
+ */
+static void
+setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
+       isc_result_t result;
+       isc_time_t when;
+       isc_interval_t i;
+
+       isc_interval_set(&i, zone->expire, 0);
+       result = isc_time_subtract(expiretime, &i, &when);
+       if (result != ISC_R_SUCCESS)
+               return;
+
+       result = ISC_R_FAILURE;
+       if (zone->journal != NULL)
+               result = isc_file_settime(zone->journal, &when);
+       if (result == ISC_R_SUCCESS &&
+           !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
+           !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
+               result = isc_file_settime(zone->masterfile, &when);
+       else if (result != ISC_R_SUCCESS)
+               result = isc_file_settime(zone->masterfile, &when);
+
+       /*
+        * Someone removed the file from underneath us!
+        */
+       if (result == ISC_R_FILENOTFOUND) {
+               zone_needdump(zone, DNS_DUMP_DELAY);
+       } else if (result != ISC_R_SUCCESS)
+               dns_zone_log(zone, ISC_LOG_ERROR, "refresh: could not set "
+                            "file modification time of '%s': %s",
+                            zone->masterfile, dns_result_totext(result));
+}
+
 /*
  * An SOA query has finished (successfully or not).
  */
@@ -11054,6 +11145,15 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
                        DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
                        goto same_master;
                }
+               if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
+                   msg->rcode == dns_rcode_badvers) {
+                       dns_zone_log(zone, ISC_LOG_DEBUG(1),
+                                    "refresh: rcode (%.*s) retrying without "
+                                    "EDNS EXPIRE OPTION master %s (source %s)",
+                                    (int)rb.used, rcode, master, source);
+                       DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
+                       goto same_master;
+               }
                dns_zone_log(zone, ISC_LOG_INFO,
                             "refresh: unexpected rcode (%.*s) from "
                             "master %s (source %s)", (int)rb.used, rcode,
@@ -11219,30 +11319,26 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
                if (msg != NULL)
                        dns_message_destroy(&msg);
        } else if (isc_serial_eq(soa.serial, oldserial)) {
-               if (zone->masterfile != NULL) {
-                       result = ISC_R_FAILURE;
-                       if (zone->journal != NULL)
-                               result = isc_file_settime(zone->journal, &now);
-                       if (result == ISC_R_SUCCESS &&
-                           !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
-                           !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
-                               result = isc_file_settime(zone->masterfile,
-                                                         &now);
-                       } else if (result != ISC_R_SUCCESS)
-                               result = isc_file_settime(zone->masterfile,
-                                                         &now);
-                       /* Someone removed the file from underneath us! */
-                       if (result == ISC_R_FILENOTFOUND) {
-                               zone_needdump(zone, DNS_DUMP_DELAY);
-                       } else if (result != ISC_R_SUCCESS)
-                               dns_zone_log(zone, ISC_LOG_ERROR,
-                                            "refresh: could not set file "
-                                            "modification time of '%s': %s",
-                                            zone->masterfile,
-                                            dns_result_totext(result));
+               isc_time_t expiretime;
+               isc_uint32_t expire;
+
+               /*
+                * Compute the new expire time based on this response.
+                */
+               expire = zone->expire;
+               get_edns_expire(zone, msg, &expire);
+               DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
+
+               /*
+                * Has the expire time improved?
+                */
+               if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
+                       zone->expiretime = expiretime;
+                       if (zone->masterfile != NULL)
+                               setmodtime(zone, &expiretime);
                }
+
                DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
-               DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
                zone->mastersok[zone->curmaster] = ISC_TRUE;
                goto next_master;
        } else {
@@ -11416,7 +11512,9 @@ create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
 }
 
 static isc_result_t
-add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
+add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid,
+       isc_boolean_t reqexpire)
+{
        isc_result_t result;
        dns_rdataset_t *rdataset = NULL;
        dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
@@ -11430,6 +11528,13 @@ add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
                ednsopts[count].value = NULL;
                count++;
        }
+       if (reqexpire) {
+               INSIST(count < DNS_EDNSOPTIONS);
+               ednsopts[count].code = DNS_OPT_EXPIRE;
+               ednsopts[count].length = 0;
+               ednsopts[count].value = NULL;
+               count++;
+       }
        result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
                                      ednsopts, count);
        if (result != ISC_R_SUCCESS)
@@ -11450,7 +11555,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
        isc_uint32_t options;
        isc_boolean_t cancel = ISC_TRUE;
        int timeout;
-       isc_boolean_t have_xfrsource, have_xfrdscp, reqnsid;
+       isc_boolean_t have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
        isc_uint16_t udpsize = SEND_BUFFER_SIZE;
        isc_dscp_t dscp = -1;
 
@@ -11513,6 +11618,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
 
        have_xfrsource = have_xfrdscp = ISC_FALSE;
        reqnsid = zone->view->requestnsid;
+       reqexpire = zone->requestexpire;
        if (zone->view->peers != NULL) {
                dns_peer_t *peer = NULL;
                isc_boolean_t edns;
@@ -11534,6 +11640,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
                                  dns_resolver_getudpsize(zone->view->resolver);
                        (void)dns_peer_getudpsize(peer, &udpsize);
                        (void)dns_peer_getrequestnsid(peer, &reqnsid);
+                       (void)dns_peer_getrequestexpire(peer, &reqexpire);
                }
        }
 
@@ -11575,7 +11682,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
                  DNS_REQUESTOPT_TCP : 0;
 
        if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
-               result = add_opt(message, udpsize, reqnsid);
+               result = add_opt(message, udpsize, reqnsid, reqexpire);
                if (result != ISC_R_SUCCESS)
                        zone_debuglog(zone, me, 1,
                                      "unable to add opt record: %s",
@@ -11790,7 +11897,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
 
        }
        if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
-               result = add_opt(message, udpsize, reqnsid);
+               result = add_opt(message, udpsize, reqnsid, ISC_FALSE);
                if (result != ISC_R_SUCCESS)
                        zone_debuglog(zone, me, 1,
                                      "unable to add opt record: %s",
@@ -17308,6 +17415,18 @@ dns_zone_getrequestixfr(dns_zone_t *zone) {
        return (zone->requestixfr);
 }
 
+void
+dns_zone_setrequestexpire(dns_zone_t *zone, isc_boolean_t flag) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+       zone->requestexpire = flag;
+}
+
+isc_boolean_t
+dns_zone_getrequestexpire(dns_zone_t *zone) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+       return (zone->requestexpire);
+}
+
 void
 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
        REQUIRE(DNS_ZONE_VALID(zone));
index d2f8dc3e9e706db3b574ed258f7897571a4ed8f5..02323781ecb501526d829b990bc18c29d89107a4 100644 (file)
@@ -1675,6 +1675,7 @@ zone_clauses[] = {
        { "notify-to-soa", &cfg_type_boolean, 0 },
        { "nsec3-test-zone", &cfg_type_boolean, CFG_CLAUSEFLAG_TESTONLY },
        { "serial-update-method", &cfg_type_updatemethod, 0 },
+       { "request-expire", &cfg_type_boolean, 0 },
        { "request-ixfr", &cfg_type_boolean, 0 },
        { "sig-signing-nodes", &cfg_type_uint32, 0 },
        { "sig-signing-signatures", &cfg_type_uint32, 0 },
@@ -1851,6 +1852,7 @@ server_clauses[] = {
        { "provide-ixfr", &cfg_type_boolean, 0 },
        { "query-source", &cfg_type_querysource4, 0 },
        { "query-source-v6", &cfg_type_querysource6, 0 },
+       { "request-expire", &cfg_type_boolean, 0 },
        { "request-ixfr", &cfg_type_boolean, 0 },
        { "request-nsid", &cfg_type_boolean, 0 },
 #ifdef ISC_PLATFORM_USESIT