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