xref: /openbsd-src/lib/libc/asr/asr_run.3 (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1.\"	$OpenBSD: asr_run.3,v 1.3 2017/02/18 19:23:05 jca Exp $
2.\"
3.\" Copyright (c) 2012-2014, Eric Faurot <eric@openbsd.org>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd $Mdocdate: February 18 2017 $
18.Dt ASR_RUN 3
19.Os
20.Sh NAME
21.Nm asr_run ,
22.Nm asr_run_sync ,
23.Nm asr_abort ,
24.Nm res_send_async ,
25.Nm res_query_async ,
26.Nm res_search_async ,
27.Nm getrrsetbyname_async ,
28.Nm gethostbyname_async ,
29.Nm gethostbyname2_async ,
30.Nm gethostbyaddr_async ,
31.Nm getnetbyname_async ,
32.Nm getnetbyaddr_async ,
33.Nm getaddrinfo_async ,
34.Nm getnameinfo_async
35.Nd asynchronous resolver functions
36.Sh SYNOPSIS
37.In sys/types.h
38.In sys/socket.h
39.In netdb.h
40.In asr.h
41.Ft int
42.Fn asr_run "struct asr_query *aq" "struct asr_result *ar"
43.Ft int
44.Fn asr_run_sync "struct asr_query *aq" "struct asr_result *ar"
45.Ft void
46.Fn asr_abort "struct asr_query *aq"
47.Ft struct asr_query *
48.Fn res_send_async "const unsigned char *pkt" "int pktlen" "void *asr"
49.Ft struct asr_query *
50.Fn res_query_async "const char *name" "int class" "int type" "void *asr"
51.Ft struct asr_query *
52.Fn res_search_async "const char *name" "int class" "int type" "void *asr"
53.Ft struct asr_query *
54.Fn getrrsetbyname_async "const char *hostname" "unsigned int rdclass" "unsigned int rdtype" "unsigned int flags" "void *asr"
55.Ft struct asr_query *
56.Fn gethostbyname_async "const char *name" "void *asr"
57.Ft struct asr_query *
58.Fn gethostbyname2_async "const char *name" "int af" "void *asr"
59.Ft struct asr_query *
60.Fn gethostbyaddr_async "const void *addr" "socklen_t len" "int af" "void *asr"
61.Ft struct asr_query *
62.Fn getnetbyname_async "const char *name" "void *asr"
63.Ft struct asr_query *
64.Fn getnetbyaddr_async "in_addr_t net" "int type" "void *asr"
65.Ft struct asr_query *
66.Fn getaddrinfo_async "const char *hostname" "const char *servname" "const struct addrinfo *hints" "void *asr"
67.Ft struct asr_query *
68.Fn getnameinfo_async "const struct sockaddr *sa" "socklen_t salen" "char *host" "size_t hostlen" "char *serv" "size_t servlen" "int flags" "void *asr"
69.Sh DESCRIPTION
70The
71.Nm asr
72functions provide a simple interface for asynchronous address
73resolution and nameserver querying.
74They should be used in place of the classical resolver functions
75of libc when blocking is not desirable.
76.Pp
77The principle of operation is as follows:
78All async requests are made against an
79.Nm asr
80context which basically defines a list of sources to query and a
81strategy to do so.
82The user creates a query through one of the dedicated functions, and
83gets a handle representing the internal query.
84A query is a state-machine that can be run to try to fulfill a
85particular request.
86This is done by calling in a generic API that performs the state
87transitions until it needs to give the control back to the user,
88either because a result is available, or because the next transition
89implies a blocking call (a file descriptor needs to be read from or
90written to).
91The user is responsible for dealing with the situation: either get
92the result, or wait until the fd conditions are met, and then call
93back into the resolving machinery when it is ready to proceed.
94.Pp
95The
96.Fn asr_run
97function drives the resolving process.
98It runs the asynchronous query represented by the
99.Fa aq
100handle until a result is available, or until it cannot continue
101without blocking.
102The results are returned to the user through the
103.Fa ar
104parameter, which must be a valid pointer to user allocated memory.
105.Fa ar
106is defined as:
107.Bd -literal
108struct asr_result {
109
110	/* Fields set if the query is not done yet (asr_run returns 0) */
111	int	 ar_cond;	/* ASR_WANT_READ or ASR_WANT_WRITE */
112	int	 ar_fd;		/* the fd waiting for io condition */
113	int	 ar_timeout;	/* time to wait for in milliseconds */
114
115	/* Error fields.  Depends on the query type. */
116	int	 ar_errno;
117	int	 ar_h_errno;
118	int	 ar_gai_errno;
119	int	 ar_rrset_errno;
120
121	/* Result for res_*_async() calls */
122	int	 ar_count;	/* number of answers in the dns reply */
123	int	 ar_rcode;	/* response code in the dns reply */
124	void	*ar_data;	/* raw reply packet (must be freed) */
125	int	 ar_datalen;	/* reply packet length */
126	struct sockaddr_storage ar_ns; /* nameserver that responded */
127
128	/* Result for other calls. Must be freed properly. */
129	struct addrinfo	 *ar_addrinfo;
130	struct rrsetinfo *ar_rrsetinfo;
131	struct hostent	 *ar_hostent;
132	struct netent	 *ar_netent;
133};
134.Ed
135.Pp
136The function returns one of the following values:
137.Bl -tag -width "0 " -offset indent
138.It 0
139The query cannot be processed further until a specific condition on a
140file descriptor becomes true.
141The following members of the
142.Fa ar
143structure are filled:
144.Pp
145.Bl -tag -width "ar_timeout " -compact
146.It Fa ar_cond
147one of ASR_WANT_READ or ASR_WANT_WRITE,
148.It Fa ar_fd
149the file descriptor waiting for an IO operation,
150.It Fa ar_timeout
151the amount of time to wait for in milliseconds.
152.El
153.Pp
154The caller is expected to call
155.Fn asr_run
156again once the condition holds or the timeout expires.
157.It 1
158The query is completed.
159The members relevant to the actual async query type are set accordingly,
160including error conditions.
161In any case, the query is cleared and its handle is invalidated.
162.El
163.Pp
164Note that although the query itself may fail (the error being properly reported
165in the
166.Fa ar
167structure), the
168.Fn asr_run
169function itself cannot fail and it always preserves errno.
170.Pp
171The
172.Fn asr_run_sync
173function is a wrapper around
174.Fn asr_run
175that handles the read/write conditions, thus falling back to a blocking
176interface.
177It only returns 1.
178It also preserves errno.
179.Pp
180The
181.Fn asr_abort
182function clears a running query.
183It can be called when the query is waiting on a file descriptor.
184Note that a completed query is already cleared when
185.Fn asr_run
186returns, so
187.Fn asr_abort
188must not be called in this case.
189.Pp
190The remaining functions are used to initiate different kinds of query
191on the
192.Fa asr
193resolver context.
194The specific operational details for each of them are described below.
195All functions return a handle to an internal query, or NULL if they could
196not allocate the necessary resources to initiate the query.
197All other errors (especially invalid parameters) are reported when calling
198.Fn asr_run .
199They usually have the same interface as an existing resolver function, with
200an additional
201.Ar asr
202argument, which specifies the context to use for this request.
203For now, the argument must always be NULL, which will use the default
204context for the current thread.
205.Pp
206The
207.Fn res_send_async ,
208.Fn res_query_async
209and
210.Fn res_search_async
211functions are asynchronous versions of the standard libc resolver routines.
212Their interface is very similar, except that the response buffer is always
213allocated internally.
214The return value is found upon completion in the
215.Fa ar_datalen
216member of the response structure.
217In addition, the
218.Fa ar_ns
219structure contains the address of the DNS server that sent the response,
220.Fa ar_rcode
221contains the code returned by the server in the DNS response packet, and
222.Fa ar_count
223contains the number of answers in the packet.
224If a response is received it is placed in a newly allocated buffer
225and returned as
226.Fa ar_data
227member.
228This buffer must be freed by the caller.
229On error, the
230.Fa ar_errno
231and
232.Fa ar_h_errno
233members are set accordingly.
234.Pp
235The
236.Fn getrrsetbyname_async
237function is an asynchronous version of
238.Xr getrrsetbyname 3 .
239Upon completion, the return code is found in
240.Fa ar_rrset_errno
241and the address to the newly allocated result set is set in
242.Fa ar_rrsetinfo .
243As for the blocking function, it must be freed by calling
244.Xr freerrset 3 .
245.Pp
246The
247.Fn gethostbyname_async ,
248.Fn gethostbyname2_async
249and
250.Fn gethostbyaddr_async
251functions provide an asynchronous version of the network host entry functions.
252Upon completion,
253.Ar ar_h_errno
254is set and the resulting hostent address, if found, is set
255in the
256.Ar ar_hostent
257field.
258Note that unlike their blocking counterparts, these functions always return a
259pointer to newly allocated memory, which must be released by the caller using
260.Xr free 3 .
261.Pp
262Similarly, the
263.Fn getnetbyname_async
264and
265.Fn getnetbyaddr_async
266functions provide an asynchronous version of the network entry functions.
267Upon completion,
268.Ar ar_h_errno
269is set and the resulting netent address, if found, is set
270in the
271.Ar ar_netent
272field.
273The memory there is also allocated for the request, and it must be freed by
274.Xr free 3 .
275.Pp
276The
277.Fn getaddrinfo_async
278function is an asynchronous version of the
279.Xr getaddrinfo 3
280call.
281It provides a chain of addrinfo structures with all valid combinations of
282socket address for the given
283.Fa hostname ,
284.Fa servname
285and
286.Fa hints .
287Those three parameters have the same meaning as for the blocking counterpart.
288Upon completion the return code is set in
289.Fa ar_gai_errno .
290The
291.Fa ar_errno
292member may also be set.
293On success, the
294.Fa ar_addrinfo
295member points to a newly allocated list of addrinfo.
296This list must be freed with
297.Xr freeaddrinfo 3 .
298.Sh WORKING WITH THREADS
299This implementation of the asynchronous resolver interface is thread-safe
300and lock-free internally, but the following restriction applies:
301Two different threads must not create queries on the same context or
302run queries originating from the same context at the same time.
303If they want to do that, all calls must be protected by a mutex around
304that context.
305.Pp
306It is generally not a problem since the main point of the asynchronous
307resolver is to multiplex queries within a single thread of control,
308so sharing a resolver among threads is not useful.
309.Sh SEE ALSO
310.Xr getaddrinfo 3 ,
311.Xr gethostbyname 3 ,
312.Xr getnameinfo 3 ,
313.Xr getnetbyname 3 ,
314.Xr getrrsetbyname 3 ,
315.Xr res_send 3 ,
316.Xr resolv.conf 5
317