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