summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libc/asr/asr.c4
-rw-r--r--lib/libc/asr/asr_private.h4
-rw-r--r--lib/libc/asr/async_resolver.321
-rw-r--r--lib/libc/asr/getaddrinfo_async.c65
-rw-r--r--lib/libc/asr/gethostnamadr_async.c46
-rw-r--r--lib/libc/asr/res_search_async.c4
-rw-r--r--lib/libc/asr/res_send_async.c4
7 files changed, 63 insertions, 85 deletions
diff --git a/lib/libc/asr/asr.c b/lib/libc/asr/asr.c
index 270f1484304..056253c092e 100644
--- a/lib/libc/asr/asr.c
+++ b/lib/libc/asr/asr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: asr.c,v 1.14 2012/11/24 15:12:48 eric Exp $ */
+/* $OpenBSD: asr.c,v 1.15 2013/03/27 07:40:41 eric Exp $ */
/*
* Copyright (c) 2010-2012 Eric Faurot <eric@openbsd.org>
*
@@ -301,8 +301,6 @@ async_free(struct async *as)
async_free(as->as.hostnamadr.subq);
if (as->as.hostnamadr.name)
free(as->as.hostnamadr.name);
- if (as->as.hostnamadr.dname)
- free(as->as.hostnamadr.dname);
break;
case ASR_GETNETBYNAME:
diff --git a/lib/libc/asr/asr_private.h b/lib/libc/asr/asr_private.h
index 8e17a44dd15..17453a8b330 100644
--- a/lib/libc/asr/asr_private.h
+++ b/lib/libc/asr/asr_private.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: asr_private.h,v 1.10 2012/11/24 15:12:48 eric Exp $ */
+/* $OpenBSD: asr_private.h,v 1.11 2013/03/27 07:40:41 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
@@ -233,10 +233,10 @@ struct async {
struct {
char *name;
int family;
- char *dname;
struct async *subq;
char addr[16];
int addrlen;
+ int h_errno;
} hostnamadr;
struct {
diff --git a/lib/libc/asr/async_resolver.3 b/lib/libc/asr/async_resolver.3
index acb26781eeb..0dca4d45f29 100644
--- a/lib/libc/asr/async_resolver.3
+++ b/lib/libc/asr/async_resolver.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: async_resolver.3,v 1.6 2012/09/06 08:38:15 eric Exp $
+.\" $OpenBSD: async_resolver.3,v 1.7 2013/03/27 07:40:41 eric Exp $
.\"
.\" Copyright (c) 2012, Eric Faurot <eric@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: September 6 2012 $
+.Dd $Mdocdate: March 27 2013 $
.Dt ASYN_RESOLVER 3
.Os
.Sh NAME
@@ -127,8 +127,7 @@ Once called, that context is invalidated and cannot be used to create new
queries.
Internally, the context is refcounted, so that existing queries made against
it will be able to complete safely.
-All relevant resources are effectively
-freed when all such queries are cleared.
+All relevant resources are effectively freed when all such queries are cleared.
.Pp
The
.Fn async_run
@@ -345,6 +344,20 @@ This list must be freed with
The
.Fa ar_count
contains the number of elements in the list.
+.Sh WORKING WITH THREADS
+This implementation of the asynchronous resolver interface is thread-safe
+and lock-free internally, but the following restriction applies:
+Two different threads must not create queries on the same context or
+run queries originating from the same context at the same time.
+If they want to do that, all calls must be protected by a mutex around
+that context.
+.Pp
+It is generally not a problem since the main point of the asynchronous
+resolver is to multiplex queries within a single thread of control,
+so sharing a resolver among threads is not useful.
+.Pp
+Note that this restriction only applies to resolver contexts explicitely
+created by the caller, as a thread-local context is used by default.
.Sh SEE ALSO
.Xr getaddrinfo 3 ,
.Xr gethostbyname 3 ,
diff --git a/lib/libc/asr/getaddrinfo_async.c b/lib/libc/asr/getaddrinfo_async.c
index 20f5a2af198..a362ccb8e63 100644
--- a/lib/libc/asr/getaddrinfo_async.c
+++ b/lib/libc/asr/getaddrinfo_async.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getaddrinfo_async.c,v 1.10 2012/11/24 15:12:48 eric Exp $ */
+/* $OpenBSD: getaddrinfo_async.c,v 1.11 2013/03/27 07:40:41 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
@@ -109,7 +109,6 @@ getaddrinfo_async_run(struct async *as, struct async_res *ar)
const char *str;
struct addrinfo *ai;
int i, family, r;
- char fqdn[MAXDNAME];
FILE *f;
union {
struct sockaddr sa;
@@ -267,35 +266,12 @@ getaddrinfo_async_run(struct async *as, struct async_res *ar)
break;
}
- /* start domain lookup */
- async_set_state(as, ASR_STATE_NEXT_DOMAIN);
- break;
-
- case ASR_STATE_NEXT_DOMAIN:
- r = asr_iter_domain(as, as->as.ai.hostname, fqdn, sizeof(fqdn));
- if (r == -1) {
- async_set_state(as, ASR_STATE_NOT_FOUND);
- break;
- }
- if (r > (int)sizeof(fqdn)) {
- ar->ar_gai_errno = EAI_OVERFLOW;
- async_set_state(as, ASR_STATE_HALT);
- break;
- }
- if (as->as.ai.fqdn)
- free(as->as.ai.fqdn);
- if ((as->as.ai.fqdn = strdup(fqdn)) == NULL) {
- ar->ar_gai_errno = EAI_MEMORY;
- async_set_state(as, ASR_STATE_HALT);
- break;
- }
- as->as_db_idx = 0;
async_set_state(as, ASR_STATE_NEXT_DB);
break;
case ASR_STATE_NEXT_DB:
if (asr_iter_db(as) == -1) {
- async_set_state(as, ASR_STATE_NEXT_DOMAIN);
+ async_set_state(as, ASR_STATE_NOT_FOUND);
break;
}
as->as_family_idx = 0;
@@ -320,14 +296,23 @@ getaddrinfo_async_run(struct async *as, struct async_res *ar)
break;
case ASR_STATE_SAME_DB:
- /* query the current DB again. */
+ /* query the current DB again */
switch (AS_DB(as)) {
case ASR_DB_DNS:
family = (as->as.ai.hints.ai_family == AF_UNSPEC) ?
AS_FAMILY(as) : as->as.ai.hints.ai_family;
- as->as.ai.subq = res_query_async_ctx(as->as.ai.fqdn,
- C_IN, (family == AF_INET6) ? T_AAAA : T_A, NULL, 0,
- as->as_ctx);
+ if (as->as.ai.fqdn) {
+ as->as.ai.subq = res_query_async_ctx(
+ as->as.ai.fqdn, C_IN,
+ (family == AF_INET6) ? T_AAAA : T_A, NULL, 0,
+ as->as_ctx);
+ }
+ else {
+ as->as.ai.subq = res_search_async_ctx(
+ as->as.ai.hostname, C_IN,
+ (family == AF_INET6) ? T_AAAA : T_A, NULL, 0,
+ as->as_ctx);
+ }
if (as->as.ai.subq == NULL) {
if (errno == ENOMEM)
ar->ar_gai_errno = EAI_MEMORY;
@@ -401,7 +386,7 @@ getaddrinfo_async_run(struct async *as, struct async_res *ar)
as->as.ai.subq = NULL;
if (ar->ar_datalen == -1) {
- async_set_state(as, ASR_STATE_NEXT_DB);
+ async_set_state(as, ASR_STATE_NEXT_FAMILY);
break;
}
@@ -582,7 +567,7 @@ addrinfo_from_file(struct async *as, int family, FILE *f)
break; /* ignore errors reading the file */
for (i = 1; i < n; i++) {
- if (strcasecmp(as->as.ai.fqdn, tokens[i]))
+ if (strcasecmp(as->as.ai.hostname, tokens[i]))
continue;
if (sockaddr_from_str(&u.sa, family, tokens[0]) == -1)
continue;
@@ -591,10 +576,8 @@ addrinfo_from_file(struct async *as, int family, FILE *f)
if (i == n)
continue;
- if (as->as.ai.hints.ai_flags & AI_CANONNAME)
+ if (as->as.ai.hints.ai_flags & (AI_CANONNAME | AI_FQDN))
c = tokens[1];
- else if (as->as.ai.hints.ai_flags & AI_FQDN)
- c = as->as.ai.fqdn;
else
c = NULL;
@@ -630,6 +613,14 @@ addrinfo_from_pkt(struct async *as, char *pkt, size_t pktlen)
rr.rr_class != q.q_class)
continue;
+ if (as->as.ai.fqdn == NULL) {
+ asr_strdname(q.q_dname, buf, sizeof buf);
+ buf[strlen(buf) - 1] = '\0';
+ as->as.ai.fqdn = strdup(buf);
+ if (as->as.ai.fqdn == NULL)
+ return (-1); /* errno set */
+ }
+
memset(&u, 0, sizeof u);
if (rr.rr_type == T_A) {
u.sain.sin_len = sizeof u.sain;
@@ -699,10 +690,8 @@ addrinfo_from_yp(struct async *as, int family, char *line)
if (sockaddr_from_str(&u.sa, family, tokens[0]) == -1)
continue;
- if (as->as.ai.hints.ai_flags & AI_CANONNAME)
+ if (as->as.ai.hints.ai_flags & (AI_CANONNAME | AI_FQDN))
c = tokens[1];
- else if (as->as.ai.hints.ai_flags & AI_FQDN)
- c = as->as.ai.fqdn;
else
c = NULL;
diff --git a/lib/libc/asr/gethostnamadr_async.c b/lib/libc/asr/gethostnamadr_async.c
index 580f618613e..33ec8b571cc 100644
--- a/lib/libc/asr/gethostnamadr_async.c
+++ b/lib/libc/asr/gethostnamadr_async.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gethostnamadr_async.c,v 1.12 2012/12/17 21:13:16 eric Exp $ */
+/* $OpenBSD: gethostnamadr_async.c,v 1.13 2013/03/27 07:40:41 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
@@ -192,42 +192,16 @@ gethostnamadr_async_run(struct async *as, struct async_res *ar)
ar->ar_h_errno = NETDB_SUCCESS;
}
async_set_state(as, ASR_STATE_HALT);
+ break;
}
- else
- async_set_state(as, ASR_STATE_NEXT_DOMAIN);
}
- else
- async_set_state(as, ASR_STATE_NEXT_DB);
- break;
-
- case ASR_STATE_NEXT_DOMAIN:
-
- r = asr_iter_domain(as, as->as.hostnamadr.name, dname,
- sizeof(dname));
- if (r == -1) {
- async_set_state(as, ASR_STATE_NOT_FOUND);
- break;
- }
-
- if (as->as.hostnamadr.dname)
- free(as->as.hostnamadr.dname);
- if ((as->as.hostnamadr.dname = strdup(dname)) == NULL) {
- ar->ar_h_errno = NETDB_INTERNAL;
- ar->ar_errno = errno;
- async_set_state(as, ASR_STATE_HALT);
- }
-
- as->as_db_idx = 0;
async_set_state(as, ASR_STATE_NEXT_DB);
break;
case ASR_STATE_NEXT_DB:
if (asr_iter_db(as) == -1) {
- if (as->as_type == ASR_GETHOSTBYNAME)
- async_set_state(as, ASR_STATE_NEXT_DOMAIN);
- else
- async_set_state(as, ASR_STATE_NOT_FOUND);
+ async_set_state(as, ASR_STATE_NOT_FOUND);
break;
}
@@ -240,8 +214,8 @@ gethostnamadr_async_run(struct async *as, struct async_res *ar)
if (as->as_type == ASR_GETHOSTBYNAME) {
type = (as->as.hostnamadr.family == AF_INET) ?
T_A : T_AAAA;
- as->as.hostnamadr.subq = res_query_async_ctx(
- as->as.hostnamadr.dname,
+ as->as.hostnamadr.subq = res_search_async_ctx(
+ as->as.hostnamadr.name,
C_IN, type, NULL, 0, as->as_ctx);
} else {
addr_as_fqdn(as->as.hostnamadr.addr,
@@ -269,7 +243,7 @@ gethostnamadr_async_run(struct async *as, struct async_res *ar)
break;
if (as->as_type == ASR_GETHOSTBYNAME)
- data = as->as.hostnamadr.dname;
+ data = as->as.hostnamadr.name;
else
data = as->as.hostnamadr.addr;
@@ -299,7 +273,7 @@ gethostnamadr_async_run(struct async *as, struct async_res *ar)
if (as->as.hostnamadr.family != AF_INET)
break;
if (as->as_type == ASR_GETHOSTBYNAME)
- data = as->as.hostnamadr.dname;
+ data = as->as.hostnamadr.name;
else
data = as->as.hostnamadr.addr;
h = _yp_gethostnamadr(as->as_type, data);
@@ -338,6 +312,7 @@ gethostnamadr_async_run(struct async *as, struct async_res *ar)
/* If we got a packet but no anwser, use the next DB. */
if (ar->ar_count == 0) {
free(ar->ar_data);
+ as->as.hostnamadr.h_errno = ar->ar_h_errno;
async_set_state(as, ASR_STATE_NEXT_DB);
break;
}
@@ -383,7 +358,10 @@ gethostnamadr_async_run(struct async *as, struct async_res *ar)
case ASR_STATE_NOT_FOUND:
ar->ar_errno = 0;
- ar->ar_h_errno = HOST_NOT_FOUND;
+ if (as->as.hostnamadr.h_errno)
+ ar->ar_h_errno = as->as.hostnamadr.h_errno;
+ else
+ ar->ar_h_errno = HOST_NOT_FOUND;
async_set_state(as, ASR_STATE_HALT);
break;
diff --git a/lib/libc/asr/res_search_async.c b/lib/libc/asr/res_search_async.c
index 915b0fea84e..5310a106263 100644
--- a/lib/libc/asr/res_search_async.c
+++ b/lib/libc/asr/res_search_async.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: res_search_async.c,v 1.3 2012/11/24 15:12:48 eric Exp $ */
+/* $OpenBSD: res_search_async.c,v 1.4 2013/03/27 07:40:41 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
@@ -177,7 +177,7 @@ res_search_async_run(struct async *as, struct async_res *ar)
free(ar->ar_data);
/*
- * The original resolver does something like this, to
+ * The original resolver does something like this.
*/
if (as->as_dom_flags & (ASYNC_DOM_NDOTS | ASYNC_DOM_ASIS))
as->as.search.saved_h_errno = ar->ar_h_errno;
diff --git a/lib/libc/asr/res_send_async.c b/lib/libc/asr/res_send_async.c
index 72efa178a41..374cc4336c5 100644
--- a/lib/libc/asr/res_send_async.c
+++ b/lib/libc/asr/res_send_async.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: res_send_async.c,v 1.6 2012/11/24 15:12:48 eric Exp $ */
+/* $OpenBSD: res_send_async.c,v 1.7 2013/03/27 07:40:41 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
@@ -150,7 +150,7 @@ res_query_async_ctx(const char *name, int class, int type, unsigned char *ans,
as->as.dns.ibuflen = 0;
/* This adds a "." to name if it doesn't already has one.
- * That's how res_query() behaves (trough res_mkquery").
+ * That's how res_query() behaves (through res_mkquery").
*/
if (setup_query(as, name, NULL, class, type) == -1)
goto err; /* errno set */