static void next_lookup(struct host_query *hquery) { int status; const char *p; struct hostent *host; for (p = hquery->remaining_lookups; *p; p++) { switch (*p) { case 'b': /* DNS lookup */ hquery->remaining_lookups = p + 1; ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback, hquery); return; case 'f': /* Host file lookup */ status = file_lookup(hquery->name, &host); if (status != ARES_ENOTFOUND) { end_hquery(hquery, status, host); return; } break; } } end_hquery(hquery, ARES_ENOTFOUND, NULL); }
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 = 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 next_lookup(struct host_query *hquery, int status_code) { const char *p; struct hostent *host; int status = status_code; for (p = hquery->remaining_lookups; *p; p++) { switch (*p) { case 'b': /* DNS lookup */ hquery->remaining_lookups = p + 1; if ((hquery->want_family == AF_INET6) || (hquery->want_family == AF_UNSPEC)) { /* if inet6 or unspec, start out with AAAA */ hquery->sent_family = AF_INET6; ares_search(hquery->channel, hquery->name, C_IN, T_AAAA, host_callback, hquery); } else { hquery->sent_family = AF_INET; ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback, hquery); } return; case 'f': /* Host file lookup */ status = file_lookup(hquery->name, hquery->want_family, &host); /* this status check below previously checked for !ARES_ENOTFOUND, but we should not assume that this single error code is the one that can occur, as that is in fact no longer the case */ if (status == ARES_SUCCESS) { end_hquery(hquery, status, host); return; } status = status_code; /* Use original status code */ break; } } end_hquery(hquery, status, NULL); }
static void host_callback(void *arg, int status, unsigned char *abuf, int alen) { struct host_query *hquery = (struct host_query *) arg; ares_channel channel = hquery->channel; struct hostent *host; if (status == ARES_SUCCESS) { status = ares_parse_a_reply(abuf, alen, &host); if (host && channel->nsort) sort_addresses(host, channel->sortlist, channel->nsort); end_hquery(hquery, status, host); } else if (status == ARES_EDESTRUCTION) end_hquery(hquery, status, NULL); else next_lookup(hquery); }