aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ares/adig.c6
-rw-r--r--ares/ahost.c4
-rw-r--r--ares/ares.h8
-rw-r--r--ares/ares_cancel.c2
-rw-r--r--ares/ares_destroy.c2
-rw-r--r--ares/ares_gethostbyaddr.37
-rw-r--r--ares/ares_gethostbyaddr.c18
-rw-r--r--ares/ares_gethostbyname.37
-rw-r--r--ares/ares_gethostbyname.c24
-rw-r--r--ares/ares_getnameinfo.37
-rw-r--r--ares/ares_getnameinfo.c24
-rw-r--r--ares/ares_private.h3
-rw-r--r--ares/ares_process.c2
-rw-r--r--ares/ares_query.37
-rw-r--r--ares/ares_query.c13
-rw-r--r--ares/ares_search.37
-rw-r--r--ares/ares_search.c22
-rw-r--r--ares/ares_send.37
-rw-r--r--ares/ares_send.c9
19 files changed, 114 insertions, 65 deletions
diff --git a/ares/adig.c b/ares/adig.c
index 1eea3df69..b4fd20536 100644
--- a/ares/adig.c
+++ b/ares/adig.c
@@ -127,7 +127,8 @@ static const char *rcodes[] = {
"(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE"
};
-static void callback(void *arg, int status, unsigned char *abuf, int alen);
+static void callback(void *arg, int status, int timeouts,
+ unsigned char *abuf, int alen);
static const unsigned char *display_question(const unsigned char *aptr,
const unsigned char *abuf,
int alen);
@@ -294,7 +295,8 @@ int main(int argc, char **argv)
return 0;
}
-static void callback(void *arg, int status, unsigned char *abuf, int alen)
+static void callback(void *arg, int status, int timeouts,
+ unsigned char *abuf, int alen)
{
char *name = (char *) arg;
int id, qr, opcode, aa, tc, rd, ra, rcode;
diff --git a/ares/ahost.c b/ares/ahost.c
index e381c1932..1e6cc8bd4 100644
--- a/ares/ahost.c
+++ b/ares/ahost.c
@@ -47,7 +47,7 @@ struct in6_addr
};
#endif
-static void callback(void *arg, int status, struct hostent *host);
+static void callback(void *arg, int status, int timeouts, struct hostent *host);
static void usage(void);
int main(int argc, char **argv)
@@ -142,7 +142,7 @@ int main(int argc, char **argv)
return 0;
}
-static void callback(void *arg, int status, struct hostent *host)
+static void callback(void *arg, int status, int timeouts, struct hostent *host)
{
char **p;
diff --git a/ares/ares.h b/ares/ares.h
index 61d5a5605..50ce7f850 100644
--- a/ares/ares.h
+++ b/ares/ares.h
@@ -193,11 +193,11 @@ struct timeval;
struct sockaddr;
struct ares_channeldata;
typedef struct ares_channeldata *ares_channel;
-typedef void (*ares_callback)(void *arg, int status, unsigned char *abuf,
- int alen);
-typedef void (*ares_host_callback)(void *arg, int status,
+typedef void (*ares_callback)(void *arg, int status, int timeouts,
+ unsigned char *abuf, int alen);
+typedef void (*ares_host_callback)(void *arg, int status, int timeouts,
struct hostent *hostent);
-typedef void (*ares_nameinfo_callback)(void *arg, int status,
+typedef void (*ares_nameinfo_callback)(void *arg, int status, int timeouts,
char *node, char *service);
int ares_init(ares_channel *channelptr);
diff --git a/ares/ares_cancel.c b/ares/ares_cancel.c
index 65f86b966..c3d668e84 100644
--- a/ares/ares_cancel.c
+++ b/ares/ares_cancel.c
@@ -31,7 +31,7 @@ void ares_cancel(ares_channel channel)
for (query = channel->queries; query; query = next)
{
next = query->next;
- query->callback(query->arg, ARES_ETIMEOUT, NULL, 0);
+ query->callback(query->arg, ARES_ETIMEOUT, 0, NULL, 0);
free(query->tcpbuf);
free(query->server_info);
free(query);
diff --git a/ares/ares_destroy.c b/ares/ares_destroy.c
index e844ea628..d1f82bdf6 100644
--- a/ares/ares_destroy.c
+++ b/ares/ares_destroy.c
@@ -62,7 +62,7 @@ void ares_destroy(ares_channel channel)
while (channel->queries) {
query = channel->queries;
channel->queries = query->next;
- query->callback(query->arg, ARES_EDESTRUCTION, NULL, 0);
+ query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL, 0);
if (query->tcpbuf)
free(query->tcpbuf);
if (query->server_info)
diff --git a/ares/ares_gethostbyaddr.3 b/ares/ares_gethostbyaddr.3
index e3fc3c522..3782d4af5 100644
--- a/ares/ares_gethostbyaddr.3
+++ b/ares/ares_gethostbyaddr.3
@@ -22,7 +22,7 @@ ares_gethostbyaddr \- Initiate a host query by address
.B #include <ares.h>
.PP
.B typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP,
-.B struct hostent *\fIhostent\fP)
+.B int \fItimeouts\fP, struct hostent *\fIhostent\fP)
.PP
.B void ares_gethostbyaddr(ares_channel \fIchannel\fP, const void *\fIaddr\fP,
.B int \fIaddrlen\fP, int \fIfamily\fP, ares_host_callback \fIcallback\fP,
@@ -76,6 +76,11 @@ The name service channel
.I channel
is being destroyed; the query will not be completed.
.PP
+The callback argument
+.I timeouts
+reports how many times a query timed out during the execution of the
+given request.
+.PP
On successful completion of the query, the callback argument
.I hostent
points to a
diff --git a/ares/ares_gethostbyaddr.c b/ares/ares_gethostbyaddr.c
index 7ea7ebbc0..b3abc093e 100644
--- a/ares/ares_gethostbyaddr.c
+++ b/ares/ares_gethostbyaddr.c
@@ -49,11 +49,12 @@ struct addr_query {
void *arg;
const char *remaining_lookups;
+ int timeouts;
};
static void next_lookup(struct addr_query *aquery);
-static void addr_callback(void *arg, int status, unsigned char *abuf,
- int alen);
+static void addr_callback(void *arg, int status, int timeouts,
+ unsigned char *abuf, int alen);
static void end_aquery(struct addr_query *aquery, int status,
struct hostent *host);
static int file_lookup(union ares_addr *addr, int family, struct hostent **host);
@@ -65,21 +66,21 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
if (family != AF_INET && family != AF_INET6)
{
- callback(arg, ARES_ENOTIMP, NULL);
+ callback(arg, ARES_ENOTIMP, 0, NULL);
return;
}
if ((family == AF_INET && addrlen != sizeof(struct in_addr)) ||
(family == AF_INET6 && addrlen != sizeof(struct in6_addr)))
{
- callback(arg, ARES_ENOTIMP, NULL);
+ callback(arg, ARES_ENOTIMP, 0, NULL);
return;
}
aquery = malloc(sizeof(struct addr_query));
if (!aquery)
{
- callback(arg, ARES_ENOMEM, NULL);
+ callback(arg, ARES_ENOMEM, 0, NULL);
return;
}
aquery->channel = channel;
@@ -91,6 +92,7 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
aquery->callback = callback;
aquery->arg = arg;
aquery->remaining_lookups = channel->lookups;
+ aquery->timeouts = 0;
next_lookup(aquery);
}
@@ -151,11 +153,13 @@ static void next_lookup(struct addr_query *aquery)
end_aquery(aquery, ARES_ENOTFOUND, NULL);
}
-static void addr_callback(void *arg, int status, unsigned char *abuf, int alen)
+static void addr_callback(void *arg, int status, int timeouts,
+ unsigned char *abuf, int alen)
{
struct addr_query *aquery = (struct addr_query *) arg;
struct hostent *host;
+ aquery->timeouts += timeouts;
if (status == ARES_SUCCESS)
{
if (aquery->family == AF_INET)
@@ -175,7 +179,7 @@ static void addr_callback(void *arg, int status, unsigned char *abuf, int alen)
static void end_aquery(struct addr_query *aquery, int status,
struct hostent *host)
{
- aquery->callback(aquery->arg, status, host);
+ aquery->callback(aquery->arg, status, aquery->timeouts, host);
if (host)
ares_free_hostent(host);
free(aquery);
diff --git a/ares/ares_gethostbyname.3 b/ares/ares_gethostbyname.3
index 680b213f3..c59c03851 100644
--- a/ares/ares_gethostbyname.3
+++ b/ares/ares_gethostbyname.3
@@ -22,7 +22,7 @@ ares_gethostbyname \- Initiate a host query by name
.B #include <ares.h>
.PP
.B typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP,
-.B struct hostent *\fIhostent\fP)
+.B int \fItimeouts\fP, struct hostent *\fIhostent\fP)
.PP
.B void ares_gethostbyname(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIfamily\fP, ares_host_callback \fIcallback\fP, void *\fIarg\fP)
@@ -80,6 +80,11 @@ The name service channel
.I channel
is being destroyed; the query will not be completed.
.PP
+The callback argument
+.I timeouts
+reports how many times a query timed out during the execution of the
+given request.
+.PP
On successful completion of the query, the callback argument
.I hostent
points to a
diff --git a/ares/ares_gethostbyname.c b/ares/ares_gethostbyname.c
index c0fa4743a..49ae53ed3 100644
--- a/ares/ares_gethostbyname.c
+++ b/ares/ares_gethostbyname.c
@@ -54,11 +54,12 @@ struct host_query {
void *arg;
int family;
const char *remaining_lookups;
+ int timeouts;
};
static void next_lookup(struct host_query *hquery);
-static void host_callback(void *arg, int status, unsigned char *abuf,
- int alen);
+static void host_callback(void *arg, int status, int timeouts,
+ unsigned char *abuf, int alen);
static void end_hquery(struct host_query *hquery, int status,
struct hostent *host);
static int fake_hostent(const char *name, int family, ares_host_callback callback,
@@ -81,7 +82,7 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
/* Right now we only know how to look up Internet addresses. */
if (family != AF_INET && family != AF_INET6)
{
- callback(arg, ARES_ENOTIMP, NULL);
+ callback(arg, ARES_ENOTIMP, 0, NULL);
return;
}
@@ -92,7 +93,7 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
hquery = malloc(sizeof(struct host_query));
if (!hquery)
{
- callback(arg, ARES_ENOMEM, NULL);
+ callback(arg, ARES_ENOMEM, 0, NULL);
return;
}
hquery->channel = channel;
@@ -101,12 +102,13 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
if (!hquery->name)
{
free(hquery);
- callback(arg, ARES_ENOMEM, NULL);
+ callback(arg, ARES_ENOMEM, 0, NULL);
return;
}
hquery->callback = callback;
hquery->arg = arg;
hquery->remaining_lookups = channel->lookups;
+ hquery->timeouts = 0;
/* Start performing lookups according to channel->lookups. */
next_lookup(hquery);
@@ -144,15 +146,16 @@ static void next_lookup(struct host_query *hquery)
break;
}
}
- end_hquery(hquery, ARES_ENOTFOUND, NULL);
}
-static void host_callback(void *arg, int status, unsigned char *abuf, int alen)
+static void host_callback(void *arg, int status, int timeouts,
+ unsigned char *abuf, int alen)
{
struct host_query *hquery = (struct host_query *) arg;
ares_channel channel = hquery->channel;
struct hostent *host;
+ hquery->timeouts += timeouts;
if (status == ARES_SUCCESS)
{
if (hquery->family == AF_INET)
@@ -185,7 +188,7 @@ static void host_callback(void *arg, int status, unsigned char *abuf, int alen)
static void end_hquery(struct host_query *hquery, int status,
struct hostent *host)
{
- hquery->callback(hquery->arg, status, host);
+ hquery->callback(hquery->arg, status, hquery->timeouts, host);
if (host)
ares_free_hostent(host);
free(hquery->name);
@@ -227,7 +230,7 @@ static int fake_hostent(const char *name, int family, ares_host_callback callbac
hostent.h_name = strdup(name);
if (!hostent.h_name)
{
- callback(arg, ARES_ENOMEM, NULL);
+ callback(arg, ARES_ENOMEM, 0, NULL);
return 1;
}
@@ -236,7 +239,7 @@ static int fake_hostent(const char *name, int family, ares_host_callback callbac
hostent.h_aliases = aliases;
hostent.h_addrtype = family;
hostent.h_addr_list = addrs;
- callback(arg, ARES_SUCCESS, &hostent);
+ callback(arg, ARES_SUCCESS, 0, &hostent);
free((char *)(hostent.h_name));
return 1;
@@ -416,4 +419,3 @@ static int get6_address_index(struct in6_addr *addr, struct apattern *sortlist,
}
return i;
}
-
diff --git a/ares/ares_getnameinfo.3 b/ares/ares_getnameinfo.3
index 9b6bd73a9..55918ffba 100644
--- a/ares/ares_getnameinfo.3
+++ b/ares/ares_getnameinfo.3
@@ -22,7 +22,7 @@ ares_getnameinfo \- Address-to-nodename translation in protocol-independent mann
.B #include <ares.h>
.PP
.B typedef void (*ares_nameinfo_callback)(void *\fIarg\fP, int \fIstatus\fP,
-.B char *\fInode\fP, char *\fIservice\fP)
+.B int \fItimeouts\fP, char *\fInode\fP, char *\fIservice\fP)
.PP
.B void ares_getnameinfo(ares_channel \fIchannel\fP, const struct sockaddr *\fIsa\fP,
.B socklen_t \fIsalen\fP, int \fIflags\fP, ares_nameinfo_callback \fIcallback\fP,
@@ -120,6 +120,11 @@ The
.I flags
parameter contains an illegal value.
.PP
+The callback argument
+.I timeouts
+reports how many times a query timed out during the execution of the
+given request.
+.PP
On successful completion of the query, the callback argument
.I node
contains a string representing the hostname (assuming
diff --git a/ares/ares_getnameinfo.c b/ares/ares_getnameinfo.c
index 2c28cebf6..4f690f9d0 100644
--- a/ares/ares_getnameinfo.c
+++ b/ares/ares_getnameinfo.c
@@ -59,6 +59,7 @@ struct nameinfo_query {
} addr;
int family;
int flags;
+ int timeouts;
};
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
@@ -67,7 +68,7 @@ struct nameinfo_query {
#define IPBUFSIZ 40
#endif
-static void nameinfo_callback(void *arg, int status, struct hostent *host);
+static void nameinfo_callback(void *arg, int status, int timeouts, struct hostent *host);
static char *lookup_service(unsigned short port, int flags,
char *buf, size_t buflen);
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
@@ -90,7 +91,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
addr6 = (struct sockaddr_in6 *)sa;
else
{
- callback(arg, ARES_ENOTIMP, NULL, NULL);
+ callback(arg, ARES_ENOTIMP, 0, NULL, NULL);
return;
}
@@ -110,7 +111,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
port = addr6->sin6_port;
service = lookup_service((unsigned short)(port & 0xffff),
flags, buf, sizeof(buf));
- callback(arg, ARES_SUCCESS, NULL, service);
+ callback(arg, ARES_SUCCESS, 0, NULL, service);
return;
}
@@ -131,7 +132,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
*/
if (flags & ARES_NI_NAMEREQD)
{
- callback(arg, ARES_EBADFLAGS, NULL, NULL);
+ callback(arg, ARES_EBADFLAGS, 0, NULL, NULL);
return;
}
if (salen == sizeof(struct sockaddr_in6))
@@ -152,7 +153,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
if (flags & ARES_NI_LOOKUPSERVICE)
service = lookup_service((unsigned short)(port & 0xffff),
flags, srvbuf, sizeof(srvbuf));
- callback(arg, ARES_SUCCESS, ipbuf, service);
+ callback(arg, ARES_SUCCESS, 0, ipbuf, service);
return;
}
/* This is where a DNS lookup becomes necessary */
@@ -161,12 +162,13 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
niquery = malloc(sizeof(struct nameinfo_query));
if (!niquery)
{
- callback(arg, ARES_ENOMEM, NULL, NULL);
+ callback(arg, ARES_ENOMEM, 0, NULL, NULL);
return;
}
niquery->callback = callback;
niquery->arg = arg;
niquery->flags = flags;
+ niquery->timeouts = 0;
if (sa->sa_family == AF_INET)
{
niquery->family = AF_INET;
@@ -185,13 +187,13 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
}
}
-static void nameinfo_callback(void *arg, int status, struct hostent *host)
+static void nameinfo_callback(void *arg, int status, int timeouts, struct hostent *host)
{
struct nameinfo_query *niquery = (struct nameinfo_query *) arg;
char srvbuf[33];
char *service = NULL;
-
+ niquery->timeouts += timeouts;
if (status == ARES_SUCCESS)
{
/* They want a service too */
@@ -220,7 +222,7 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
*end = 0;
}
}
- niquery->callback(niquery->arg, ARES_SUCCESS, (char *)(host->h_name),
+ niquery->callback(niquery->arg, ARES_SUCCESS, niquery->timeouts, (char *)(host->h_name),
service);
return;
}
@@ -247,10 +249,10 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
service = lookup_service(niquery->addr.addr6.sin6_port,
niquery->flags, srvbuf, sizeof(srvbuf));
}
- niquery->callback(niquery->arg, ARES_SUCCESS, ipbuf, service);
+ niquery->callback(niquery->arg, ARES_SUCCESS, 0, ipbuf, service);
return;
}
- niquery->callback(niquery->arg, status, NULL, NULL);
+ niquery->callback(niquery->arg, status, 0, NULL, NULL);
free(niquery);
}
diff --git a/ares/ares_private.h b/ares/ares_private.h
index dd9070aa7..e6ecaa251 100644
--- a/ares/ares_private.h
+++ b/ares/ares_private.h
@@ -152,6 +152,7 @@ struct query {
/* Next query in chain */
struct query *next;
+ int timeouts; /* number of timeouts we saw for this request */
};
/* Per-server state for a query */
@@ -195,6 +196,8 @@ struct ares_channeldata {
int ndots;
int udp_port;
int tcp_port;
+ int socket_send_buffer_size;
+ int socket_receive_buffer_size;
char **domains;
int ndomains;
struct apattern *sortlist;
diff --git a/ares/ares_process.c b/ares/ares_process.c
index 15aa06e1c..d359b115a 100644
--- a/ares/ares_process.c
+++ b/ares/ares_process.c
@@ -936,7 +936,7 @@ static struct query *end_query (ares_channel channel, struct query *query, int s
}
/* Invoke the callback */
- query->callback(query->arg, status, abuf, alen);
+ query->callback(query->arg, status, query->timeouts, abuf, alen);
for (q = &channel->queries; *q; q = &(*q)->next)
{
if (*q == query)
diff --git a/ares/ares_query.3 b/ares/ares_query.3
index 4bd8b68bd..93f64b2f2 100644
--- a/ares/ares_query.3
+++ b/ares/ares_query.3
@@ -22,7 +22,7 @@ ares_query \- Initiate a single-question DNS query
.B #include <ares.h>
.PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
-.B unsigned char *\fIabuf\fP, int \fIalen\fP)
+.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP)
.PP
.B void ares_query(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP,
@@ -124,6 +124,11 @@ The name service channel
.I channel
is being destroyed; the query will not be completed.
.PP
+The callback argument
+.I timeouts
+reports how many times a query timed out during the execution of the
+given request.
+.PP
If the query completed (even if there was something wrong with it, as
indicated by some of the above error codes), the callback argument
.I abuf
diff --git a/ares/ares_query.c b/ares/ares_query.c
index 0cd655709..c5fc12449 100644
--- a/ares/ares_query.c
+++ b/ares/ares_query.c
@@ -37,7 +37,7 @@ struct qquery {
void *arg;
};
-static void qcallback(void *arg, int status, unsigned char *abuf, int alen);
+static void qcallback(void *arg, int status, int timeouts, unsigned char *abuf, int alen);
void ares__rc4(rc4_key* key, unsigned char *buffer_ptr, int buffer_len)
{
@@ -110,7 +110,8 @@ void ares_query(ares_channel channel, const char *name, int dnsclass,
&qlen);
if (status != ARES_SUCCESS)
{
- callback(arg, status, NULL, 0);
+ if (qbuf != NULL) free(qbuf);
+ callback(arg, status, 0, NULL, 0);
return;
}
@@ -121,7 +122,7 @@ void ares_query(ares_channel channel, const char *name, int dnsclass,
if (!qquery)
{
ares_free_string(qbuf);
- callback(arg, ARES_ENOMEM, NULL, 0);
+ callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
qquery->callback = callback;
@@ -132,14 +133,14 @@ void ares_query(ares_channel channel, const char *name, int dnsclass,
ares_free_string(qbuf);
}
-static void qcallback(void *arg, int status, unsigned char *abuf, int alen)
+static void qcallback(void *arg, int status, int timeouts, unsigned char *abuf, int alen)
{
struct qquery *qquery = (struct qquery *) arg;
unsigned int ancount;
int rcode;
if (status != ARES_SUCCESS)
- qquery->callback(qquery->arg, status, abuf, alen);
+ qquery->callback(qquery->arg, status, timeouts, abuf, alen);
else
{
/* Pull the response code and answer count from the packet. */
@@ -168,7 +169,7 @@ static void qcallback(void *arg, int status, unsigned char *abuf, int alen)
status = ARES_EREFUSED;
break;
}
- qquery->callback(qquery->arg, status, abuf, alen);
+ qquery->callback(qquery->arg, status, timeouts, abuf, alen);
}
free(qquery);
}
diff --git a/ares/ares_search.3 b/ares/ares_search.3
index 2e93ba3da..f5bf80d9c 100644
--- a/ares/ares_search.3
+++ b/ares/ares_search.3
@@ -22,7 +22,7 @@ ares_search \- Initiate a DNS query with domain search
.B #include <ares.h>
.PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
-.B unsigned char *\fIabuf\fP, int \fIalen\fP)
+.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP)
.PP
.B void ares_search(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP,
@@ -125,6 +125,11 @@ The name service channel
.I channel
is being destroyed; the query will not be completed.
.PP
+The callback argument
+.I timeouts
+reports how many times a query timed out during the execution of the
+given request.
+.PP
If a query completed successfully, the callback argument
.I abuf
points to a result buffer of length
diff --git a/ares/ares_search.c b/ares/ares_search.c
index 4ff54532e..ca703a3cb 100644
--- a/ares/ares_search.c
+++ b/ares/ares_search.c
@@ -41,10 +41,11 @@ struct search_query {
int status_as_is; /* error status from trying as-is */
int next_domain; /* next search domain to try */
int trying_as_is; /* current query is for name as-is */
+ int timeouts; /* number of timeouts we saw for this request */
};
-static void search_callback(void *arg, int status, unsigned char *abuf,
- int alen);
+static void search_callback(void *arg, int status, int timeouts,
+ unsigned char *abuf, int alen);
static void end_squery(struct search_query *squery, int status,
unsigned char *abuf, int alen);
static int cat_domain(const char *name, const char *domain, char **s);
@@ -64,7 +65,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
status = single_domain(channel, name, &s);
if (status != ARES_SUCCESS)
{
- callback(arg, status, NULL, 0);
+ callback(arg, status, 0, NULL, 0);
return;
}
if (s)
@@ -80,7 +81,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
squery = malloc(sizeof(struct search_query));
if (!squery)
{
- callback(arg, ARES_ENOMEM, NULL, 0);
+ callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
squery->channel = channel;
@@ -88,7 +89,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
if (!squery->name)
{
free(squery);
- callback(arg, ARES_ENOMEM, NULL, 0);
+ callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
squery->dnsclass = dnsclass;
@@ -96,6 +97,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
squery->status_as_is = -1;
squery->callback = callback;
squery->arg = arg;
+ squery->timeouts = 0;
/* Count the number of dots in name. */
ndots = 0;
@@ -132,18 +134,20 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
/* failed, free the malloc()ed memory */
free(squery->name);
free(squery);
- callback(arg, status, NULL, 0);
+ callback(arg, status, 0, NULL, 0);
}
}
}
-static void search_callback(void *arg, int status, unsigned char *abuf,
- int alen)
+static void search_callback(void *arg, int status, int timeouts,
+ unsigned char *abuf, int alen)
{
struct search_query *squery = (struct search_query *) arg;
ares_channel channel = squery->channel;
char *s;
+ squery->timeouts += timeouts;
+
/* Stop searching unless we got a non-fatal error. */
if (status != ARES_ENODATA && status != ARES_ESERVFAIL
&& status != ARES_ENOTFOUND)
@@ -184,7 +188,7 @@ static void search_callback(void *arg, int status, unsigned char *abuf,
static void end_squery(struct search_query *squery, int status,
unsigned char *abuf, int alen)
{
- squery->callback(squery->arg, status, abuf, alen);
+ squery->callback(squery->arg, status, squery->timeouts, abuf, alen);
free(squery->name);
free(squery);
}
diff --git a/ares/ares_send.3 b/ares/ares_send.3
index 2627b17ef..e8a240471 100644
--- a/ares/ares_send.3
+++ b/ares/ares_send.3
@@ -22,7 +22,7 @@ ares_send \- Initiate a DNS query
.B #include <ares.h>
.PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
-.B unsigned char *\fIabuf\fP, int \fIalen\fP)
+.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP)
.PP
.B void ares_send(ares_channel \fIchannel\fP, const unsigned char *\fIqbuf\fP,
.B int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP)
@@ -79,6 +79,11 @@ The name service channel
.I channel
is being destroyed; the query will not be completed.
.PP
+The callback argument
+.I timeouts
+reports how many times a query timed out during the execution of the
+given request.
+.PP
If the query completed, the callback argument
.I abuf
points to a result buffer of length
diff --git a/ares/ares_send.c b/ares/ares_send.c
index fd1450b4a..c8015803b 100644
--- a/ares/ares_send.c
+++ b/ares/ares_send.c
@@ -44,7 +44,7 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
/* Verify that the query is at least long enough to hold the header. */
if (qlen < HFIXEDSZ || qlen >= (1 << 16))
{
- callback(arg, ARES_EBADQUERY, NULL, 0);
+ callback(arg, ARES_EBADQUERY, 0, NULL, 0);
return;
}
@@ -52,14 +52,14 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
query = malloc(sizeof(struct query));
if (!query)
{
- callback(arg, ARES_ENOMEM, NULL, 0);
+ callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
query->tcpbuf = malloc(qlen + 2);
if (!query->tcpbuf)
{
free(query);
- callback(arg, ARES_ENOMEM, NULL, 0);
+ callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
query->server_info = malloc(channel->nservers *
@@ -68,7 +68,7 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
{
free(query->tcpbuf);
free(query);
- callback(arg, ARES_ENOMEM, NULL, 0);
+ callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
@@ -100,6 +100,7 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
}
query->using_tcp = (channel->flags & ARES_FLAG_USEVC) || qlen > PACKETSZ;
query->error_status = ARES_ECONNREFUSED;
+ query->timeouts = 0;
/* Chain the query into this channel's query list. */
query->next = channel->queries;