Improve the dns retry logic

Bug reported by Richard Silverman on heimdal-bugs
This commit is contained in:
Love Hornquist Astrand
2010-03-19 14:19:43 -07:00
parent d3efb7d043
commit b0a79dcd40

View File

@@ -521,8 +521,7 @@ dns_lookup_int(const char *domain, int rr_class, int rr_type)
{ {
struct rk_dns_reply *r; struct rk_dns_reply *r;
void *reply = NULL; void *reply = NULL;
int size; int size, len;
int len;
#if defined(HAVE_DNS_SEARCH) #if defined(HAVE_DNS_SEARCH)
struct sockaddr_storage from; struct sockaddr_storage from;
uint32_t fromsize = sizeof(from); uint32_t fromsize = sizeof(from);
@@ -540,15 +539,12 @@ dns_lookup_int(const char *domain, int rr_class, int rr_type)
return NULL; /* is this the best we can do? */ return NULL; /* is this the best we can do? */
#endif #endif
size = 0; len = 1500;
len = 1000; while(1) {
do {
if (reply) { if (reply) {
free(reply); free(reply);
reply = NULL; reply = NULL;
} }
if (size <= len)
size = len;
if (_resolve_debug) { if (_resolve_debug) {
#if defined(HAVE_DNS_SEARCH) #if defined(HAVE_DNS_SEARCH)
dns_set_debug(handle, 1); dns_set_debug(handle, 1);
@@ -556,27 +552,37 @@ dns_lookup_int(const char *domain, int rr_class, int rr_type)
state.options |= RES_DEBUG; state.options |= RES_DEBUG;
#endif #endif
fprintf(stderr, "dns_lookup(%s, %d, %s), buffer size %d\n", domain, fprintf(stderr, "dns_lookup(%s, %d, %s), buffer size %d\n", domain,
rr_class, rk_dns_type_to_string(rr_type), size); rr_class, rk_dns_type_to_string(rr_type), len);
} }
reply = malloc(size); reply = malloc(len);
if (reply == NULL) { if (reply == NULL) {
resolve_free_handle(handle); resolve_free_handle(handle);
return NULL; return NULL;
} }
len = resolve_search(handle, domain, rr_class, rr_type, reply, size); size = resolve_search(handle, domain, rr_class, rr_type, reply, len);
if (_resolve_debug) { if (_resolve_debug) {
fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n", fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n",
domain, rr_class, rk_dns_type_to_string(rr_type), len); domain, rr_class, rk_dns_type_to_string(rr_type), size);
} }
if (len <= 0) { if (size > len) {
/* resolver thinks it know better, go for it */
len = size;
} else if (size > 0) {
/* got a good reply */
break;
} else if (size <= 0 && len < rk_DNS_MAX_PACKET_SIZE) {
len *= 2;
if (len > rk_DNS_MAX_PACKET_SIZE)
len = rk_DNS_MAX_PACKET_SIZE;
} else {
/* the end, leave */
resolve_free_handle(handle); resolve_free_handle(handle);
free(reply); free(reply);
return NULL; return NULL;
} }
} while (size < len && len < rk_DNS_MAX_PACKET_SIZE); }
resolve_free_handle(handle);
len = min(len, size); len = min(len, size);
r = parse_reply(reply, len); r = parse_reply(reply, len);