- DNS failure cache: do several attempts before blacklisting

This commit is contained in:
Thomas Ries 2007-12-20 17:42:10 +00:00
parent 6859b0b9b3
commit f81e32fe73
3 changed files with 58 additions and 35 deletions

View File

@ -1,5 +1,6 @@
0.6.1 0.6.1
===== =====
20-Dec-2007: - DNS failure cache: do several attempts before blacklisting
28-Nov-2007: - Fix: Detach from controlling TTY if daemonized 28-Nov-2007: - Fix: Detach from controlling TTY if daemonized
22-Nov-2007: - Working on code that that will allow siproxd to use 22-Nov-2007: - Working on code that that will allow siproxd to use
separate interfaces in its "in front of NAT routes" setup. separate interfaces in its "in front of NAT routes" setup.

View File

@ -261,6 +261,8 @@ int sip_message_set_body(osip_message_t * sip, const char *buf, size_t len);
#define URL_STRING_SIZE 128 /* max size of an URL/URI string */ #define URL_STRING_SIZE 128 /* max size of an URL/URI string */
#define STATUSCODE_SIZE 5 /* size of string representation of status */ #define STATUSCODE_SIZE 5 /* size of string representation of status */
#define DNS_CACHE_SIZE 256 /* number of entries in internal DNS cache */ #define DNS_CACHE_SIZE 256 /* number of entries in internal DNS cache */
#define DNS_ATTEMPTS 3 /* number of attempts to resolve a name
before it is marked as bad */
#define DNS_GOOD_AGE 60 /* maximum age of a good cache entry (sec) */ #define DNS_GOOD_AGE 60 /* maximum age of a good cache entry (sec) */
#define DNS_BAD_AGE 600 /* maximum age of a bad cache entry (sec) */ #define DNS_BAD_AGE 600 /* maximum age of a bad cache entry (sec) */
#define IFADR_CACHE_SIZE 32 /* number of entries in internal IFADR cache */ #define IFADR_CACHE_SIZE 32 /* number of entries in internal IFADR cache */

View File

@ -63,7 +63,7 @@ extern int h_errno;
* STS_FAILURE on failure * STS_FAILURE on failure
*/ */
int get_ip_by_host(char *hostname, struct in_addr *addr) { int get_ip_by_host(char *hostname, struct in_addr *addr) {
int i, j, k; int i, j, k, idx;
time_t t1, t2; time_t t1, t2;
struct hostent *hostentry; struct hostent *hostentry;
#if defined(HAVE_GETHOSTBYNAME_R) #if defined(HAVE_GETHOSTBYNAME_R)
@ -74,6 +74,7 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
static struct { static struct {
time_t expires_timestamp; /* time of expiration */ time_t expires_timestamp; /* time of expiration */
struct in_addr addr; /* IP address or 0.0.0.0 if a bad entry */ struct in_addr addr; /* IP address or 0.0.0.0 if a bad entry */
char error_count; /* counts failed resolution attempts */
char bad_entry; /* != 0 if resolving failed */ char bad_entry; /* != 0 if resolving failed */
char hostname[HOSTNAME_SIZE+1]; char hostname[HOSTNAME_SIZE+1];
} dns_cache[DNS_CACHE_SIZE]; } dns_cache[DNS_CACHE_SIZE];
@ -109,15 +110,22 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
/* /*
* search requested entry in cache * search requested entry in cache
*/ */
idx=0;
for (i=0; i<DNS_CACHE_SIZE; i++) { for (i=0; i<DNS_CACHE_SIZE; i++) {
if (dns_cache[i].hostname[0]=='\0') continue; /* empty */ if (dns_cache[i].hostname[0]=='\0') continue; /* empty */
if (strcasecmp(hostname, dns_cache[i].hostname) == 0) { /* match */ if (strcasecmp(hostname, dns_cache[i].hostname) == 0) { /* match */
memcpy(addr, &dns_cache[i].addr, sizeof(struct in_addr)); memcpy(addr, &dns_cache[i].addr, sizeof(struct in_addr));
if (dns_cache[i].bad_entry) { if (dns_cache[i].bad_entry) {
DEBUGC(DBCLASS_DNS, "DNS lookup - bad entry from cache: %s", DEBUGC(DBCLASS_DNS, "DNS lookup - blacklisted from cache: %s",
hostname); hostname);
return STS_FAILURE; return STS_FAILURE;
} }
if (dns_cache[i].error_count > 0) {
DEBUGC(DBCLASS_DNS, "DNS lookup - previous resolution failed: %s"
", attempt %i", hostname, dns_cache[i].error_count);
idx=i;
break;
}
DEBUGC(DBCLASS_DNS, "DNS lookup - from cache: %s -> %s", DEBUGC(DBCLASS_DNS, "DNS lookup - from cache: %s -> %s",
hostname, utils_inet_ntoa(*addr)); hostname, utils_inet_ntoa(*addr));
return STS_SUCCESS; return STS_SUCCESS;
@ -203,47 +211,59 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
hostname, utils_inet_ntoa(*addr)); hostname, utils_inet_ntoa(*addr));
} }
/* /* if we already have the entry, skip finding a new empty one */
* find an empty slot in the cache if (idx == 0) {
*/ /*
j=0; * find an empty slot in the cache
k=0; */
t1=INT_MAX; j=0;
t2=INT_MAX; k=0;
for (i=0; i<DNS_CACHE_SIZE; i++) { t1=INT_MAX;
if (dns_cache[i].hostname[0]=='\0') break; t2=INT_MAX;
if ((dns_cache[i].expires_timestamp < t1) && for (i=0; i<DNS_CACHE_SIZE; i++) {
(dns_cache[i].bad_entry == 0)) { if (dns_cache[i].hostname[0]=='\0') break;
/* remember oldest good entry */ if ((dns_cache[i].expires_timestamp < t1) &&
t1=dns_cache[i].expires_timestamp; (dns_cache[i].bad_entry == 0)) {
j=i; /* remember oldest good entry */
} else t1=dns_cache[i].expires_timestamp;
if (dns_cache[i].expires_timestamp < t2) { j=i;
/* remember oldest bad entry */ } else
t2=dns_cache[i].expires_timestamp; if (dns_cache[i].expires_timestamp < t2) {
k=i; /* remember oldest bad entry */
t2=dns_cache[i].expires_timestamp;
k=i;
}
} }
} /* if no empty slot found, victimize oldest one.
/* if no empty slot found, victimize oldest one. * Give preference to the oldest "bad" entry if
* Give preference to the oldest "bad" entry if * one exists */
* one exists */ if (i >= DNS_CACHE_SIZE) {
if (i >= DNS_CACHE_SIZE) { if (k > 0) i=k;
if (k > 0) i=k; else i=j;
else i=j; }
idx=i;
memset(&dns_cache[idx], 0, sizeof(dns_cache[0]));
} }
/* /*
* store the result in the cache * store the result in the cache
*/ */
DEBUGC(DBCLASS_DNS, "DNS lookup - store into cache, entry %i)", i); DEBUGC(DBCLASS_DNS, "DNS lookup - store into cache, entry %i)", idx);
memset(&dns_cache[i], 0, sizeof(dns_cache[0])); strncpy(dns_cache[idx].hostname, hostname, HOSTNAME_SIZE);
strncpy(dns_cache[i].hostname, hostname, HOSTNAME_SIZE); dns_cache[idx].expires_timestamp = time(NULL) + DNS_GOOD_AGE;
if (hostentry) { if (hostentry) {
dns_cache[i].expires_timestamp = time(NULL) + DNS_GOOD_AGE; memcpy(&dns_cache[idx].addr, addr, sizeof(struct in_addr));
memcpy(&dns_cache[i].addr, addr, sizeof(struct in_addr)); dns_cache[idx].error_count = 0;
dns_cache[idx].bad_entry = 0;
} else { } else {
dns_cache[i].expires_timestamp = time(NULL) + DNS_BAD_AGE; dns_cache[idx].error_count++;
dns_cache[i].bad_entry = 1; DEBUGC(DBCLASS_DNS, "DNS lookup - errcnt=%i", dns_cache[idx].error_count);
if (dns_cache[idx].error_count >= DNS_ATTEMPTS) {
DEBUGC(DBCLASS_DNS, "DNS lookup - blacklisting entry");
dns_cache[idx].expires_timestamp = time(NULL) + DNS_BAD_AGE;
dns_cache[idx].bad_entry = 1;
}
return STS_FAILURE;
} }
return STS_SUCCESS; return STS_SUCCESS;
} }