mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
r22714: Prevent DNS lookup storms when the DNS servers are unreachable.
Helps when transitioning from offline to online mode. Note that this is a quick hack and a better solution would be to start the DNS server's state between processes (similar to the namecache entries).
This commit is contained in:
parent
4086ef15b3
commit
4f05c6fe26
@ -270,45 +270,76 @@ static int dnssrvcmp( struct dns_rr_srv *a, struct dns_rr_srv *b )
|
|||||||
Simple wrapper for a DNS query
|
Simple wrapper for a DNS query
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
|
#define DNS_FAILED_WAITTIME 30
|
||||||
|
|
||||||
static NTSTATUS dns_send_req( TALLOC_CTX *ctx, const char *name, int q_type,
|
static NTSTATUS dns_send_req( TALLOC_CTX *ctx, const char *name, int q_type,
|
||||||
uint8 **buf, int *resp_length )
|
uint8 **buf, int *resp_length )
|
||||||
{
|
{
|
||||||
uint8 *buffer = NULL;
|
uint8 *buffer = NULL;
|
||||||
size_t buf_len;
|
size_t buf_len;
|
||||||
int resp_len = NS_PACKETSZ;
|
int resp_len = NS_PACKETSZ;
|
||||||
|
static time_t last_dns_check = 0;
|
||||||
|
static NTSTATUS last_dns_status = NT_STATUS_OK;
|
||||||
|
time_t now = time(NULL);
|
||||||
|
|
||||||
|
/* Try to prevent bursts of DNS lookups if the server is down */
|
||||||
|
|
||||||
|
/* Protect against large clock changes */
|
||||||
|
|
||||||
|
if ( last_dns_check > now )
|
||||||
|
last_dns_check = 0;
|
||||||
|
|
||||||
|
/* IF we had a DNS timeout or a bad server and we are still
|
||||||
|
in the 30 second cache window, just return the previous
|
||||||
|
status and save the network timeout. */
|
||||||
|
|
||||||
|
if ( (NT_STATUS_EQUAL(last_dns_status,NT_STATUS_IO_TIMEOUT) ||
|
||||||
|
NT_STATUS_EQUAL(last_dns_status,NT_STATUS_CONNECTION_REFUSED)) &&
|
||||||
|
(last_dns_check+DNS_FAILED_WAITTIME) > now )
|
||||||
|
{
|
||||||
|
DEBUG(10,("last_dns_check: Returning cached status (%s)\n",
|
||||||
|
nt_errstr(last_dns_status) ));
|
||||||
|
return last_dns_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the Query */
|
||||||
do {
|
do {
|
||||||
if ( buffer )
|
if ( buffer )
|
||||||
TALLOC_FREE( buffer );
|
TALLOC_FREE( buffer );
|
||||||
|
|
||||||
buf_len = resp_len * sizeof(uint8);
|
buf_len = resp_len * sizeof(uint8);
|
||||||
|
|
||||||
if (buf_len) {
|
if (buf_len) {
|
||||||
if ( (buffer = TALLOC_ARRAY(ctx, uint8, buf_len)) == NULL ) {
|
if ( (buffer = TALLOC_ARRAY(ctx, uint8, buf_len)) == NULL ) {
|
||||||
DEBUG(0,("ads_dns_lookup_srv: talloc() failed!\n"));
|
DEBUG(0,("ads_dns_lookup_srv: talloc() failed!\n"));
|
||||||
return NT_STATUS_NO_MEMORY;
|
last_dns_status = NT_STATUS_NO_MEMORY;
|
||||||
|
last_dns_check = time(NULL);
|
||||||
|
return last_dns_status;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
buffer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (resp_len = res_query(name, C_IN, q_type, buffer, buf_len)) < 0 ) {
|
if ( (resp_len = res_query(name, C_IN, q_type, buffer, buf_len)) < 0 ) {
|
||||||
DEBUG(3,("ads_dns_lookup_srv: Failed to resolve %s (%s)\n", name, strerror(errno)));
|
DEBUG(3,("ads_dns_lookup_srv: Failed to resolve %s (%s)\n", name, strerror(errno)));
|
||||||
TALLOC_FREE( buffer );
|
TALLOC_FREE( buffer );
|
||||||
|
last_dns_status = NT_STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
if (errno == ETIMEDOUT) {
|
if (errno == ETIMEDOUT) {
|
||||||
return NT_STATUS_IO_TIMEOUT;
|
last_dns_status = NT_STATUS_IO_TIMEOUT;
|
||||||
}
|
}
|
||||||
if (errno == ECONNREFUSED) {
|
if (errno == ECONNREFUSED) {
|
||||||
return NT_STATUS_CONNECTION_REFUSED;
|
last_dns_status = NT_STATUS_CONNECTION_REFUSED;
|
||||||
}
|
}
|
||||||
return NT_STATUS_UNSUCCESSFUL;
|
last_dns_check = time(NULL);
|
||||||
|
return last_dns_status;
|
||||||
}
|
}
|
||||||
} while ( buf_len < resp_len && resp_len < MAX_DNS_PACKET_SIZE );
|
} while ( buf_len < resp_len && resp_len < MAX_DNS_PACKET_SIZE );
|
||||||
|
|
||||||
*buf = buffer;
|
*buf = buffer;
|
||||||
*resp_length = resp_len;
|
*resp_length = resp_len;
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
last_dns_check = time(NULL);
|
||||||
|
last_dns_status = NT_STATUS_OK;
|
||||||
|
return last_dns_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
|
Loading…
Reference in New Issue
Block a user