async_resolv.c revision 7aaf9138ccf7ab73883f28cfafd6e508d29ffa67
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn Async resolver
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn Martin Nagy <mnagy@redhat.com>
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn Jakub Hrozek <jhrozek@redhat.com>
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn Copyright (C) Red Hat, Inc 2009
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn This program is free software; you can redistribute it and/or modify
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn it under the terms of the GNU General Public License as published by
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn the Free Software Foundation; either version 3 of the License, or
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn (at your option) any later version.
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn This program is distributed in the hope that it will be useful,
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn but WITHOUT ANY WARRANTY; without even the implied warranty of
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn GNU General Public License for more details.
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn You should have received a copy of the GNU General Public License
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn along with this program. If not, see <http://www.gnu.org/licenses/>.
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn#define ares_parse_srv_reply(abuf, alen, srv_out) \
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn#define ares_parse_txt_reply(abuf, alen, txt_out) \
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn#endif /* HAVE_ARES_DATA */
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn#define DNS_HEADER_ANCOUNT(h) DNS__16BIT((h) + 6)
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallynenum host_database default_host_dbs[] = { DB_FILES, DB_DNS, DB_SENTINEL };
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn /* List of file descriptors that are watched by tevent. */
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn /* Time in milliseconds before canceling a DNS request */
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn /* The timeout watcher periodically calls ares_process_fd() to check
198b363fff1de9afcee2f26b9aa847316f589afeSerge Hallyn * if our pending requests didn't timeout. */
ctx);
static struct resolv_request *
if (!rreq) {
return NULL;
rreq);
return NULL;
return NULL;
return rreq;
static struct resolv_request *
return rreq;
int flags;
while (watch) {
while (watch) {
int ret;
return EOK;
int ret;
return ENOMEM;
goto done;
return EOK;
done:
return ret;
static errno_t
return EOK;
static errno_t
return EOK;
static struct resolv_hostent *
int len;
return NULL;
goto fail;
goto fail;
for (i = 0; i < len; i++) {
goto fail;
return ret;
fail:
return NULL;
struct resolv_hostent *
int len;
return NULL;
goto fail;
for (i = 0; i < len; i++) {
struct resolv_addr);
goto fail;
goto fail;
return ret;
fail:
return NULL;
struct resolv_hostent *
int num_ares_ttl_data)
return NULL;
if (num_ares_ttl_data > 0) {
goto fail;
for (i = 0; i < num_ares_ttl_data; i++) {
struct resolv_addr);
goto fail;
switch (family) {
case AF_INET:
case AF_INET6:
goto fail;
goto fail;
return ret;
fail:
return NULL;
struct gethostbyname_files_state {
const char *name;
int family;
int status;
static struct tevent_req *
const char *name,
int family)
struct gethostbyname_files_state);
goto done;
&hostent);
goto done;
goto done;
goto done;
done:
return req;
static errno_t
struct gethostbyname_files_state);
if (status) {
if (rhostent) {
return EOK;
struct gethostbyname_dns_state {
const char *name;
int family;
int status;
int timeouts;
int retrying;
static struct tevent_req *
int family)
return NULL;
return NULL;
return NULL;
return req;
struct tevent_req);
struct gethostbyname_dns_state);
if (!rreq) {
/* If resolv.conf changed during processing of a request we might
int naddrttls;
case AF_INET:
if (!addr) {
goto fail;
&naddrttls);
case AF_INET6:
if (!addr) {
goto fail;
&naddrttls);
goto fail;
goto fail;
return ENOENT;
fail:
return ret;
struct gethostbyname_dns_state);
if (status) {
if (timeouts) {
if (rhostent) {
return EOK;
struct gethostbyname_state {
const char *name;
int family;
int dbi;
int status;
int timeouts;
int retrying;
static errno_t
static errno_t
struct tevent_req *
return NULL;
return NULL;
goto fail;
goto fail;
return req;
goto fail;
return req;
fail:
return NULL;
int ret;
if (ret != 0) {
return ret == 0;
static errno_t
int family;
if (!rhostent) {
goto done;
goto done;
struct resolv_addr);
goto done;
sizeof(struct in6_addr));
goto done;
goto done;
done:
return ret;
switch(family_order) {
case IPV4_ONLY:
case IPV4_FIRST:
return AF_INET;
case IPV6_ONLY:
case IPV6_FIRST:
return AF_INET6;
return EOK;
return EOK;
return EOK;
return ENOENT;
static errno_t
struct gethostbyname_state);
case DB_FILES:
case DB_DNS:
return EINVAL;
return ENOMEM;
return EOK;
struct tevent_req);
struct gethostbyname_state);
case DB_FILES:
case DB_DNS:
if (status) {
if (timeouts) {
if (rhostent) {
return EOK;
unsigned int addrindex)
char *address;
return NULL;
errno = 0;
return NULL;
return address;
char *straddr;
if (!straddr) {
return NULL;
(address[0]));
return NULL;
return straddr;
struct sockaddr_storage *
return NULL;
case AF_INET:
sizeof(struct in_addr));
case AF_INET6:
sizeof(struct in6_addr));
return NULL;
return sockaddr;
if (!old_list) {
return EOK;
while (old_list) {
if (!new_list) {
return ENOMEM;
return ENOMEM;
return ENOMEM;
return EOK;
struct getsrv_state {
/* the SRV query - for example _ldap._tcp.example.com */
const char *query;
int status;
int timeouts;
int retrying;
struct tevent_req *
return NULL;
return NULL;
return NULL;
return req;
int ret;
goto fail;
goto fail;
goto fail;
fail:
if (status)
if (timeouts)
if (reply_list)
return EOK;
struct tevent_req);
struct getsrv_state);
if (!rreq) {
#ifdef BUILD_TXT
if (!old_list) {
return EOK;
while (old_list) {
if (!new_list) {
return ENOMEM;
return ENOMEM;
return ENOMEM;
return EOK;
struct gettxt_state {
const char *query;
int status;
int timeouts;
int retrying;
struct tevent_req *
return NULL;
return NULL;
return NULL;
return req;
int ret;
goto fail;
goto fail;
goto fail;
fail:
if (status)
if (timeouts)
if (reply_list)
return EOK;
struct tevent_req);
struct gettxt_state);
if (!rreq) {
if (!list) {
return NULL;
return single_step;
struct ares_srv_reply *l, *r;
if (!left)
return right;
if (!right)
return left;
r = right;
l = left;
res = l;
l = l->next;
res = r;
r = r->next;
return res_start;
return list;
return list;
int *totals;
int ret;
return EOK;
if (!totals) {
return ENOMEM;
r = *(start);
while (r != NULL) {
if (r->weight == 0) {
if (prev) {
tmp = r;
r = r->next;
prev = r;
r = r->next;
total = 0;
prev = r;
goto done;
if (prev) {
if (!new_start) {
new_start = r;
new_end = r;
new_end = r;
done:
return ret;
int ret;
int len;
return EIO;
while (pri_start) {
len++;
if (ret) {
return ret;
if (prev_end) {
return EOK;