"(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);
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;
};
#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)
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;
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);
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);
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)
.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,
.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
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);
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;
aquery->callback = callback;
aquery->arg = arg;
aquery->remaining_lookups = channel->lookups;
+ aquery->timeouts = 0;
next_lookup(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)
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);
.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)
.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
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,
/* 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;
}
hquery = malloc(sizeof(struct host_query));
if (!hquery)
{
- callback(arg, ARES_ENOMEM, NULL);
+ callback(arg, ARES_ENOMEM, 0, NULL);
return;
}
hquery->channel = channel;
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);
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)
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);
hostent.h_name = strdup(name);
if (!hostent.h_name)
{
- callback(arg, ARES_ENOMEM, NULL);
+ callback(arg, ARES_ENOMEM, 0, NULL);
return 1;
}
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;
}
return i;
}
-
.B #include <ares.h>\r
.PP\r
.B typedef void (*ares_nameinfo_callback)(void *\fIarg\fP, int \fIstatus\fP,\r
-.B char *\fInode\fP, char *\fIservice\fP)\r
+.B int \fItimeouts\fP, char *\fInode\fP, char *\fIservice\fP)\r
.PP\r
.B void ares_getnameinfo(ares_channel \fIchannel\fP, const struct sockaddr *\fIsa\fP,\r
.B socklen_t \fIsalen\fP, int \fIflags\fP, ares_nameinfo_callback \fIcallback\fP,\r
.I flags\r
parameter contains an illegal value.\r
.PP\r
+The callback argument\r
+.I timeouts\r
+reports how many times a query timed out during the execution of the\r
+given request.\r
+.PP\r
On successful completion of the query, the callback argument\r
.I node\r
contains a string representing the hostname (assuming \r
} addr;
int family;
int flags;
+ int timeouts;
};
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
#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
addr6 = (struct sockaddr_in6 *)sa;
else
{
- callback(arg, ARES_ENOTIMP, NULL, NULL);
+ callback(arg, ARES_ENOTIMP, 0, NULL, NULL);
return;
}
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;
}
*/
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))
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 */
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;
}
}
-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 */
*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;
}
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);
}
/* Next query in chain */
struct query *next;
+ int timeouts; /* number of timeouts we saw for this request */
};
/* Per-server state for a query */
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;
}
/* 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)
.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,
.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
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)
{
&qlen);
if (status != ARES_SUCCESS)
{
- callback(arg, status, NULL, 0);
+ if (qbuf != NULL) free(qbuf);
+ callback(arg, status, 0, NULL, 0);
return;
}
if (!qquery)
{
ares_free_string(qbuf);
- callback(arg, ARES_ENOMEM, NULL, 0);
+ callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
qquery->callback = callback;
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. */
status = ARES_EREFUSED;
break;
}
- qquery->callback(qquery->arg, status, abuf, alen);
+ qquery->callback(qquery->arg, status, timeouts, abuf, alen);
}
free(qquery);
}
.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,
.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
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);
status = single_domain(channel, name, &s);
if (status != ARES_SUCCESS)
{
- callback(arg, status, NULL, 0);
+ callback(arg, status, 0, NULL, 0);
return;
}
if (s)
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;
if (!squery->name)
{
free(squery);
- callback(arg, ARES_ENOMEM, NULL, 0);
+ callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
squery->dnsclass = dnsclass;
squery->status_as_is = -1;
squery->callback = callback;
squery->arg = arg;
+ squery->timeouts = 0;
/* Count the number of dots in name. */
ndots = 0;
/* 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)
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);
}
.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)
.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
/* 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;
}
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 *
{
free(query->tcpbuf);
free(query);
- callback(arg, ARES_ENOMEM, NULL, 0);
+ callback(arg, ARES_ENOMEM, 0, NULL, 0);
return;
}
}
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;