@@ -453,9 +453,9 @@ extern int __read_etc_hosts_r(parser_t *parser,
struct hostent **result,
int *h_errnop) attribute_hidden;
extern int __dns_lookup(const char *name,
- int type,
+ const int type,
unsigned char **outpacket,
- struct resolv_answer *a) attribute_hidden;
+ struct resolv_answer *a) attribute_hidden __nonnull((1));
extern int __encode_dotted(const char *dotted,
unsigned char *dest,
int maxlen) attribute_hidden;
@@ -1230,7 +1230,7 @@ static int __decode_answer(const unsigned char *message, /* packet */
* This is a malloced string. May be NULL because strdup failed.
*/
int __dns_lookup(const char *name,
- int type,
+ const int type,
unsigned char **outpacket,
struct resolv_answer *a)
{
@@ -1240,7 +1240,7 @@ int __dns_lookup(const char *name,
int i, j, fd, rc;
int packet_len;
- int name_len;
+ const size_t name_len = strlen(name);
#ifdef USE_SELECT
struct timeval tv;
fd_set fds;
@@ -1258,18 +1258,16 @@ int __dns_lookup(const char *name,
int local_ns_num = -1; /* Nth server to use */
int local_id = local_id; /* for compiler */
int sdomains;
- bool ends_with_dot;
+ const bool ends_with_dot = name[name_len - 1] == '.';
sockaddr46_t sa;
fd = -1;
lookup = NULL;
- name_len = strlen(name);
if ((unsigned)name_len >= MAXDNAME - MAXLEN_searchdomain - 2)
goto fail; /* paranoia */
lookup = malloc(name_len + 1/*for '.'*/ + MAXLEN_searchdomain + 1);
if (!packet || !lookup || !name[0])
goto fail;
- ends_with_dot = (name[name_len - 1] == '.');
/* no strcpy! paranoia, user might change name[] under us */
memcpy(lookup, name, name_len);
@@ -1456,32 +1454,38 @@ int __dns_lookup(const char *name,
h.qdcount, h.ancount, h.nscount, h.arcount);
DPRINTF("opcode=%d,aa=%d,tc=%d,rd=%d,ra=%d,rcode=%d\n",
h.opcode, h.aa, h.tc, h.rd, h.ra, h.rcode);
+ if (unlikely(h.rcode != 0)) {
+ /* bug 660 says we treat negative response as an error
+ * and retry, which is, eh, an error. :) */
+
+ /* Try to keep latency and traffic low here, please! */
+ if (h.rcode == REFUSED) {
+ /* type not supported,
+ try the next server, with fresh variants */
+ goto try_next_server;
+ }
+ /* Insert other non-fatal errors here, which do not warrant
+ * switching to next nameserver */
- /* bug 660 says we treat negative response as an error
- * and retry, which is, eh, an error. :)
- * We were incurring long delays because of this. */
- if (h.rcode == NXDOMAIN || h.rcode == SERVFAIL) {
- /* if possible, try next search domain */
if (!ends_with_dot) {
+ /* When not being asked for a specific delegation we can try
+ * other variants of the given name */
DPRINTF("variant:%d sdomains:%d\n", variant, sdomains);
if (variant < sdomains - 1) {
- /* next search domain */
+ /* if possible, try next search domain */
variant++;
continue;
}
- /* no more search domains to try */
+ } else if (h.rcode == NXDOMAIN) {
+ /* Specific */
+ /* Fall through to
+ Finally; dont loop, this is "no such host" situation
+ */
}
- /* dont loop, this is "no such host" situation */
+ /* Finally; dont loop, this is "no such host" situation */
h_errno = HOST_NOT_FOUND;
goto fail1;
}
- /* Insert other non-fatal errors here, which do not warrant
- * switching to next nameserver */
-
- /* Strange error, assuming this nameserver is feeling bad */
- if (h.rcode != 0)
- goto try_next_server;
-
/* Code below won't work correctly with h.ancount == 0, so... */
if (h.ancount <= 0) {
h_errno = NO_DATA; /* [is this correct code to check for?] */