mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
1226. [func] Use EDNS for zone refresh queries. [RT #2551]
This commit is contained in:
149
lib/dns/zone.c
149
lib/dns/zone.c
@@ -15,7 +15,7 @@
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: zone.c,v 1.363 2002/02/20 03:34:24 marka Exp $ */
|
||||
/* $Id: zone.c,v 1.364 2002/03/11 04:41:53 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -256,6 +256,7 @@ struct dns_zone {
|
||||
#define DNS_ZONEFLG_SHUTDOWN 0x00080000U
|
||||
#define DNS_ZONEFLAG_NOIXFR 0x00100000U /* IXFR failed, force AXFR */
|
||||
#define DNS_ZONEFLG_FLUSH 0x00200000U
|
||||
#define DNS_ZONEFLG_NOEDNS 0x00400000U
|
||||
|
||||
#define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
|
||||
|
||||
@@ -362,6 +363,8 @@ struct dns_io {
|
||||
isc_event_t *event;
|
||||
};
|
||||
|
||||
#define SEND_BUFFER_SIZE 2048
|
||||
|
||||
static void zone_settimer(dns_zone_t *, isc_time_t *);
|
||||
static void cancel_refresh(dns_zone_t *);
|
||||
static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
|
||||
@@ -2133,6 +2136,7 @@ dns_zone_refresh(dns_zone_t *zone) {
|
||||
goto unlock;
|
||||
}
|
||||
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
|
||||
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
|
||||
if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
|
||||
goto unlock;
|
||||
|
||||
@@ -3086,6 +3090,16 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
|
||||
isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
|
||||
|
||||
if (revent->result != ISC_R_SUCCESS) {
|
||||
if (revent->result == ISC_R_TIMEDOUT &&
|
||||
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
|
||||
LOCK_ZONE(zone);
|
||||
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
|
||||
UNLOCK_ZONE(zone);
|
||||
dns_zone_log(zone, ISC_LOG_DEBUG(1),
|
||||
"refreshing stub: timeout retrying "
|
||||
" without EDNS master %s", master);
|
||||
goto same_master;
|
||||
}
|
||||
dns_zone_log(zone, ISC_LOG_INFO,
|
||||
"could not refresh stub from master %s: %s",
|
||||
master, dns_result_totext(revent->result));
|
||||
@@ -3110,6 +3124,20 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
|
||||
isc_buffer_init(&rb, rcode, sizeof(rcode));
|
||||
(void)dns_rcode_totext(msg->rcode, &rb);
|
||||
|
||||
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
|
||||
(msg->rcode == dns_rcode_servfail ||
|
||||
msg->rcode == dns_rcode_notimp ||
|
||||
msg->rcode == dns_rcode_formerr)) {
|
||||
dns_zone_log(zone, ISC_LOG_DEBUG(1),
|
||||
"refreshing stub: rcode (%.*s) retrying "
|
||||
"without EDNS master %s",
|
||||
(int)rb.used, rcode, master);
|
||||
LOCK_ZONE(zone);
|
||||
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
|
||||
UNLOCK_ZONE(zone);
|
||||
goto same_master;
|
||||
}
|
||||
|
||||
dns_zone_log(zone, ISC_LOG_INFO,
|
||||
"refreshing stub: "
|
||||
"unexpected rcode (%.*s) from %s",
|
||||
@@ -3213,6 +3241,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
|
||||
LOCK_ZONE(zone);
|
||||
dns_request_destroy(&zone->request);
|
||||
zone->curmaster++;
|
||||
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
|
||||
if (exiting || zone->curmaster >= zone->masterscnt) {
|
||||
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
|
||||
|
||||
@@ -3280,6 +3309,16 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
||||
TIME_NOW(&now);
|
||||
|
||||
if (revent->result != ISC_R_SUCCESS) {
|
||||
if (revent->result == ISC_R_TIMEDOUT &&
|
||||
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
|
||||
LOCK_ZONE(zone);
|
||||
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
|
||||
UNLOCK_ZONE(zone);
|
||||
dns_zone_log(zone, ISC_LOG_DEBUG(1),
|
||||
"refresh: timeout retrying without EDNS "
|
||||
"master %s", master);
|
||||
goto same_master;
|
||||
}
|
||||
if (revent->result == ISC_R_TIMEDOUT &&
|
||||
!dns_request_usedtcp(revent->request)) {
|
||||
dns_zone_log(zone, ISC_LOG_INFO,
|
||||
@@ -3314,6 +3353,19 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
||||
isc_buffer_init(&rb, rcode, sizeof(rcode));
|
||||
(void)dns_rcode_totext(msg->rcode, &rb);
|
||||
|
||||
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
|
||||
(msg->rcode == dns_rcode_servfail ||
|
||||
msg->rcode == dns_rcode_notimp ||
|
||||
msg->rcode == dns_rcode_formerr)) {
|
||||
dns_zone_log(zone, ISC_LOG_DEBUG(1),
|
||||
"refresh: rcode (%.*s) retrying without "
|
||||
"EDNS master %s", (int)rb.used, rcode,
|
||||
master);
|
||||
LOCK_ZONE(zone);
|
||||
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
|
||||
UNLOCK_ZONE(zone);
|
||||
goto same_master;
|
||||
}
|
||||
dns_zone_log(zone, ISC_LOG_INFO,
|
||||
"refresh: unexpected rcode (%.*s) from master %s",
|
||||
(int)rb.used, rcode, master);
|
||||
@@ -3481,6 +3533,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
||||
LOCK_ZONE(zone);
|
||||
dns_request_destroy(&zone->request);
|
||||
zone->curmaster++;
|
||||
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
|
||||
if (zone->curmaster >= zone->masterscnt) {
|
||||
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
|
||||
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
|
||||
@@ -3598,6 +3651,64 @@ create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
add_opt(dns_message_t *message) {
|
||||
dns_rdataset_t *rdataset = NULL;
|
||||
dns_rdatalist_t *rdatalist = NULL;
|
||||
dns_rdata_t *rdata = NULL;
|
||||
isc_result_t result;
|
||||
|
||||
result = dns_message_gettemprdatalist(message, &rdatalist);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
result = dns_message_gettemprdata(message, &rdata);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
result = dns_message_gettemprdataset(message, &rdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
dns_rdataset_init(rdataset);
|
||||
|
||||
rdatalist->type = dns_rdatatype_opt;
|
||||
rdatalist->covers = 0;
|
||||
|
||||
/*
|
||||
* Set Maximum UDP buffer size.
|
||||
*/
|
||||
rdatalist->rdclass = SEND_BUFFER_SIZE;
|
||||
|
||||
/*
|
||||
* Set EXTENDED-RCODE, VERSION, DO and Z to 0.
|
||||
*/
|
||||
rdatalist->ttl = 0;
|
||||
|
||||
/*
|
||||
* No EDNS options.
|
||||
*/
|
||||
rdata->data = NULL;
|
||||
rdata->length = 0;
|
||||
rdata->rdclass = rdatalist->rdclass;
|
||||
rdata->type = rdatalist->type;
|
||||
rdata->flags = 0;
|
||||
|
||||
ISC_LIST_INIT(rdatalist->rdata);
|
||||
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
|
||||
RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
|
||||
== ISC_R_SUCCESS);
|
||||
|
||||
return (dns_message_setopt(message, rdataset));
|
||||
|
||||
cleanup:
|
||||
if (rdatalist != NULL)
|
||||
dns_message_puttemprdatalist(message, &rdatalist);
|
||||
if (rdataset != NULL)
|
||||
dns_message_puttemprdataset(message, &rdataset);
|
||||
if (rdata != NULL)
|
||||
dns_message_puttemprdata(message, &rdata);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
soa_query(isc_task_t *task, isc_event_t *event) {
|
||||
const char me[] = "soa_query";
|
||||
@@ -3641,6 +3752,24 @@ soa_query(isc_task_t *task, isc_event_t *event) {
|
||||
isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
|
||||
(void)dns_view_getpeertsig(zone->view, &masterip, &key);
|
||||
|
||||
if (zone->view->peers != NULL) {
|
||||
dns_peer_t *peer = NULL;
|
||||
isc_boolean_t edns;
|
||||
result = dns_peerlist_peerbyaddr(zone->view->peers,
|
||||
&masterip, &peer);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
result = dns_peer_getsupportedns(peer, &edns);
|
||||
if (result == ISC_R_SUCCESS && !edns)
|
||||
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
|
||||
}
|
||||
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
|
||||
result = add_opt(message);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
zone_debuglog(zone, me, 1,
|
||||
"unable to add opt record: %s",
|
||||
dns_result_totext(result));
|
||||
}
|
||||
|
||||
options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
|
||||
DNS_REQUESTOPT_TCP : 0;
|
||||
switch (isc_sockaddr_pf(&zone->masteraddr)) {
|
||||
@@ -3782,6 +3911,24 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
|
||||
isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
|
||||
(void)dns_view_getpeertsig(zone->view, &masterip, &key);
|
||||
|
||||
if (zone->view->peers != NULL) {
|
||||
dns_peer_t *peer = NULL;
|
||||
isc_boolean_t edns;
|
||||
result = dns_peerlist_peerbyaddr(zone->view->peers,
|
||||
&masterip, &peer);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
result = dns_peer_getsupportedns(peer, &edns);
|
||||
if (result == ISC_R_SUCCESS && !edns)
|
||||
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
|
||||
}
|
||||
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
|
||||
result = add_opt(message);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
zone_debuglog(zone, me, 1,
|
||||
"unable to add opt record: %s",
|
||||
dns_result_totext(result));
|
||||
}
|
||||
|
||||
/*
|
||||
* Always use TCP so that we shouldn't truncate in additional section.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user