Alien-cares
view release on metacpan or search on metacpan
libcares/ares_gethostbyname.c view on Meta::CPAN
{
struct host_query *hquery = (struct host_query *) arg;
ares_channel channel = hquery->channel;
struct hostent *host = NULL;
hquery->timeouts += timeouts;
if (status == ARES_SUCCESS)
{
if (hquery->sent_family == AF_INET)
{
status = ares_parse_a_reply(abuf, alen, &host, NULL, NULL);
if (host && channel->nsort)
sort_addresses(host, channel->sortlist, channel->nsort);
}
else if (hquery->sent_family == AF_INET6)
{
status = ares_parse_aaaa_reply(abuf, alen, &host, NULL, NULL);
if ((status == ARES_ENODATA || status == ARES_EBADRESP ||
(status == ARES_SUCCESS && host && host->h_addr_list[0] == NULL)) &&
hquery->want_family == AF_UNSPEC) {
/* The query returned something but either there were no AAAA
records (e.g. just CNAME) or the response was malformed. Try
looking up A instead. */
if (host)
ares_free_hostent(host);
hquery->sent_family = AF_INET;
ares_search(hquery->channel, hquery->name, C_IN, T_A,
host_callback, hquery);
return;
}
if (host && channel->nsort)
sort6_addresses(host, channel->sortlist, channel->nsort);
}
end_hquery(hquery, status, host);
}
else if ((status == ARES_ENODATA || status == ARES_EBADRESP ||
status == ARES_ETIMEOUT) && (hquery->sent_family == AF_INET6 &&
hquery->want_family == AF_UNSPEC))
{
/* The AAAA query yielded no useful result. Now look up an A instead. */
hquery->sent_family = AF_INET;
ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
hquery);
}
else if (status == ARES_EDESTRUCTION)
end_hquery(hquery, status, NULL);
else
next_lookup(hquery, status);
}
static void end_hquery(struct host_query *hquery, int status,
struct hostent *host)
{
hquery->callback(hquery->arg, status, hquery->timeouts, host);
if (host)
ares_free_hostent(host);
ares_free(hquery->name);
ares_free(hquery);
}
/* If the name looks like an IP address, fake up a host entry, end the
* query immediately, and return true. Otherwise return false.
*/
static int fake_hostent(const char *name, int family,
ares_host_callback callback, void *arg)
{
struct hostent hostent;
char *aliases[1] = { NULL };
char *addrs[2];
int result = 0;
struct in_addr in;
struct ares_in6_addr in6;
if (family == AF_INET || family == AF_INET6)
{
/* It only looks like an IP address if it's all numbers and dots. */
int numdots = 0, valid = 1;
const char *p;
for (p = name; *p; p++)
{
if (!ISDIGIT(*p) && *p != '.') {
valid = 0;
break;
} else if (*p == '.') {
numdots++;
}
}
/* if we don't have 3 dots, it is illegal
* (although inet_addr doesn't think so).
*/
if (numdots != 3 || !valid)
result = 0;
else
result = ((in.s_addr = inet_addr(name)) == INADDR_NONE ? 0 : 1);
if (result)
family = AF_INET;
}
if (family == AF_INET6)
result = (ares_inet_pton(AF_INET6, name, &in6) < 1 ? 0 : 1);
if (!result)
return 0;
if (family == AF_INET)
{
hostent.h_length = (int)sizeof(struct in_addr);
addrs[0] = (char *)∈
}
else if (family == AF_INET6)
{
hostent.h_length = (int)sizeof(struct ares_in6_addr);
addrs[0] = (char *)&in6;
}
/* Duplicate the name, to avoid a constness violation. */
hostent.h_name = ares_strdup(name);
if (!hostent.h_name)
{
callback(arg, ARES_ENOMEM, 0, NULL);
return 1;
}
/* Fill in the rest of the host structure and terminate the query. */
addrs[1] = NULL;
hostent.h_aliases = aliases;
hostent.h_addrtype = aresx_sitoss(family);
hostent.h_addr_list = addrs;
callback(arg, ARES_SUCCESS, 0, &hostent);
ares_free((char *)(hostent.h_name));
return 1;
}
/* This is an API method */
int ares_gethostbyname_file(ares_channel channel, const char *name,
( run in 0.459 second using v1.01-cache-2.11-cpan-2398b32b56e )