1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker
25*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
26*6236dae4SAndroid Build Coastguard Worker
27*6236dae4SAndroid Build Coastguard Worker /***********************************************************************
28*6236dae4SAndroid Build Coastguard Worker * Only for ares-enabled builds
29*6236dae4SAndroid Build Coastguard Worker * And only for functions that fulfill the asynch resolver backend API
30*6236dae4SAndroid Build Coastguard Worker * as defined in asyn.h, nothing else belongs in this file!
31*6236dae4SAndroid Build Coastguard Worker **********************************************************************/
32*6236dae4SAndroid Build Coastguard Worker
33*6236dae4SAndroid Build Coastguard Worker #ifdef CURLRES_ARES
34*6236dae4SAndroid Build Coastguard Worker
35*6236dae4SAndroid Build Coastguard Worker #include <limits.h>
36*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
37*6236dae4SAndroid Build Coastguard Worker #include <netinet/in.h>
38*6236dae4SAndroid Build Coastguard Worker #endif
39*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETDB_H
40*6236dae4SAndroid Build Coastguard Worker #include <netdb.h>
41*6236dae4SAndroid Build Coastguard Worker #endif
42*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
43*6236dae4SAndroid Build Coastguard Worker #include <arpa/inet.h>
44*6236dae4SAndroid Build Coastguard Worker #endif
45*6236dae4SAndroid Build Coastguard Worker #ifdef __VMS
46*6236dae4SAndroid Build Coastguard Worker #include <in.h>
47*6236dae4SAndroid Build Coastguard Worker #include <inet.h>
48*6236dae4SAndroid Build Coastguard Worker #endif
49*6236dae4SAndroid Build Coastguard Worker
50*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
51*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
52*6236dae4SAndroid Build Coastguard Worker #include "hostip.h"
53*6236dae4SAndroid Build Coastguard Worker #include "hash.h"
54*6236dae4SAndroid Build Coastguard Worker #include "share.h"
55*6236dae4SAndroid Build Coastguard Worker #include "url.h"
56*6236dae4SAndroid Build Coastguard Worker #include "multiif.h"
57*6236dae4SAndroid Build Coastguard Worker #include "inet_pton.h"
58*6236dae4SAndroid Build Coastguard Worker #include "connect.h"
59*6236dae4SAndroid Build Coastguard Worker #include "select.h"
60*6236dae4SAndroid Build Coastguard Worker #include "progress.h"
61*6236dae4SAndroid Build Coastguard Worker #include "timediff.h"
62*6236dae4SAndroid Build Coastguard Worker
63*6236dae4SAndroid Build Coastguard Worker #if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
64*6236dae4SAndroid Build Coastguard Worker defined(_WIN32)
65*6236dae4SAndroid Build Coastguard Worker # define CARES_STATICLIB
66*6236dae4SAndroid Build Coastguard Worker #endif
67*6236dae4SAndroid Build Coastguard Worker #include <ares.h>
68*6236dae4SAndroid Build Coastguard Worker #include <ares_version.h> /* really old c-ares did not include this by
69*6236dae4SAndroid Build Coastguard Worker itself */
70*6236dae4SAndroid Build Coastguard Worker
71*6236dae4SAndroid Build Coastguard Worker #if ARES_VERSION >= 0x010500
72*6236dae4SAndroid Build Coastguard Worker /* c-ares 1.5.0 or later, the callback proto is modified */
73*6236dae4SAndroid Build Coastguard Worker #define HAVE_CARES_CALLBACK_TIMEOUTS 1
74*6236dae4SAndroid Build Coastguard Worker #endif
75*6236dae4SAndroid Build Coastguard Worker
76*6236dae4SAndroid Build Coastguard Worker #if ARES_VERSION >= 0x010601
77*6236dae4SAndroid Build Coastguard Worker /* IPv6 supported since 1.6.1 */
78*6236dae4SAndroid Build Coastguard Worker #define HAVE_CARES_IPV6 1
79*6236dae4SAndroid Build Coastguard Worker #endif
80*6236dae4SAndroid Build Coastguard Worker
81*6236dae4SAndroid Build Coastguard Worker #if ARES_VERSION >= 0x010704
82*6236dae4SAndroid Build Coastguard Worker #define HAVE_CARES_SERVERS_CSV 1
83*6236dae4SAndroid Build Coastguard Worker #define HAVE_CARES_LOCAL_DEV 1
84*6236dae4SAndroid Build Coastguard Worker #define HAVE_CARES_SET_LOCAL 1
85*6236dae4SAndroid Build Coastguard Worker #endif
86*6236dae4SAndroid Build Coastguard Worker
87*6236dae4SAndroid Build Coastguard Worker #if ARES_VERSION >= 0x010b00
88*6236dae4SAndroid Build Coastguard Worker #define HAVE_CARES_PORTS_CSV 1
89*6236dae4SAndroid Build Coastguard Worker #endif
90*6236dae4SAndroid Build Coastguard Worker
91*6236dae4SAndroid Build Coastguard Worker #if ARES_VERSION >= 0x011000
92*6236dae4SAndroid Build Coastguard Worker /* 1.16.0 or later has ares_getaddrinfo */
93*6236dae4SAndroid Build Coastguard Worker #define HAVE_CARES_GETADDRINFO 1
94*6236dae4SAndroid Build Coastguard Worker #endif
95*6236dae4SAndroid Build Coastguard Worker
96*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
97*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
98*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
99*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
100*6236dae4SAndroid Build Coastguard Worker
101*6236dae4SAndroid Build Coastguard Worker struct thread_data {
102*6236dae4SAndroid Build Coastguard Worker int num_pending; /* number of outstanding c-ares requests */
103*6236dae4SAndroid Build Coastguard Worker struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
104*6236dae4SAndroid Build Coastguard Worker parts */
105*6236dae4SAndroid Build Coastguard Worker int last_status;
106*6236dae4SAndroid Build Coastguard Worker #ifndef HAVE_CARES_GETADDRINFO
107*6236dae4SAndroid Build Coastguard Worker struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
108*6236dae4SAndroid Build Coastguard Worker #endif
109*6236dae4SAndroid Build Coastguard Worker char hostname[1];
110*6236dae4SAndroid Build Coastguard Worker };
111*6236dae4SAndroid Build Coastguard Worker
112*6236dae4SAndroid Build Coastguard Worker /* How long we are willing to wait for additional parallel responses after
113*6236dae4SAndroid Build Coastguard Worker obtaining a "definitive" one. For old c-ares without getaddrinfo.
114*6236dae4SAndroid Build Coastguard Worker
115*6236dae4SAndroid Build Coastguard Worker This is intended to equal the c-ares default timeout. cURL always uses that
116*6236dae4SAndroid Build Coastguard Worker default value. Unfortunately, c-ares does not expose its default timeout in
117*6236dae4SAndroid Build Coastguard Worker its API, but it is officially documented as 5 seconds.
118*6236dae4SAndroid Build Coastguard Worker
119*6236dae4SAndroid Build Coastguard Worker See query_completed_cb() for an explanation of how this is used.
120*6236dae4SAndroid Build Coastguard Worker */
121*6236dae4SAndroid Build Coastguard Worker #define HAPPY_EYEBALLS_DNS_TIMEOUT 5000
122*6236dae4SAndroid Build Coastguard Worker
123*6236dae4SAndroid Build Coastguard Worker #define CARES_TIMEOUT_PER_ATTEMPT 2000
124*6236dae4SAndroid Build Coastguard Worker
125*6236dae4SAndroid Build Coastguard Worker static int ares_ver = 0;
126*6236dae4SAndroid Build Coastguard Worker
127*6236dae4SAndroid Build Coastguard Worker /*
128*6236dae4SAndroid Build Coastguard Worker * Curl_resolver_global_init() - the generic low-level asynchronous name
129*6236dae4SAndroid Build Coastguard Worker * resolve API. Called from curl_global_init() to initialize global resolver
130*6236dae4SAndroid Build Coastguard Worker * environment. Initializes ares library.
131*6236dae4SAndroid Build Coastguard Worker */
Curl_resolver_global_init(void)132*6236dae4SAndroid Build Coastguard Worker int Curl_resolver_global_init(void)
133*6236dae4SAndroid Build Coastguard Worker {
134*6236dae4SAndroid Build Coastguard Worker #ifdef CARES_HAVE_ARES_LIBRARY_INIT
135*6236dae4SAndroid Build Coastguard Worker if(ares_library_init(ARES_LIB_INIT_ALL)) {
136*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
137*6236dae4SAndroid Build Coastguard Worker }
138*6236dae4SAndroid Build Coastguard Worker #endif
139*6236dae4SAndroid Build Coastguard Worker ares_version(&ares_ver);
140*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
141*6236dae4SAndroid Build Coastguard Worker }
142*6236dae4SAndroid Build Coastguard Worker
143*6236dae4SAndroid Build Coastguard Worker /*
144*6236dae4SAndroid Build Coastguard Worker * Curl_resolver_global_cleanup()
145*6236dae4SAndroid Build Coastguard Worker *
146*6236dae4SAndroid Build Coastguard Worker * Called from curl_global_cleanup() to destroy global resolver environment.
147*6236dae4SAndroid Build Coastguard Worker * Deinitializes ares library.
148*6236dae4SAndroid Build Coastguard Worker */
Curl_resolver_global_cleanup(void)149*6236dae4SAndroid Build Coastguard Worker void Curl_resolver_global_cleanup(void)
150*6236dae4SAndroid Build Coastguard Worker {
151*6236dae4SAndroid Build Coastguard Worker #ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP
152*6236dae4SAndroid Build Coastguard Worker ares_library_cleanup();
153*6236dae4SAndroid Build Coastguard Worker #endif
154*6236dae4SAndroid Build Coastguard Worker }
155*6236dae4SAndroid Build Coastguard Worker
156*6236dae4SAndroid Build Coastguard Worker
sock_state_cb(void * data,ares_socket_t socket_fd,int readable,int writable)157*6236dae4SAndroid Build Coastguard Worker static void sock_state_cb(void *data, ares_socket_t socket_fd,
158*6236dae4SAndroid Build Coastguard Worker int readable, int writable)
159*6236dae4SAndroid Build Coastguard Worker {
160*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *easy = data;
161*6236dae4SAndroid Build Coastguard Worker if(!readable && !writable) {
162*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(easy);
163*6236dae4SAndroid Build Coastguard Worker Curl_multi_closed(easy, socket_fd);
164*6236dae4SAndroid Build Coastguard Worker }
165*6236dae4SAndroid Build Coastguard Worker }
166*6236dae4SAndroid Build Coastguard Worker
167*6236dae4SAndroid Build Coastguard Worker /*
168*6236dae4SAndroid Build Coastguard Worker * Curl_resolver_init()
169*6236dae4SAndroid Build Coastguard Worker *
170*6236dae4SAndroid Build Coastguard Worker * Called from curl_easy_init() -> Curl_open() to initialize resolver
171*6236dae4SAndroid Build Coastguard Worker * URL-state specific environment ('resolver' member of the UrlState
172*6236dae4SAndroid Build Coastguard Worker * structure). Fills the passed pointer by the initialized ares_channel.
173*6236dae4SAndroid Build Coastguard Worker */
Curl_resolver_init(struct Curl_easy * easy,void ** resolver)174*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
175*6236dae4SAndroid Build Coastguard Worker {
176*6236dae4SAndroid Build Coastguard Worker int status;
177*6236dae4SAndroid Build Coastguard Worker struct ares_options options;
178*6236dae4SAndroid Build Coastguard Worker int optmask = ARES_OPT_SOCK_STATE_CB;
179*6236dae4SAndroid Build Coastguard Worker options.sock_state_cb = sock_state_cb;
180*6236dae4SAndroid Build Coastguard Worker options.sock_state_cb_data = easy;
181*6236dae4SAndroid Build Coastguard Worker
182*6236dae4SAndroid Build Coastguard Worker /*
183*6236dae4SAndroid Build Coastguard Worker if c ares < 1.20.0: curl set timeout to CARES_TIMEOUT_PER_ATTEMPT (2s)
184*6236dae4SAndroid Build Coastguard Worker
185*6236dae4SAndroid Build Coastguard Worker if c-ares >= 1.20.0 it already has the timeout to 2s, curl does not need
186*6236dae4SAndroid Build Coastguard Worker to set the timeout value;
187*6236dae4SAndroid Build Coastguard Worker
188*6236dae4SAndroid Build Coastguard Worker if c-ares >= 1.24.0, user can set the timeout via /etc/resolv.conf to
189*6236dae4SAndroid Build Coastguard Worker overwrite c-ares' timeout.
190*6236dae4SAndroid Build Coastguard Worker */
191*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(ares_ver);
192*6236dae4SAndroid Build Coastguard Worker if(ares_ver < 0x011400) {
193*6236dae4SAndroid Build Coastguard Worker options.timeout = CARES_TIMEOUT_PER_ATTEMPT;
194*6236dae4SAndroid Build Coastguard Worker optmask |= ARES_OPT_TIMEOUTMS;
195*6236dae4SAndroid Build Coastguard Worker }
196*6236dae4SAndroid Build Coastguard Worker
197*6236dae4SAndroid Build Coastguard Worker status = ares_init_options((ares_channel*)resolver, &options, optmask);
198*6236dae4SAndroid Build Coastguard Worker if(status != ARES_SUCCESS) {
199*6236dae4SAndroid Build Coastguard Worker if(status == ARES_ENOMEM)
200*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
201*6236dae4SAndroid Build Coastguard Worker else
202*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
203*6236dae4SAndroid Build Coastguard Worker }
204*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
205*6236dae4SAndroid Build Coastguard Worker /* make sure that all other returns from this function should destroy the
206*6236dae4SAndroid Build Coastguard Worker ares channel before returning error! */
207*6236dae4SAndroid Build Coastguard Worker }
208*6236dae4SAndroid Build Coastguard Worker
209*6236dae4SAndroid Build Coastguard Worker /*
210*6236dae4SAndroid Build Coastguard Worker * Curl_resolver_cleanup()
211*6236dae4SAndroid Build Coastguard Worker *
212*6236dae4SAndroid Build Coastguard Worker * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
213*6236dae4SAndroid Build Coastguard Worker * URL-state specific environment ('resolver' member of the UrlState
214*6236dae4SAndroid Build Coastguard Worker * structure). Destroys the ares channel.
215*6236dae4SAndroid Build Coastguard Worker */
Curl_resolver_cleanup(void * resolver)216*6236dae4SAndroid Build Coastguard Worker void Curl_resolver_cleanup(void *resolver)
217*6236dae4SAndroid Build Coastguard Worker {
218*6236dae4SAndroid Build Coastguard Worker ares_destroy((ares_channel)resolver);
219*6236dae4SAndroid Build Coastguard Worker }
220*6236dae4SAndroid Build Coastguard Worker
221*6236dae4SAndroid Build Coastguard Worker /*
222*6236dae4SAndroid Build Coastguard Worker * Curl_resolver_duphandle()
223*6236dae4SAndroid Build Coastguard Worker *
224*6236dae4SAndroid Build Coastguard Worker * Called from curl_easy_duphandle() to duplicate resolver URL-state specific
225*6236dae4SAndroid Build Coastguard Worker * environment ('resolver' member of the UrlState structure). Duplicates the
226*6236dae4SAndroid Build Coastguard Worker * 'from' ares channel and passes the resulting channel to the 'to' pointer.
227*6236dae4SAndroid Build Coastguard Worker */
Curl_resolver_duphandle(struct Curl_easy * easy,void ** to,void * from)228*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
229*6236dae4SAndroid Build Coastguard Worker {
230*6236dae4SAndroid Build Coastguard Worker (void)from;
231*6236dae4SAndroid Build Coastguard Worker /*
232*6236dae4SAndroid Build Coastguard Worker * it would be better to call ares_dup instead, but right now
233*6236dae4SAndroid Build Coastguard Worker * it is not possible to set 'sock_state_cb_data' outside of
234*6236dae4SAndroid Build Coastguard Worker * ares_init_options
235*6236dae4SAndroid Build Coastguard Worker */
236*6236dae4SAndroid Build Coastguard Worker return Curl_resolver_init(easy, to);
237*6236dae4SAndroid Build Coastguard Worker }
238*6236dae4SAndroid Build Coastguard Worker
239*6236dae4SAndroid Build Coastguard Worker static void destroy_async_data(struct Curl_async *async);
240*6236dae4SAndroid Build Coastguard Worker
241*6236dae4SAndroid Build Coastguard Worker /*
242*6236dae4SAndroid Build Coastguard Worker * Cancel all possibly still on-going resolves for this connection.
243*6236dae4SAndroid Build Coastguard Worker */
Curl_resolver_cancel(struct Curl_easy * data)244*6236dae4SAndroid Build Coastguard Worker void Curl_resolver_cancel(struct Curl_easy *data)
245*6236dae4SAndroid Build Coastguard Worker {
246*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
247*6236dae4SAndroid Build Coastguard Worker if(data->state.async.resolver)
248*6236dae4SAndroid Build Coastguard Worker ares_cancel((ares_channel)data->state.async.resolver);
249*6236dae4SAndroid Build Coastguard Worker destroy_async_data(&data->state.async);
250*6236dae4SAndroid Build Coastguard Worker }
251*6236dae4SAndroid Build Coastguard Worker
252*6236dae4SAndroid Build Coastguard Worker /*
253*6236dae4SAndroid Build Coastguard Worker * We are equivalent to Curl_resolver_cancel() for the c-ares resolver. We
254*6236dae4SAndroid Build Coastguard Worker * never block.
255*6236dae4SAndroid Build Coastguard Worker */
Curl_resolver_kill(struct Curl_easy * data)256*6236dae4SAndroid Build Coastguard Worker void Curl_resolver_kill(struct Curl_easy *data)
257*6236dae4SAndroid Build Coastguard Worker {
258*6236dae4SAndroid Build Coastguard Worker /* We do not need to check the resolver state because we can be called safely
259*6236dae4SAndroid Build Coastguard Worker at any time and we always do the same thing. */
260*6236dae4SAndroid Build Coastguard Worker Curl_resolver_cancel(data);
261*6236dae4SAndroid Build Coastguard Worker }
262*6236dae4SAndroid Build Coastguard Worker
263*6236dae4SAndroid Build Coastguard Worker /*
264*6236dae4SAndroid Build Coastguard Worker * destroy_async_data() cleans up async resolver data.
265*6236dae4SAndroid Build Coastguard Worker */
destroy_async_data(struct Curl_async * async)266*6236dae4SAndroid Build Coastguard Worker static void destroy_async_data(struct Curl_async *async)
267*6236dae4SAndroid Build Coastguard Worker {
268*6236dae4SAndroid Build Coastguard Worker if(async->tdata) {
269*6236dae4SAndroid Build Coastguard Worker struct thread_data *res = async->tdata;
270*6236dae4SAndroid Build Coastguard Worker if(res) {
271*6236dae4SAndroid Build Coastguard Worker if(res->temp_ai) {
272*6236dae4SAndroid Build Coastguard Worker Curl_freeaddrinfo(res->temp_ai);
273*6236dae4SAndroid Build Coastguard Worker res->temp_ai = NULL;
274*6236dae4SAndroid Build Coastguard Worker }
275*6236dae4SAndroid Build Coastguard Worker free(res);
276*6236dae4SAndroid Build Coastguard Worker }
277*6236dae4SAndroid Build Coastguard Worker async->tdata = NULL;
278*6236dae4SAndroid Build Coastguard Worker }
279*6236dae4SAndroid Build Coastguard Worker }
280*6236dae4SAndroid Build Coastguard Worker
281*6236dae4SAndroid Build Coastguard Worker /*
282*6236dae4SAndroid Build Coastguard Worker * Curl_resolver_getsock() is called when someone from the outside world
283*6236dae4SAndroid Build Coastguard Worker * (using curl_multi_fdset()) wants to get our fd_set setup and we are talking
284*6236dae4SAndroid Build Coastguard Worker * with ares. The caller must make sure that this function is only called when
285*6236dae4SAndroid Build Coastguard Worker * we have a working ares channel.
286*6236dae4SAndroid Build Coastguard Worker *
287*6236dae4SAndroid Build Coastguard Worker * Returns: sockets-in-use-bitmap
288*6236dae4SAndroid Build Coastguard Worker */
289*6236dae4SAndroid Build Coastguard Worker
Curl_resolver_getsock(struct Curl_easy * data,curl_socket_t * socks)290*6236dae4SAndroid Build Coastguard Worker int Curl_resolver_getsock(struct Curl_easy *data,
291*6236dae4SAndroid Build Coastguard Worker curl_socket_t *socks)
292*6236dae4SAndroid Build Coastguard Worker {
293*6236dae4SAndroid Build Coastguard Worker struct timeval maxtime = { CURL_TIMEOUT_RESOLVE, 0 };
294*6236dae4SAndroid Build Coastguard Worker struct timeval timebuf;
295*6236dae4SAndroid Build Coastguard Worker int max = ares_getsock((ares_channel)data->state.async.resolver,
296*6236dae4SAndroid Build Coastguard Worker (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
297*6236dae4SAndroid Build Coastguard Worker struct timeval *timeout =
298*6236dae4SAndroid Build Coastguard Worker ares_timeout((ares_channel)data->state.async.resolver, &maxtime, &timebuf);
299*6236dae4SAndroid Build Coastguard Worker timediff_t milli = curlx_tvtoms(timeout);
300*6236dae4SAndroid Build Coastguard Worker Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
301*6236dae4SAndroid Build Coastguard Worker return max;
302*6236dae4SAndroid Build Coastguard Worker }
303*6236dae4SAndroid Build Coastguard Worker
304*6236dae4SAndroid Build Coastguard Worker /*
305*6236dae4SAndroid Build Coastguard Worker * waitperform()
306*6236dae4SAndroid Build Coastguard Worker *
307*6236dae4SAndroid Build Coastguard Worker * 1) Ask ares what sockets it currently plays with, then
308*6236dae4SAndroid Build Coastguard Worker * 2) wait for the timeout period to check for action on ares' sockets.
309*6236dae4SAndroid Build Coastguard Worker * 3) tell ares to act on all the sockets marked as "with action"
310*6236dae4SAndroid Build Coastguard Worker *
311*6236dae4SAndroid Build Coastguard Worker * return number of sockets it worked on, or -1 on error
312*6236dae4SAndroid Build Coastguard Worker */
313*6236dae4SAndroid Build Coastguard Worker
waitperform(struct Curl_easy * data,timediff_t timeout_ms)314*6236dae4SAndroid Build Coastguard Worker static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
315*6236dae4SAndroid Build Coastguard Worker {
316*6236dae4SAndroid Build Coastguard Worker int nfds;
317*6236dae4SAndroid Build Coastguard Worker int bitmask;
318*6236dae4SAndroid Build Coastguard Worker ares_socket_t socks[ARES_GETSOCK_MAXNUM];
319*6236dae4SAndroid Build Coastguard Worker struct pollfd pfd[ARES_GETSOCK_MAXNUM];
320*6236dae4SAndroid Build Coastguard Worker int i;
321*6236dae4SAndroid Build Coastguard Worker int num = 0;
322*6236dae4SAndroid Build Coastguard Worker
323*6236dae4SAndroid Build Coastguard Worker bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks,
324*6236dae4SAndroid Build Coastguard Worker ARES_GETSOCK_MAXNUM);
325*6236dae4SAndroid Build Coastguard Worker
326*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
327*6236dae4SAndroid Build Coastguard Worker pfd[i].events = 0;
328*6236dae4SAndroid Build Coastguard Worker pfd[i].revents = 0;
329*6236dae4SAndroid Build Coastguard Worker if(ARES_GETSOCK_READABLE(bitmask, i)) {
330*6236dae4SAndroid Build Coastguard Worker pfd[i].fd = socks[i];
331*6236dae4SAndroid Build Coastguard Worker pfd[i].events |= POLLRDNORM|POLLIN;
332*6236dae4SAndroid Build Coastguard Worker }
333*6236dae4SAndroid Build Coastguard Worker if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
334*6236dae4SAndroid Build Coastguard Worker pfd[i].fd = socks[i];
335*6236dae4SAndroid Build Coastguard Worker pfd[i].events |= POLLWRNORM|POLLOUT;
336*6236dae4SAndroid Build Coastguard Worker }
337*6236dae4SAndroid Build Coastguard Worker if(pfd[i].events)
338*6236dae4SAndroid Build Coastguard Worker num++;
339*6236dae4SAndroid Build Coastguard Worker else
340*6236dae4SAndroid Build Coastguard Worker break;
341*6236dae4SAndroid Build Coastguard Worker }
342*6236dae4SAndroid Build Coastguard Worker
343*6236dae4SAndroid Build Coastguard Worker if(num) {
344*6236dae4SAndroid Build Coastguard Worker nfds = Curl_poll(pfd, (unsigned int)num, timeout_ms);
345*6236dae4SAndroid Build Coastguard Worker if(nfds < 0)
346*6236dae4SAndroid Build Coastguard Worker return -1;
347*6236dae4SAndroid Build Coastguard Worker }
348*6236dae4SAndroid Build Coastguard Worker else
349*6236dae4SAndroid Build Coastguard Worker nfds = 0;
350*6236dae4SAndroid Build Coastguard Worker
351*6236dae4SAndroid Build Coastguard Worker if(!nfds)
352*6236dae4SAndroid Build Coastguard Worker /* Call ares_process() unconditionally here, even if we simply timed out
353*6236dae4SAndroid Build Coastguard Worker above, as otherwise the ares name resolve will not timeout! */
354*6236dae4SAndroid Build Coastguard Worker ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD,
355*6236dae4SAndroid Build Coastguard Worker ARES_SOCKET_BAD);
356*6236dae4SAndroid Build Coastguard Worker else {
357*6236dae4SAndroid Build Coastguard Worker /* move through the descriptors and ask for processing on them */
358*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < num; i++)
359*6236dae4SAndroid Build Coastguard Worker ares_process_fd((ares_channel)data->state.async.resolver,
360*6236dae4SAndroid Build Coastguard Worker (pfd[i].revents & (POLLRDNORM|POLLIN)) ?
361*6236dae4SAndroid Build Coastguard Worker pfd[i].fd : ARES_SOCKET_BAD,
362*6236dae4SAndroid Build Coastguard Worker (pfd[i].revents & (POLLWRNORM|POLLOUT)) ?
363*6236dae4SAndroid Build Coastguard Worker pfd[i].fd : ARES_SOCKET_BAD);
364*6236dae4SAndroid Build Coastguard Worker }
365*6236dae4SAndroid Build Coastguard Worker return nfds;
366*6236dae4SAndroid Build Coastguard Worker }
367*6236dae4SAndroid Build Coastguard Worker
368*6236dae4SAndroid Build Coastguard Worker /*
369*6236dae4SAndroid Build Coastguard Worker * Curl_resolver_is_resolved() is called repeatedly to check if a previous
370*6236dae4SAndroid Build Coastguard Worker * name resolve request has completed. It should also make sure to time-out if
371*6236dae4SAndroid Build Coastguard Worker * the operation seems to take too long.
372*6236dae4SAndroid Build Coastguard Worker *
373*6236dae4SAndroid Build Coastguard Worker * Returns normal CURLcode errors.
374*6236dae4SAndroid Build Coastguard Worker */
Curl_resolver_is_resolved(struct Curl_easy * data,struct Curl_dns_entry ** dns)375*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
376*6236dae4SAndroid Build Coastguard Worker struct Curl_dns_entry **dns)
377*6236dae4SAndroid Build Coastguard Worker {
378*6236dae4SAndroid Build Coastguard Worker struct thread_data *res = data->state.async.tdata;
379*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
380*6236dae4SAndroid Build Coastguard Worker
381*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(dns);
382*6236dae4SAndroid Build Coastguard Worker *dns = NULL;
383*6236dae4SAndroid Build Coastguard Worker
384*6236dae4SAndroid Build Coastguard Worker if(waitperform(data, 0) < 0)
385*6236dae4SAndroid Build Coastguard Worker return CURLE_UNRECOVERABLE_POLL;
386*6236dae4SAndroid Build Coastguard Worker
387*6236dae4SAndroid Build Coastguard Worker #ifndef HAVE_CARES_GETADDRINFO
388*6236dae4SAndroid Build Coastguard Worker /* Now that we have checked for any last minute results above, see if there
389*6236dae4SAndroid Build Coastguard Worker are any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
390*6236dae4SAndroid Build Coastguard Worker expires. */
391*6236dae4SAndroid Build Coastguard Worker if(res
392*6236dae4SAndroid Build Coastguard Worker && res->num_pending
393*6236dae4SAndroid Build Coastguard Worker /* This is only set to non-zero if the timer was started. */
394*6236dae4SAndroid Build Coastguard Worker && (res->happy_eyeballs_dns_time.tv_sec
395*6236dae4SAndroid Build Coastguard Worker || res->happy_eyeballs_dns_time.tv_usec)
396*6236dae4SAndroid Build Coastguard Worker && (Curl_timediff(Curl_now(), res->happy_eyeballs_dns_time)
397*6236dae4SAndroid Build Coastguard Worker >= HAPPY_EYEBALLS_DNS_TIMEOUT)) {
398*6236dae4SAndroid Build Coastguard Worker /* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer
399*6236dae4SAndroid Build Coastguard Worker running. */
400*6236dae4SAndroid Build Coastguard Worker memset(
401*6236dae4SAndroid Build Coastguard Worker &res->happy_eyeballs_dns_time, 0, sizeof(res->happy_eyeballs_dns_time));
402*6236dae4SAndroid Build Coastguard Worker
403*6236dae4SAndroid Build Coastguard Worker /* Cancel the raw c-ares request, which will fire query_completed_cb() with
404*6236dae4SAndroid Build Coastguard Worker ARES_ECANCELLED synchronously for all pending responses. This will
405*6236dae4SAndroid Build Coastguard Worker leave us with res->num_pending == 0, which is perfect for the next
406*6236dae4SAndroid Build Coastguard Worker block. */
407*6236dae4SAndroid Build Coastguard Worker ares_cancel((ares_channel)data->state.async.resolver);
408*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(res->num_pending == 0);
409*6236dae4SAndroid Build Coastguard Worker }
410*6236dae4SAndroid Build Coastguard Worker #endif
411*6236dae4SAndroid Build Coastguard Worker
412*6236dae4SAndroid Build Coastguard Worker if(res && !res->num_pending) {
413*6236dae4SAndroid Build Coastguard Worker (void)Curl_addrinfo_callback(data, res->last_status, res->temp_ai);
414*6236dae4SAndroid Build Coastguard Worker /* temp_ai ownership is moved to the connection, so we need not free-up
415*6236dae4SAndroid Build Coastguard Worker them */
416*6236dae4SAndroid Build Coastguard Worker res->temp_ai = NULL;
417*6236dae4SAndroid Build Coastguard Worker
418*6236dae4SAndroid Build Coastguard Worker if(!data->state.async.dns)
419*6236dae4SAndroid Build Coastguard Worker result = Curl_resolver_error(data);
420*6236dae4SAndroid Build Coastguard Worker else
421*6236dae4SAndroid Build Coastguard Worker *dns = data->state.async.dns;
422*6236dae4SAndroid Build Coastguard Worker
423*6236dae4SAndroid Build Coastguard Worker destroy_async_data(&data->state.async);
424*6236dae4SAndroid Build Coastguard Worker }
425*6236dae4SAndroid Build Coastguard Worker
426*6236dae4SAndroid Build Coastguard Worker return result;
427*6236dae4SAndroid Build Coastguard Worker }
428*6236dae4SAndroid Build Coastguard Worker
429*6236dae4SAndroid Build Coastguard Worker /*
430*6236dae4SAndroid Build Coastguard Worker * Curl_resolver_wait_resolv()
431*6236dae4SAndroid Build Coastguard Worker *
432*6236dae4SAndroid Build Coastguard Worker * Waits for a resolve to finish. This function should be avoided since using
433*6236dae4SAndroid Build Coastguard Worker * this risk getting the multi interface to "hang".
434*6236dae4SAndroid Build Coastguard Worker *
435*6236dae4SAndroid Build Coastguard Worker * 'entry' MUST be non-NULL.
436*6236dae4SAndroid Build Coastguard Worker *
437*6236dae4SAndroid Build Coastguard Worker * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
438*6236dae4SAndroid Build Coastguard Worker * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
439*6236dae4SAndroid Build Coastguard Worker */
Curl_resolver_wait_resolv(struct Curl_easy * data,struct Curl_dns_entry ** entry)440*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
441*6236dae4SAndroid Build Coastguard Worker struct Curl_dns_entry **entry)
442*6236dae4SAndroid Build Coastguard Worker {
443*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
444*6236dae4SAndroid Build Coastguard Worker timediff_t timeout;
445*6236dae4SAndroid Build Coastguard Worker struct curltime now = Curl_now();
446*6236dae4SAndroid Build Coastguard Worker
447*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(entry);
448*6236dae4SAndroid Build Coastguard Worker *entry = NULL; /* clear on entry */
449*6236dae4SAndroid Build Coastguard Worker
450*6236dae4SAndroid Build Coastguard Worker timeout = Curl_timeleft(data, &now, TRUE);
451*6236dae4SAndroid Build Coastguard Worker if(timeout < 0) {
452*6236dae4SAndroid Build Coastguard Worker /* already expired! */
453*6236dae4SAndroid Build Coastguard Worker connclose(data->conn, "Timed out before name resolve started");
454*6236dae4SAndroid Build Coastguard Worker return CURLE_OPERATION_TIMEDOUT;
455*6236dae4SAndroid Build Coastguard Worker }
456*6236dae4SAndroid Build Coastguard Worker if(!timeout)
457*6236dae4SAndroid Build Coastguard Worker timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
458*6236dae4SAndroid Build Coastguard Worker
459*6236dae4SAndroid Build Coastguard Worker /* Wait for the name resolve query to complete. */
460*6236dae4SAndroid Build Coastguard Worker while(!result) {
461*6236dae4SAndroid Build Coastguard Worker struct timeval *tvp, tv, store;
462*6236dae4SAndroid Build Coastguard Worker int itimeout;
463*6236dae4SAndroid Build Coastguard Worker timediff_t timeout_ms;
464*6236dae4SAndroid Build Coastguard Worker
465*6236dae4SAndroid Build Coastguard Worker #if TIMEDIFF_T_MAX > INT_MAX
466*6236dae4SAndroid Build Coastguard Worker itimeout = (timeout > INT_MAX) ? INT_MAX : (int)timeout;
467*6236dae4SAndroid Build Coastguard Worker #else
468*6236dae4SAndroid Build Coastguard Worker itimeout = (int)timeout;
469*6236dae4SAndroid Build Coastguard Worker #endif
470*6236dae4SAndroid Build Coastguard Worker
471*6236dae4SAndroid Build Coastguard Worker store.tv_sec = itimeout/1000;
472*6236dae4SAndroid Build Coastguard Worker store.tv_usec = (itimeout%1000)*1000;
473*6236dae4SAndroid Build Coastguard Worker
474*6236dae4SAndroid Build Coastguard Worker tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv);
475*6236dae4SAndroid Build Coastguard Worker
476*6236dae4SAndroid Build Coastguard Worker /* use the timeout period ares returned to us above if less than one
477*6236dae4SAndroid Build Coastguard Worker second is left, otherwise just use 1000ms to make sure the progress
478*6236dae4SAndroid Build Coastguard Worker callback gets called frequent enough */
479*6236dae4SAndroid Build Coastguard Worker if(!tvp->tv_sec)
480*6236dae4SAndroid Build Coastguard Worker timeout_ms = (timediff_t)(tvp->tv_usec/1000);
481*6236dae4SAndroid Build Coastguard Worker else
482*6236dae4SAndroid Build Coastguard Worker timeout_ms = 1000;
483*6236dae4SAndroid Build Coastguard Worker
484*6236dae4SAndroid Build Coastguard Worker if(waitperform(data, timeout_ms) < 0)
485*6236dae4SAndroid Build Coastguard Worker return CURLE_UNRECOVERABLE_POLL;
486*6236dae4SAndroid Build Coastguard Worker result = Curl_resolver_is_resolved(data, entry);
487*6236dae4SAndroid Build Coastguard Worker
488*6236dae4SAndroid Build Coastguard Worker if(result || data->state.async.done)
489*6236dae4SAndroid Build Coastguard Worker break;
490*6236dae4SAndroid Build Coastguard Worker
491*6236dae4SAndroid Build Coastguard Worker if(Curl_pgrsUpdate(data))
492*6236dae4SAndroid Build Coastguard Worker result = CURLE_ABORTED_BY_CALLBACK;
493*6236dae4SAndroid Build Coastguard Worker else {
494*6236dae4SAndroid Build Coastguard Worker struct curltime now2 = Curl_now();
495*6236dae4SAndroid Build Coastguard Worker timediff_t timediff = Curl_timediff(now2, now); /* spent time */
496*6236dae4SAndroid Build Coastguard Worker if(timediff <= 0)
497*6236dae4SAndroid Build Coastguard Worker timeout -= 1; /* always deduct at least 1 */
498*6236dae4SAndroid Build Coastguard Worker else if(timediff > timeout)
499*6236dae4SAndroid Build Coastguard Worker timeout = -1;
500*6236dae4SAndroid Build Coastguard Worker else
501*6236dae4SAndroid Build Coastguard Worker timeout -= timediff;
502*6236dae4SAndroid Build Coastguard Worker now = now2; /* for next loop */
503*6236dae4SAndroid Build Coastguard Worker }
504*6236dae4SAndroid Build Coastguard Worker if(timeout < 0)
505*6236dae4SAndroid Build Coastguard Worker result = CURLE_OPERATION_TIMEDOUT;
506*6236dae4SAndroid Build Coastguard Worker }
507*6236dae4SAndroid Build Coastguard Worker if(result)
508*6236dae4SAndroid Build Coastguard Worker /* failure, so we cancel the ares operation */
509*6236dae4SAndroid Build Coastguard Worker ares_cancel((ares_channel)data->state.async.resolver);
510*6236dae4SAndroid Build Coastguard Worker
511*6236dae4SAndroid Build Coastguard Worker /* Operation complete, if the lookup was successful we now have the entry
512*6236dae4SAndroid Build Coastguard Worker in the cache. */
513*6236dae4SAndroid Build Coastguard Worker if(entry)
514*6236dae4SAndroid Build Coastguard Worker *entry = data->state.async.dns;
515*6236dae4SAndroid Build Coastguard Worker
516*6236dae4SAndroid Build Coastguard Worker if(result)
517*6236dae4SAndroid Build Coastguard Worker /* close the connection, since we cannot return failure here without
518*6236dae4SAndroid Build Coastguard Worker cleaning up this connection properly. */
519*6236dae4SAndroid Build Coastguard Worker connclose(data->conn, "c-ares resolve failed");
520*6236dae4SAndroid Build Coastguard Worker
521*6236dae4SAndroid Build Coastguard Worker return result;
522*6236dae4SAndroid Build Coastguard Worker }
523*6236dae4SAndroid Build Coastguard Worker
524*6236dae4SAndroid Build Coastguard Worker #ifndef HAVE_CARES_GETADDRINFO
525*6236dae4SAndroid Build Coastguard Worker
526*6236dae4SAndroid Build Coastguard Worker /* Connects results to the list */
compound_results(struct thread_data * res,struct Curl_addrinfo * ai)527*6236dae4SAndroid Build Coastguard Worker static void compound_results(struct thread_data *res,
528*6236dae4SAndroid Build Coastguard Worker struct Curl_addrinfo *ai)
529*6236dae4SAndroid Build Coastguard Worker {
530*6236dae4SAndroid Build Coastguard Worker if(!ai)
531*6236dae4SAndroid Build Coastguard Worker return;
532*6236dae4SAndroid Build Coastguard Worker
533*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6 /* CURLRES_IPV6 */
534*6236dae4SAndroid Build Coastguard Worker if(res->temp_ai && res->temp_ai->ai_family == PF_INET6) {
535*6236dae4SAndroid Build Coastguard Worker /* We have results already, put the new IPv6 entries at the head of the
536*6236dae4SAndroid Build Coastguard Worker list. */
537*6236dae4SAndroid Build Coastguard Worker struct Curl_addrinfo *temp_ai_tail = res->temp_ai;
538*6236dae4SAndroid Build Coastguard Worker
539*6236dae4SAndroid Build Coastguard Worker while(temp_ai_tail->ai_next)
540*6236dae4SAndroid Build Coastguard Worker temp_ai_tail = temp_ai_tail->ai_next;
541*6236dae4SAndroid Build Coastguard Worker
542*6236dae4SAndroid Build Coastguard Worker temp_ai_tail->ai_next = ai;
543*6236dae4SAndroid Build Coastguard Worker }
544*6236dae4SAndroid Build Coastguard Worker else
545*6236dae4SAndroid Build Coastguard Worker #endif /* CURLRES_IPV6 */
546*6236dae4SAndroid Build Coastguard Worker {
547*6236dae4SAndroid Build Coastguard Worker /* Add the new results to the list of old results. */
548*6236dae4SAndroid Build Coastguard Worker struct Curl_addrinfo *ai_tail = ai;
549*6236dae4SAndroid Build Coastguard Worker while(ai_tail->ai_next)
550*6236dae4SAndroid Build Coastguard Worker ai_tail = ai_tail->ai_next;
551*6236dae4SAndroid Build Coastguard Worker
552*6236dae4SAndroid Build Coastguard Worker ai_tail->ai_next = res->temp_ai;
553*6236dae4SAndroid Build Coastguard Worker res->temp_ai = ai;
554*6236dae4SAndroid Build Coastguard Worker }
555*6236dae4SAndroid Build Coastguard Worker }
556*6236dae4SAndroid Build Coastguard Worker
557*6236dae4SAndroid Build Coastguard Worker /*
558*6236dae4SAndroid Build Coastguard Worker * ares_query_completed_cb() is the callback that ares will call when
559*6236dae4SAndroid Build Coastguard Worker * the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(),
560*6236dae4SAndroid Build Coastguard Worker * when using ares, is completed either successfully or with failure.
561*6236dae4SAndroid Build Coastguard Worker */
query_completed_cb(void * arg,int status,int timeouts,struct hostent * hostent)562*6236dae4SAndroid Build Coastguard Worker static void query_completed_cb(void *arg, /* (struct connectdata *) */
563*6236dae4SAndroid Build Coastguard Worker int status,
564*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_CARES_CALLBACK_TIMEOUTS
565*6236dae4SAndroid Build Coastguard Worker int timeouts,
566*6236dae4SAndroid Build Coastguard Worker #endif
567*6236dae4SAndroid Build Coastguard Worker struct hostent *hostent)
568*6236dae4SAndroid Build Coastguard Worker {
569*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = (struct Curl_easy *)arg;
570*6236dae4SAndroid Build Coastguard Worker struct thread_data *res;
571*6236dae4SAndroid Build Coastguard Worker
572*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_CARES_CALLBACK_TIMEOUTS
573*6236dae4SAndroid Build Coastguard Worker (void)timeouts; /* ignored */
574*6236dae4SAndroid Build Coastguard Worker #endif
575*6236dae4SAndroid Build Coastguard Worker
576*6236dae4SAndroid Build Coastguard Worker if(ARES_EDESTRUCTION == status)
577*6236dae4SAndroid Build Coastguard Worker /* when this ares handle is getting destroyed, the 'arg' pointer may not
578*6236dae4SAndroid Build Coastguard Worker be valid so only defer it when we know the 'status' says its fine! */
579*6236dae4SAndroid Build Coastguard Worker return;
580*6236dae4SAndroid Build Coastguard Worker
581*6236dae4SAndroid Build Coastguard Worker res = data->state.async.tdata;
582*6236dae4SAndroid Build Coastguard Worker if(res) {
583*6236dae4SAndroid Build Coastguard Worker res->num_pending--;
584*6236dae4SAndroid Build Coastguard Worker
585*6236dae4SAndroid Build Coastguard Worker if(CURL_ASYNC_SUCCESS == status) {
586*6236dae4SAndroid Build Coastguard Worker struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
587*6236dae4SAndroid Build Coastguard Worker if(ai) {
588*6236dae4SAndroid Build Coastguard Worker compound_results(res, ai);
589*6236dae4SAndroid Build Coastguard Worker }
590*6236dae4SAndroid Build Coastguard Worker }
591*6236dae4SAndroid Build Coastguard Worker /* A successful result overwrites any previous error */
592*6236dae4SAndroid Build Coastguard Worker if(res->last_status != ARES_SUCCESS)
593*6236dae4SAndroid Build Coastguard Worker res->last_status = status;
594*6236dae4SAndroid Build Coastguard Worker
595*6236dae4SAndroid Build Coastguard Worker /* If there are responses still pending, we presume they must be the
596*6236dae4SAndroid Build Coastguard Worker complementary IPv4 or IPv6 lookups that we started in parallel in
597*6236dae4SAndroid Build Coastguard Worker Curl_resolver_getaddrinfo() (for Happy Eyeballs). If we have got a
598*6236dae4SAndroid Build Coastguard Worker "definitive" response from one of a set of parallel queries, we need to
599*6236dae4SAndroid Build Coastguard Worker think about how long we are willing to wait for more responses. */
600*6236dae4SAndroid Build Coastguard Worker if(res->num_pending
601*6236dae4SAndroid Build Coastguard Worker /* Only these c-ares status values count as "definitive" for these
602*6236dae4SAndroid Build Coastguard Worker purposes. For example, ARES_ENODATA is what we expect when there is
603*6236dae4SAndroid Build Coastguard Worker no IPv6 entry for a domain name, and that is not a reason to get more
604*6236dae4SAndroid Build Coastguard Worker aggressive in our timeouts for the other response. Other errors are
605*6236dae4SAndroid Build Coastguard Worker either a result of bad input (which should affect all parallel
606*6236dae4SAndroid Build Coastguard Worker requests), local or network conditions, non-definitive server
607*6236dae4SAndroid Build Coastguard Worker responses, or us cancelling the request. */
608*6236dae4SAndroid Build Coastguard Worker && (status == ARES_SUCCESS || status == ARES_ENOTFOUND)) {
609*6236dae4SAndroid Build Coastguard Worker /* Right now, there can only be up to two parallel queries, so do not
610*6236dae4SAndroid Build Coastguard Worker bother handling any other cases. */
611*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(res->num_pending == 1);
612*6236dae4SAndroid Build Coastguard Worker
613*6236dae4SAndroid Build Coastguard Worker /* it is possible that one of these parallel queries could succeed
614*6236dae4SAndroid Build Coastguard Worker quickly, but the other could always fail or timeout (when we are
615*6236dae4SAndroid Build Coastguard Worker talking to a pool of DNS servers that can only successfully resolve
616*6236dae4SAndroid Build Coastguard Worker IPv4 address, for example).
617*6236dae4SAndroid Build Coastguard Worker
618*6236dae4SAndroid Build Coastguard Worker it is also possible that the other request could always just take
619*6236dae4SAndroid Build Coastguard Worker longer because it needs more time or only the second DNS server can
620*6236dae4SAndroid Build Coastguard Worker fulfill it successfully. But, to align with the philosophy of Happy
621*6236dae4SAndroid Build Coastguard Worker Eyeballs, we do not want to wait _too_ long or users will think
622*6236dae4SAndroid Build Coastguard Worker requests are slow when IPv6 lookups do not actually work (but IPv4
623*6236dae4SAndroid Build Coastguard Worker ones do).
624*6236dae4SAndroid Build Coastguard Worker
625*6236dae4SAndroid Build Coastguard Worker So, now that we have a usable answer (some IPv4 addresses, some IPv6
626*6236dae4SAndroid Build Coastguard Worker addresses, or "no such domain"), we start a timeout for the remaining
627*6236dae4SAndroid Build Coastguard Worker pending responses. Even though it is typical that this resolved
628*6236dae4SAndroid Build Coastguard Worker request came back quickly, that needn't be the case. It might be that
629*6236dae4SAndroid Build Coastguard Worker this completing request did not get a result from the first DNS
630*6236dae4SAndroid Build Coastguard Worker server or even the first round of the whole DNS server pool. So it
631*6236dae4SAndroid Build Coastguard Worker could already be quite some time after we issued the DNS queries in
632*6236dae4SAndroid Build Coastguard Worker the first place. Without modifying c-ares, we cannot know exactly
633*6236dae4SAndroid Build Coastguard Worker where in its retry cycle we are. We could guess based on how much
634*6236dae4SAndroid Build Coastguard Worker time has gone by, but it does not really matter. Happy Eyeballs tells
635*6236dae4SAndroid Build Coastguard Worker us that, given usable information in hand, we simply do not want to
636*6236dae4SAndroid Build Coastguard Worker wait "too much longer" after we get a result.
637*6236dae4SAndroid Build Coastguard Worker
638*6236dae4SAndroid Build Coastguard Worker We simply wait an additional amount of time equal to the default
639*6236dae4SAndroid Build Coastguard Worker c-ares query timeout. That is enough time for a typical parallel
640*6236dae4SAndroid Build Coastguard Worker response to arrive without being "too long". Even on a network
641*6236dae4SAndroid Build Coastguard Worker where one of the two types of queries is failing or timing out
642*6236dae4SAndroid Build Coastguard Worker constantly, this will usually mean we wait a total of the default
643*6236dae4SAndroid Build Coastguard Worker c-ares timeout (5 seconds) plus the round trip time for the successful
644*6236dae4SAndroid Build Coastguard Worker request, which seems bearable. The downside is that c-ares might race
645*6236dae4SAndroid Build Coastguard Worker with us to issue one more retry just before we give up, but it seems
646*6236dae4SAndroid Build Coastguard Worker better to "waste" that request instead of trying to guess the perfect
647*6236dae4SAndroid Build Coastguard Worker timeout to prevent it. After all, we do not even know where in the
648*6236dae4SAndroid Build Coastguard Worker c-ares retry cycle each request is.
649*6236dae4SAndroid Build Coastguard Worker */
650*6236dae4SAndroid Build Coastguard Worker res->happy_eyeballs_dns_time = Curl_now();
651*6236dae4SAndroid Build Coastguard Worker Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT,
652*6236dae4SAndroid Build Coastguard Worker EXPIRE_HAPPY_EYEBALLS_DNS);
653*6236dae4SAndroid Build Coastguard Worker }
654*6236dae4SAndroid Build Coastguard Worker }
655*6236dae4SAndroid Build Coastguard Worker }
656*6236dae4SAndroid Build Coastguard Worker #else
657*6236dae4SAndroid Build Coastguard Worker /* c-ares 1.16.0 or later */
658*6236dae4SAndroid Build Coastguard Worker
659*6236dae4SAndroid Build Coastguard Worker /*
660*6236dae4SAndroid Build Coastguard Worker * ares2addr() converts an address list provided by c-ares to an internal
661*6236dae4SAndroid Build Coastguard Worker * libcurl compatible list
662*6236dae4SAndroid Build Coastguard Worker */
ares2addr(struct ares_addrinfo_node * node)663*6236dae4SAndroid Build Coastguard Worker static struct Curl_addrinfo *ares2addr(struct ares_addrinfo_node *node)
664*6236dae4SAndroid Build Coastguard Worker {
665*6236dae4SAndroid Build Coastguard Worker /* traverse the ares_addrinfo_node list */
666*6236dae4SAndroid Build Coastguard Worker struct ares_addrinfo_node *ai;
667*6236dae4SAndroid Build Coastguard Worker struct Curl_addrinfo *cafirst = NULL;
668*6236dae4SAndroid Build Coastguard Worker struct Curl_addrinfo *calast = NULL;
669*6236dae4SAndroid Build Coastguard Worker int error = 0;
670*6236dae4SAndroid Build Coastguard Worker
671*6236dae4SAndroid Build Coastguard Worker for(ai = node; ai != NULL; ai = ai->ai_next) {
672*6236dae4SAndroid Build Coastguard Worker size_t ss_size;
673*6236dae4SAndroid Build Coastguard Worker struct Curl_addrinfo *ca;
674*6236dae4SAndroid Build Coastguard Worker /* ignore elements with unsupported address family, */
675*6236dae4SAndroid Build Coastguard Worker /* settle family-specific sockaddr structure size. */
676*6236dae4SAndroid Build Coastguard Worker if(ai->ai_family == AF_INET)
677*6236dae4SAndroid Build Coastguard Worker ss_size = sizeof(struct sockaddr_in);
678*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
679*6236dae4SAndroid Build Coastguard Worker else if(ai->ai_family == AF_INET6)
680*6236dae4SAndroid Build Coastguard Worker ss_size = sizeof(struct sockaddr_in6);
681*6236dae4SAndroid Build Coastguard Worker #endif
682*6236dae4SAndroid Build Coastguard Worker else
683*6236dae4SAndroid Build Coastguard Worker continue;
684*6236dae4SAndroid Build Coastguard Worker
685*6236dae4SAndroid Build Coastguard Worker /* ignore elements without required address info */
686*6236dae4SAndroid Build Coastguard Worker if(!ai->ai_addr || !(ai->ai_addrlen > 0))
687*6236dae4SAndroid Build Coastguard Worker continue;
688*6236dae4SAndroid Build Coastguard Worker
689*6236dae4SAndroid Build Coastguard Worker /* ignore elements with bogus address size */
690*6236dae4SAndroid Build Coastguard Worker if((size_t)ai->ai_addrlen < ss_size)
691*6236dae4SAndroid Build Coastguard Worker continue;
692*6236dae4SAndroid Build Coastguard Worker
693*6236dae4SAndroid Build Coastguard Worker ca = malloc(sizeof(struct Curl_addrinfo) + ss_size);
694*6236dae4SAndroid Build Coastguard Worker if(!ca) {
695*6236dae4SAndroid Build Coastguard Worker error = EAI_MEMORY;
696*6236dae4SAndroid Build Coastguard Worker break;
697*6236dae4SAndroid Build Coastguard Worker }
698*6236dae4SAndroid Build Coastguard Worker
699*6236dae4SAndroid Build Coastguard Worker /* copy each structure member individually, member ordering, */
700*6236dae4SAndroid Build Coastguard Worker /* size, or padding might be different for each platform. */
701*6236dae4SAndroid Build Coastguard Worker
702*6236dae4SAndroid Build Coastguard Worker ca->ai_flags = ai->ai_flags;
703*6236dae4SAndroid Build Coastguard Worker ca->ai_family = ai->ai_family;
704*6236dae4SAndroid Build Coastguard Worker ca->ai_socktype = ai->ai_socktype;
705*6236dae4SAndroid Build Coastguard Worker ca->ai_protocol = ai->ai_protocol;
706*6236dae4SAndroid Build Coastguard Worker ca->ai_addrlen = (curl_socklen_t)ss_size;
707*6236dae4SAndroid Build Coastguard Worker ca->ai_addr = NULL;
708*6236dae4SAndroid Build Coastguard Worker ca->ai_canonname = NULL;
709*6236dae4SAndroid Build Coastguard Worker ca->ai_next = NULL;
710*6236dae4SAndroid Build Coastguard Worker
711*6236dae4SAndroid Build Coastguard Worker ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
712*6236dae4SAndroid Build Coastguard Worker memcpy(ca->ai_addr, ai->ai_addr, ss_size);
713*6236dae4SAndroid Build Coastguard Worker
714*6236dae4SAndroid Build Coastguard Worker /* if the return list is empty, this becomes the first element */
715*6236dae4SAndroid Build Coastguard Worker if(!cafirst)
716*6236dae4SAndroid Build Coastguard Worker cafirst = ca;
717*6236dae4SAndroid Build Coastguard Worker
718*6236dae4SAndroid Build Coastguard Worker /* add this element last in the return list */
719*6236dae4SAndroid Build Coastguard Worker if(calast)
720*6236dae4SAndroid Build Coastguard Worker calast->ai_next = ca;
721*6236dae4SAndroid Build Coastguard Worker calast = ca;
722*6236dae4SAndroid Build Coastguard Worker }
723*6236dae4SAndroid Build Coastguard Worker
724*6236dae4SAndroid Build Coastguard Worker /* if we failed, destroy the Curl_addrinfo list */
725*6236dae4SAndroid Build Coastguard Worker if(error) {
726*6236dae4SAndroid Build Coastguard Worker Curl_freeaddrinfo(cafirst);
727*6236dae4SAndroid Build Coastguard Worker cafirst = NULL;
728*6236dae4SAndroid Build Coastguard Worker }
729*6236dae4SAndroid Build Coastguard Worker
730*6236dae4SAndroid Build Coastguard Worker return cafirst;
731*6236dae4SAndroid Build Coastguard Worker }
732*6236dae4SAndroid Build Coastguard Worker
addrinfo_cb(void * arg,int status,int timeouts,struct ares_addrinfo * result)733*6236dae4SAndroid Build Coastguard Worker static void addrinfo_cb(void *arg, int status, int timeouts,
734*6236dae4SAndroid Build Coastguard Worker struct ares_addrinfo *result)
735*6236dae4SAndroid Build Coastguard Worker {
736*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = (struct Curl_easy *)arg;
737*6236dae4SAndroid Build Coastguard Worker struct thread_data *res = data->state.async.tdata;
738*6236dae4SAndroid Build Coastguard Worker (void)timeouts;
739*6236dae4SAndroid Build Coastguard Worker if(ARES_SUCCESS == status) {
740*6236dae4SAndroid Build Coastguard Worker res->temp_ai = ares2addr(result->nodes);
741*6236dae4SAndroid Build Coastguard Worker res->last_status = CURL_ASYNC_SUCCESS;
742*6236dae4SAndroid Build Coastguard Worker ares_freeaddrinfo(result);
743*6236dae4SAndroid Build Coastguard Worker }
744*6236dae4SAndroid Build Coastguard Worker res->num_pending--;
745*6236dae4SAndroid Build Coastguard Worker }
746*6236dae4SAndroid Build Coastguard Worker
747*6236dae4SAndroid Build Coastguard Worker #endif
748*6236dae4SAndroid Build Coastguard Worker /*
749*6236dae4SAndroid Build Coastguard Worker * Curl_resolver_getaddrinfo() - when using ares
750*6236dae4SAndroid Build Coastguard Worker *
751*6236dae4SAndroid Build Coastguard Worker * Returns name information about the given hostname and port number. If
752*6236dae4SAndroid Build Coastguard Worker * successful, the 'hostent' is returned and the fourth argument will point to
753*6236dae4SAndroid Build Coastguard Worker * memory we need to free after use. That memory *MUST* be freed with
754*6236dae4SAndroid Build Coastguard Worker * Curl_freeaddrinfo(), nothing else.
755*6236dae4SAndroid Build Coastguard Worker */
Curl_resolver_getaddrinfo(struct Curl_easy * data,const char * hostname,int port,int * waitp)756*6236dae4SAndroid Build Coastguard Worker struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
757*6236dae4SAndroid Build Coastguard Worker const char *hostname,
758*6236dae4SAndroid Build Coastguard Worker int port,
759*6236dae4SAndroid Build Coastguard Worker int *waitp)
760*6236dae4SAndroid Build Coastguard Worker {
761*6236dae4SAndroid Build Coastguard Worker struct thread_data *res = NULL;
762*6236dae4SAndroid Build Coastguard Worker size_t namelen = strlen(hostname);
763*6236dae4SAndroid Build Coastguard Worker *waitp = 0; /* default to synchronous response */
764*6236dae4SAndroid Build Coastguard Worker
765*6236dae4SAndroid Build Coastguard Worker res = calloc(1, sizeof(struct thread_data) + namelen);
766*6236dae4SAndroid Build Coastguard Worker if(res) {
767*6236dae4SAndroid Build Coastguard Worker strcpy(res->hostname, hostname);
768*6236dae4SAndroid Build Coastguard Worker data->state.async.hostname = res->hostname;
769*6236dae4SAndroid Build Coastguard Worker data->state.async.port = port;
770*6236dae4SAndroid Build Coastguard Worker data->state.async.done = FALSE; /* not done */
771*6236dae4SAndroid Build Coastguard Worker data->state.async.status = 0; /* clear */
772*6236dae4SAndroid Build Coastguard Worker data->state.async.dns = NULL; /* clear */
773*6236dae4SAndroid Build Coastguard Worker data->state.async.tdata = res;
774*6236dae4SAndroid Build Coastguard Worker
775*6236dae4SAndroid Build Coastguard Worker /* initial status - failed */
776*6236dae4SAndroid Build Coastguard Worker res->last_status = ARES_ENOTFOUND;
777*6236dae4SAndroid Build Coastguard Worker
778*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_CARES_GETADDRINFO
779*6236dae4SAndroid Build Coastguard Worker {
780*6236dae4SAndroid Build Coastguard Worker struct ares_addrinfo_hints hints;
781*6236dae4SAndroid Build Coastguard Worker char service[12];
782*6236dae4SAndroid Build Coastguard Worker int pf = PF_INET;
783*6236dae4SAndroid Build Coastguard Worker memset(&hints, 0, sizeof(hints));
784*6236dae4SAndroid Build Coastguard Worker #ifdef CURLRES_IPV6
785*6236dae4SAndroid Build Coastguard Worker if((data->conn->ip_version != CURL_IPRESOLVE_V4) &&
786*6236dae4SAndroid Build Coastguard Worker Curl_ipv6works(data)) {
787*6236dae4SAndroid Build Coastguard Worker /* The stack seems to be IPv6-enabled */
788*6236dae4SAndroid Build Coastguard Worker if(data->conn->ip_version == CURL_IPRESOLVE_V6)
789*6236dae4SAndroid Build Coastguard Worker pf = PF_INET6;
790*6236dae4SAndroid Build Coastguard Worker else
791*6236dae4SAndroid Build Coastguard Worker pf = PF_UNSPEC;
792*6236dae4SAndroid Build Coastguard Worker }
793*6236dae4SAndroid Build Coastguard Worker #endif /* CURLRES_IPV6 */
794*6236dae4SAndroid Build Coastguard Worker hints.ai_family = pf;
795*6236dae4SAndroid Build Coastguard Worker hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ?
796*6236dae4SAndroid Build Coastguard Worker SOCK_STREAM : SOCK_DGRAM;
797*6236dae4SAndroid Build Coastguard Worker /* Since the service is a numerical one, set the hint flags
798*6236dae4SAndroid Build Coastguard Worker * accordingly to save a call to getservbyname in inside C-Ares
799*6236dae4SAndroid Build Coastguard Worker */
800*6236dae4SAndroid Build Coastguard Worker hints.ai_flags = ARES_AI_NUMERICSERV;
801*6236dae4SAndroid Build Coastguard Worker msnprintf(service, sizeof(service), "%d", port);
802*6236dae4SAndroid Build Coastguard Worker res->num_pending = 1;
803*6236dae4SAndroid Build Coastguard Worker ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname,
804*6236dae4SAndroid Build Coastguard Worker service, &hints, addrinfo_cb, data);
805*6236dae4SAndroid Build Coastguard Worker }
806*6236dae4SAndroid Build Coastguard Worker #else
807*6236dae4SAndroid Build Coastguard Worker
808*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_CARES_IPV6
809*6236dae4SAndroid Build Coastguard Worker if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
810*6236dae4SAndroid Build Coastguard Worker /* The stack seems to be IPv6-enabled */
811*6236dae4SAndroid Build Coastguard Worker res->num_pending = 2;
812*6236dae4SAndroid Build Coastguard Worker
813*6236dae4SAndroid Build Coastguard Worker /* areschannel is already setup in the Curl_open() function */
814*6236dae4SAndroid Build Coastguard Worker ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
815*6236dae4SAndroid Build Coastguard Worker PF_INET, query_completed_cb, data);
816*6236dae4SAndroid Build Coastguard Worker ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
817*6236dae4SAndroid Build Coastguard Worker PF_INET6, query_completed_cb, data);
818*6236dae4SAndroid Build Coastguard Worker }
819*6236dae4SAndroid Build Coastguard Worker else
820*6236dae4SAndroid Build Coastguard Worker #endif
821*6236dae4SAndroid Build Coastguard Worker {
822*6236dae4SAndroid Build Coastguard Worker res->num_pending = 1;
823*6236dae4SAndroid Build Coastguard Worker
824*6236dae4SAndroid Build Coastguard Worker /* areschannel is already setup in the Curl_open() function */
825*6236dae4SAndroid Build Coastguard Worker ares_gethostbyname((ares_channel)data->state.async.resolver,
826*6236dae4SAndroid Build Coastguard Worker hostname, PF_INET,
827*6236dae4SAndroid Build Coastguard Worker query_completed_cb, data);
828*6236dae4SAndroid Build Coastguard Worker }
829*6236dae4SAndroid Build Coastguard Worker #endif
830*6236dae4SAndroid Build Coastguard Worker *waitp = 1; /* expect asynchronous response */
831*6236dae4SAndroid Build Coastguard Worker }
832*6236dae4SAndroid Build Coastguard Worker return NULL; /* no struct yet */
833*6236dae4SAndroid Build Coastguard Worker }
834*6236dae4SAndroid Build Coastguard Worker
Curl_set_dns_servers(struct Curl_easy * data,char * servers)835*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_set_dns_servers(struct Curl_easy *data,
836*6236dae4SAndroid Build Coastguard Worker char *servers)
837*6236dae4SAndroid Build Coastguard Worker {
838*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_NOT_BUILT_IN;
839*6236dae4SAndroid Build Coastguard Worker int ares_result;
840*6236dae4SAndroid Build Coastguard Worker
841*6236dae4SAndroid Build Coastguard Worker /* If server is NULL or empty, this would purge all DNS servers
842*6236dae4SAndroid Build Coastguard Worker * from ares library, which will cause any and all queries to fail.
843*6236dae4SAndroid Build Coastguard Worker * So, just return OK if none are configured and do not actually make
844*6236dae4SAndroid Build Coastguard Worker * any changes to c-ares. This lets c-ares use its defaults, which
845*6236dae4SAndroid Build Coastguard Worker * it gets from the OS (for instance from /etc/resolv.conf on Linux).
846*6236dae4SAndroid Build Coastguard Worker */
847*6236dae4SAndroid Build Coastguard Worker if(!(servers && servers[0]))
848*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
849*6236dae4SAndroid Build Coastguard Worker
850*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_CARES_SERVERS_CSV
851*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_CARES_PORTS_CSV
852*6236dae4SAndroid Build Coastguard Worker ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
853*6236dae4SAndroid Build Coastguard Worker servers);
854*6236dae4SAndroid Build Coastguard Worker #else
855*6236dae4SAndroid Build Coastguard Worker ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
856*6236dae4SAndroid Build Coastguard Worker #endif
857*6236dae4SAndroid Build Coastguard Worker switch(ares_result) {
858*6236dae4SAndroid Build Coastguard Worker case ARES_SUCCESS:
859*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
860*6236dae4SAndroid Build Coastguard Worker break;
861*6236dae4SAndroid Build Coastguard Worker case ARES_ENOMEM:
862*6236dae4SAndroid Build Coastguard Worker result = CURLE_OUT_OF_MEMORY;
863*6236dae4SAndroid Build Coastguard Worker break;
864*6236dae4SAndroid Build Coastguard Worker case ARES_ENOTINITIALIZED:
865*6236dae4SAndroid Build Coastguard Worker case ARES_ENODATA:
866*6236dae4SAndroid Build Coastguard Worker case ARES_EBADSTR:
867*6236dae4SAndroid Build Coastguard Worker default:
868*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "bad servers set"));
869*6236dae4SAndroid Build Coastguard Worker result = CURLE_BAD_FUNCTION_ARGUMENT;
870*6236dae4SAndroid Build Coastguard Worker break;
871*6236dae4SAndroid Build Coastguard Worker }
872*6236dae4SAndroid Build Coastguard Worker #else /* too old c-ares version! */
873*6236dae4SAndroid Build Coastguard Worker (void)data;
874*6236dae4SAndroid Build Coastguard Worker (void)(ares_result);
875*6236dae4SAndroid Build Coastguard Worker #endif
876*6236dae4SAndroid Build Coastguard Worker return result;
877*6236dae4SAndroid Build Coastguard Worker }
878*6236dae4SAndroid Build Coastguard Worker
Curl_set_dns_interface(struct Curl_easy * data,const char * interf)879*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_set_dns_interface(struct Curl_easy *data,
880*6236dae4SAndroid Build Coastguard Worker const char *interf)
881*6236dae4SAndroid Build Coastguard Worker {
882*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_CARES_LOCAL_DEV
883*6236dae4SAndroid Build Coastguard Worker if(!interf)
884*6236dae4SAndroid Build Coastguard Worker interf = "";
885*6236dae4SAndroid Build Coastguard Worker
886*6236dae4SAndroid Build Coastguard Worker ares_set_local_dev((ares_channel)data->state.async.resolver, interf);
887*6236dae4SAndroid Build Coastguard Worker
888*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
889*6236dae4SAndroid Build Coastguard Worker #else /* c-ares version too old! */
890*6236dae4SAndroid Build Coastguard Worker (void)data;
891*6236dae4SAndroid Build Coastguard Worker (void)interf;
892*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
893*6236dae4SAndroid Build Coastguard Worker #endif
894*6236dae4SAndroid Build Coastguard Worker }
895*6236dae4SAndroid Build Coastguard Worker
Curl_set_dns_local_ip4(struct Curl_easy * data,const char * local_ip4)896*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
897*6236dae4SAndroid Build Coastguard Worker const char *local_ip4)
898*6236dae4SAndroid Build Coastguard Worker {
899*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_CARES_SET_LOCAL
900*6236dae4SAndroid Build Coastguard Worker struct in_addr a4;
901*6236dae4SAndroid Build Coastguard Worker
902*6236dae4SAndroid Build Coastguard Worker if((!local_ip4) || (local_ip4[0] == 0)) {
903*6236dae4SAndroid Build Coastguard Worker a4.s_addr = 0; /* disabled: do not bind to a specific address */
904*6236dae4SAndroid Build Coastguard Worker }
905*6236dae4SAndroid Build Coastguard Worker else {
906*6236dae4SAndroid Build Coastguard Worker if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
907*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "bad DNS IPv4 address"));
908*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
909*6236dae4SAndroid Build Coastguard Worker }
910*6236dae4SAndroid Build Coastguard Worker }
911*6236dae4SAndroid Build Coastguard Worker
912*6236dae4SAndroid Build Coastguard Worker ares_set_local_ip4((ares_channel)data->state.async.resolver,
913*6236dae4SAndroid Build Coastguard Worker ntohl(a4.s_addr));
914*6236dae4SAndroid Build Coastguard Worker
915*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
916*6236dae4SAndroid Build Coastguard Worker #else /* c-ares version too old! */
917*6236dae4SAndroid Build Coastguard Worker (void)data;
918*6236dae4SAndroid Build Coastguard Worker (void)local_ip4;
919*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
920*6236dae4SAndroid Build Coastguard Worker #endif
921*6236dae4SAndroid Build Coastguard Worker }
922*6236dae4SAndroid Build Coastguard Worker
Curl_set_dns_local_ip6(struct Curl_easy * data,const char * local_ip6)923*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
924*6236dae4SAndroid Build Coastguard Worker const char *local_ip6)
925*6236dae4SAndroid Build Coastguard Worker {
926*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_CARES_SET_LOCAL) && defined(USE_IPV6)
927*6236dae4SAndroid Build Coastguard Worker unsigned char a6[INET6_ADDRSTRLEN];
928*6236dae4SAndroid Build Coastguard Worker
929*6236dae4SAndroid Build Coastguard Worker if((!local_ip6) || (local_ip6[0] == 0)) {
930*6236dae4SAndroid Build Coastguard Worker /* disabled: do not bind to a specific address */
931*6236dae4SAndroid Build Coastguard Worker memset(a6, 0, sizeof(a6));
932*6236dae4SAndroid Build Coastguard Worker }
933*6236dae4SAndroid Build Coastguard Worker else {
934*6236dae4SAndroid Build Coastguard Worker if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) {
935*6236dae4SAndroid Build Coastguard Worker DEBUGF(infof(data, "bad DNS IPv6 address"));
936*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
937*6236dae4SAndroid Build Coastguard Worker }
938*6236dae4SAndroid Build Coastguard Worker }
939*6236dae4SAndroid Build Coastguard Worker
940*6236dae4SAndroid Build Coastguard Worker ares_set_local_ip6((ares_channel)data->state.async.resolver, a6);
941*6236dae4SAndroid Build Coastguard Worker
942*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
943*6236dae4SAndroid Build Coastguard Worker #else /* c-ares version too old! */
944*6236dae4SAndroid Build Coastguard Worker (void)data;
945*6236dae4SAndroid Build Coastguard Worker (void)local_ip6;
946*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
947*6236dae4SAndroid Build Coastguard Worker #endif
948*6236dae4SAndroid Build Coastguard Worker }
949*6236dae4SAndroid Build Coastguard Worker #endif /* CURLRES_ARES */
950