From 43b9737b11f4f14b2d378746d0cd5561b1dc24a0 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 6 Aug 2014 11:50:40 +1000 Subject: [PATCH] 3911. [func] Implement EDNS EXPIRE option client side. [RT #35925] --- CHANGES | 2 + bin/named/config.c | 1 + bin/named/server.c | 5 + bin/named/zoneconf.c | 5 + bin/tests/system/xfer/clean.sh | 1 + bin/tests/system/xfer/ns1/named.conf | 5 + bin/tests/system/xfer/ns6/named.conf | 8 +- bin/tests/system/xfer/ns7/named.conf | 6 + bin/tests/system/xfer/setup.sh | 1 + bin/tests/system/xfer/tests.sh | 12 ++ doc/arm/Bv9ARM-book.xml | 19 +++ lib/bind9/check.c | 3 +- lib/dns/include/dns/peer.h | 7 ++ lib/dns/include/dns/zone.h | 20 ++++ lib/dns/peer.c | 27 +++++ lib/dns/zone.c | 171 +++++++++++++++++++++++---- lib/isccfg/namedconf.c | 2 + 17 files changed, 267 insertions(+), 28 deletions(-) diff --git a/CHANGES b/CHANGES index 4b68841dfc..1ce4b71ffb 100644 --- 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 diff --git a/bin/named/config.c b/bin/named/config.c index c841e31e09..f7647e76f7 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -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\ diff --git a/bin/named/server.c b/bin/named/server.c index 24989cfb52..ecb64b91d5 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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) diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index b3143fa2c1..18db36822f 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -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); diff --git a/bin/tests/system/xfer/clean.sh b/bin/tests/system/xfer/clean.sh index 48aa159137..3c9c1f7662 100644 --- a/bin/tests/system/xfer/clean.sh +++ b/bin/tests/system/xfer/clean.sh @@ -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 diff --git a/bin/tests/system/xfer/ns1/named.conf b/bin/tests/system/xfer/ns1/named.conf index 07dad85d9b..7d20f12d6e 100644 --- a/bin/tests/system/xfer/ns1/named.conf +++ b/bin/tests/system/xfer/ns1/named.conf @@ -44,3 +44,8 @@ zone "slave" { type master; file "slave.db"; }; + +zone "edns-expire" { + type master; + file "edns-expire.db"; +}; diff --git a/bin/tests/system/xfer/ns6/named.conf b/bin/tests/system/xfer/ns6/named.conf index c9421b1f65..6cccbe4bcd 100644 --- a/bin/tests/system/xfer/ns6/named.conf +++ b/bin/tests/system/xfer/ns6/named.conf @@ -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"; +}; diff --git a/bin/tests/system/xfer/ns7/named.conf b/bin/tests/system/xfer/ns7/named.conf index dcacb08e64..e8f1645b1e 100644 --- a/bin/tests/system/xfer/ns7/named.conf +++ b/bin/tests/system/xfer/ns7/named.conf @@ -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"; +}; diff --git a/bin/tests/system/xfer/setup.sh b/bin/tests/system/xfer/setup.sh index 56ca9018ec..7df04dd4e4 100644 --- a/bin/tests/system/xfer/setup.sh +++ b/bin/tests/system/xfer/setup.sh @@ -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 diff --git a/bin/tests/system/xfer/tests.sh b/bin/tests/system/xfer/tests.sh index 2afaa0f20a..232c351462 100644 --- a/bin/tests/system/xfer/tests.sh +++ b/bin/tests/system/xfer/tests.sh @@ -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 diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index bf99f22cc5..d2acb8e318 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -4934,6 +4934,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] use-ixfr yes_or_no ; provide-ixfr yes_or_no; request-ixfr yes_or_no; + request-expire yes_or_no; treat-cr-as-space yes_or_no ; min-refresh-time number ; max-refresh-time number ; @@ -6476,6 +6477,17 @@ options { + + request-expire + + + See the description of + request-expire in + . + + + + treat-cr-as-space @@ -10390,6 +10402,7 @@ rate-limit { bogus yes_or_no ; provide-ixfr yes_or_no ; request-ixfr yes_or_no ; + request-expire yes_or_no ; request-nsid yes_or_no ; request-sit yes_or_no ; edns yes_or_no ; @@ -10494,6 +10507,12 @@ rate-limit { is buggy and crashes or corrupts data when IXFR is used. + + The request-expire clause determines + whether the local server, acting as a slave, will request + the EDNS EXPIRE value. + + The edns clause determines whether the local server will attempt to use EDNS when communicating diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 0e81401232..a8d5e00aa6 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -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")); diff --git a/lib/dns/include/dns/peer.h b/lib/dns/include/dns/peer.h index 4374db4570..52ea86ef43 100644 --- a/lib/dns/include/dns/peer.h +++ b/lib/dns/include/dns/peer.h @@ -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); diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 5a103636ea..3c5e2fd78b 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -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); /*% diff --git a/lib/dns/peer.c b/lib/dns/peer.c index 40520d7614..4f55f0cdbd 100644 --- a/lib/dns/peer.c +++ b/lib/dns/peer.c @@ -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; diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 43f8b89a15..b1c0f544e8 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -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)); diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index d2f8dc3e9e..02323781ec 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -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