diff --git a/bin/named/client.c b/bin/named/client.c index 6e091c9b3c..4e58ae77c6 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -249,7 +249,6 @@ allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl); static void compute_sit(ns_client_t *client, isc_uint32_t when, isc_uint32_t nonce, isc_buffer_t *buf); #endif -static inline isc_result_t client_addopt(ns_client_t *client); void ns_client_recursing(ns_client_t *client) { @@ -1018,7 +1017,8 @@ client_send(ns_client_t *client) { * Create an OPT for our reply. */ if ((client->attributes & NS_CLIENTATTR_WANTOPT) != 0) { - result = client_addopt(client); + result = ns_client_addopt(client, client->message, + &client->opt); if (result != ISC_R_SUCCESS) goto done; } @@ -1377,8 +1377,10 @@ ns_client_error(ns_client_t *client, isc_result_t result) { ns_client_send(client); } -static inline isc_result_t -client_addopt(ns_client_t *client) { +isc_result_t +ns_client_addopt(ns_client_t *client, dns_message_t *message, + dns_rdataset_t **opt) +{ char nsid[BUFSIZ], *nsidp; #ifdef ISC_PLATFORM_USESIT unsigned char sit[SIT_SIZE]; @@ -1392,7 +1394,9 @@ client_addopt(ns_client_t *client) { unsigned int flags; unsigned char expire[4]; - REQUIRE(client->opt == NULL); /* XXXRTH free old. */ + REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(opt != NULL && *opt == NULL); + REQUIRE(message != NULL); view = client->view; resolver = (view != NULL) ? view->resolver : NULL; @@ -1456,8 +1460,8 @@ client_addopt(ns_client_t *client) { count++; } - result = dns_message_buildopt(client->message, &client->opt, 0, - udpsize, flags, ednsopts, count); + result = dns_message_buildopt(message, opt, 0, udpsize, flags, + ednsopts, count); return (result); } @@ -1748,7 +1752,8 @@ process_opt(ns_client_t *client, dns_rdataset_t *opt) { if (client->ednsversion > 0) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_badednsver); - result = client_addopt(client); + result = ns_client_addopt(client, client->message, + &client->opt); if (result == ISC_R_SUCCESS) result = DNS_R_BADVERS; ns_client_error(client, result); diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index c526fe0a8e..60cb74b638 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -393,4 +393,8 @@ ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey, isc_result_t ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp); +isc_result_t +ns_client_addopt(ns_client_t *client, dns_message_t *message, + dns_rdataset_t **opt); + #endif /* NAMED_CLIENT_H */ diff --git a/bin/named/query.c b/bin/named/query.c index 08c5675cdb..7bd7afcf58 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -6073,7 +6073,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_fixedname_t fixed; dns_fixedname_t wildcardname; dns_dbversion_t *version, *zversion; - dns_zone_t *zone; + dns_zone_t *zone, *raw = NULL, *mayberaw; dns_rdata_cname_t cname; dns_rdata_dname_t dname; unsigned int options; @@ -7864,10 +7864,17 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_name_equal(client->query.qname, dns_rootname)) client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL; + /* + * Return the time to expire for slave zones. + */ + if (is_zone) + dns_zone_getraw(zone, &raw); + mayberaw = (raw != NULL) ? raw : zone; + if (is_zone && qtype == dns_rdatatype_soa && (client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 && client->query.restarts == 0 && - dns_zone_gettype(zone) == dns_zone_slave) { + dns_zone_gettype(mayberaw) == dns_zone_slave) { isc_time_t expiretime; isc_uint32_t secs; dns_zone_getexpiretime(zone, &expiretime); @@ -7877,6 +7884,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) client->expire = secs - client->now; } } + if (raw != NULL) + dns_zone_detach(&raw); if (dns64) { qtype = type = dns_rdatatype_aaaa; diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c index df22aa2d6c..b794949d41 100644 --- a/bin/named/xfrout.c +++ b/bin/named/xfrout.c @@ -729,7 +729,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { isc_result_t result; dns_name_t *question_name; dns_rdataset_t *question_rdataset; - dns_zone_t *zone = NULL; + dns_zone_t *zone = NULL, *raw = NULL, *mayberaw; dns_db_t *db = NULL; dns_dbversion_t *ver = NULL; dns_rdataclass_t question_class; @@ -1083,6 +1083,23 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname, current_serial); + + dns_zone_getraw(zone, &raw); + mayberaw = (raw != NULL) ? raw : zone; + if ((client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 && + dns_zone_gettype(mayberaw) == dns_zone_slave) { + isc_time_t expiretime; + isc_uint32_t secs; + dns_zone_getexpiretime(zone, &expiretime); + secs = isc_time_seconds(&expiretime); + if (secs >= client->now && result == ISC_R_SUCCESS) { + client->attributes |= NS_CLIENTATTR_HAVEEXPIRE; + client->expire = secs - client->now; + } + } + if (raw != NULL) + dns_zone_detach(&raw); + /* * Hand the context over to sendstream(). Set xfr to NULL; * sendstream() is responsible for either passing the @@ -1292,6 +1309,21 @@ sendstream(xfrout_ctx_t *xfr) { if (xfr->lasttsig != NULL) isc_buffer_free(&xfr->lasttsig); + /* + * Add a EDNS option to the message? + */ + if ((xfr->client->attributes & NS_CLIENTATTR_WANTOPT) != 0) { + dns_rdataset_t *opt = NULL; + + CHECK(ns_client_addopt(xfr->client, msg, &opt)); + CHECK(dns_message_setopt(msg, opt)); + /* + * Add to first message only. + */ + xfr->client->attributes &= ~NS_CLIENTATTR_WANTNSID; + xfr->client->attributes &= ~NS_CLIENTATTR_HAVEEXPIRE; + } + /* * Account for reserved space. */