blob: b11fab24684a55ceeff564a27140be0a996efc02 [file] [log] [blame]
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07008 * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07009 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
Alex Deymod15eaac2016-06-28 14:49:26 -070012 * are also available at https://curl.haxx.se/docs/copyright.html.
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070013 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "curl_setup.h"
24
Elliott Hughes82be86d2017-09-20 17:00:17 -070025/***********************************************************************
26 * Only for threaded name resolves builds
27 **********************************************************************/
28#ifdef CURLRES_THREADED
29
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070030#ifdef HAVE_NETINET_IN_H
31#include <netinet/in.h>
32#endif
33#ifdef HAVE_NETDB_H
34#include <netdb.h>
35#endif
36#ifdef HAVE_ARPA_INET_H
37#include <arpa/inet.h>
38#endif
39#ifdef __VMS
40#include <in.h>
41#include <inet.h>
42#endif
43
44#if defined(USE_THREADS_POSIX)
45# ifdef HAVE_PTHREAD_H
46# include <pthread.h>
47# endif
48#elif defined(USE_THREADS_WIN32)
49# ifdef HAVE_PROCESS_H
50# include <process.h>
51# endif
52#endif
53
54#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
55#undef in_addr_t
56#define in_addr_t unsigned long
57#endif
58
59#ifdef HAVE_GETADDRINFO
60# define RESOLVER_ENOMEM EAI_MEMORY
61#else
62# define RESOLVER_ENOMEM ENOMEM
63#endif
64
65#include "urldata.h"
66#include "sendf.h"
67#include "hostip.h"
68#include "hash.h"
69#include "share.h"
70#include "strerror.h"
71#include "url.h"
72#include "multiif.h"
73#include "inet_pton.h"
74#include "inet_ntop.h"
75#include "curl_threads.h"
76#include "connect.h"
Alex Deymod15eaac2016-06-28 14:49:26 -070077/* The last 3 #include files should be in this order */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070078#include "curl_printf.h"
79#include "curl_memory.h"
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070080#include "memdebug.h"
81
Elliott Hughes1ef06ba2018-05-30 15:43:58 -070082struct resdata {
83 struct curltime start;
84};
85
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070086/*
87 * Curl_resolver_global_init()
88 * Called from curl_global_init() to initialize global resolver environment.
89 * Does nothing here.
90 */
91int Curl_resolver_global_init(void)
92{
93 return CURLE_OK;
94}
95
96/*
97 * Curl_resolver_global_cleanup()
98 * Called from curl_global_cleanup() to destroy global resolver environment.
99 * Does nothing here.
100 */
101void Curl_resolver_global_cleanup(void)
102{
103}
104
105/*
106 * Curl_resolver_init()
107 * Called from curl_easy_init() -> Curl_open() to initialize resolver
108 * URL-state specific environment ('resolver' member of the UrlState
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700109 * structure).
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700110 */
111CURLcode Curl_resolver_init(void **resolver)
112{
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700113 *resolver = calloc(1, sizeof(struct resdata));
114 if(!*resolver)
115 return CURLE_OUT_OF_MEMORY;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700116 return CURLE_OK;
117}
118
119/*
120 * Curl_resolver_cleanup()
121 * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
122 * URL-state specific environment ('resolver' member of the UrlState
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700123 * structure).
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700124 */
125void Curl_resolver_cleanup(void *resolver)
126{
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700127 free(resolver);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700128}
129
130/*
131 * Curl_resolver_duphandle()
132 * Called from curl_easy_duphandle() to duplicate resolver URL state-specific
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700133 * environment ('resolver' member of the UrlState structure).
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700134 */
135int Curl_resolver_duphandle(void **to, void *from)
136{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700137 (void)from;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700138 return Curl_resolver_init(to);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700139}
140
141static void destroy_async_data(struct Curl_async *);
142
143/*
144 * Cancel all possibly still on-going resolves for this connection.
145 */
146void Curl_resolver_cancel(struct connectdata *conn)
147{
148 destroy_async_data(&conn->async);
149}
150
151/* This function is used to init a threaded resolve */
152static bool init_resolve_thread(struct connectdata *conn,
153 const char *hostname, int port,
154 const struct addrinfo *hints);
155
156
157/* Data for synchronization between resolver thread and its parent */
158struct thread_sync_data {
159 curl_mutex_t * mtx;
160 int done;
161
Elliott Hughescee03382017-06-23 12:17:18 -0700162 char *hostname; /* hostname to resolve, Curl_async.hostname
163 duplicate */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700164 int port;
165 int sock_error;
166 Curl_addrinfo *res;
167#ifdef HAVE_GETADDRINFO
168 struct addrinfo hints;
169#endif
170 struct thread_data *td; /* for thread-self cleanup */
171};
172
173struct thread_data {
174 curl_thread_t thread_hnd;
175 unsigned int poll_interval;
Elliott Hughescee03382017-06-23 12:17:18 -0700176 time_t interval_end;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700177 struct thread_sync_data tsd;
178};
179
180static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn)
181{
182 return &(((struct thread_data *)conn->async.os_specific)->tsd);
183}
184
185#define CONN_THREAD_SYNC_DATA(conn) &(((conn)->async.os_specific)->tsd);
186
187/* Destroy resolver thread synchronization data */
188static
189void destroy_thread_sync_data(struct thread_sync_data * tsd)
190{
191 if(tsd->mtx) {
192 Curl_mutex_destroy(tsd->mtx);
193 free(tsd->mtx);
194 }
195
196 free(tsd->hostname);
197
198 if(tsd->res)
199 Curl_freeaddrinfo(tsd->res);
200
201 memset(tsd, 0, sizeof(*tsd));
202}
203
204/* Initialize resolver thread synchronization data */
205static
206int init_thread_sync_data(struct thread_data * td,
Elliott Hughescee03382017-06-23 12:17:18 -0700207 const char *hostname,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700208 int port,
209 const struct addrinfo *hints)
210{
211 struct thread_sync_data *tsd = &td->tsd;
212
213 memset(tsd, 0, sizeof(*tsd));
214
215 tsd->td = td;
216 tsd->port = port;
Alex Deymo486467e2017-12-19 19:04:07 +0100217 /* Treat the request as done until the thread actually starts so any early
218 * cleanup gets done properly.
219 */
220 tsd->done = 1;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700221#ifdef HAVE_GETADDRINFO
222 DEBUGASSERT(hints);
223 tsd->hints = *hints;
224#else
225 (void) hints;
226#endif
227
228 tsd->mtx = malloc(sizeof(curl_mutex_t));
229 if(tsd->mtx == NULL)
230 goto err_exit;
231
232 Curl_mutex_init(tsd->mtx);
233
234 tsd->sock_error = CURL_ASYNC_SUCCESS;
235
236 /* Copying hostname string because original can be destroyed by parent
237 * thread during gethostbyname execution.
238 */
239 tsd->hostname = strdup(hostname);
240 if(!tsd->hostname)
241 goto err_exit;
242
243 return 1;
244
245 err_exit:
246 /* Memory allocation failed */
247 destroy_thread_sync_data(tsd);
248 return 0;
249}
250
251static int getaddrinfo_complete(struct connectdata *conn)
252{
253 struct thread_sync_data *tsd = conn_thread_sync_data(conn);
254 int rc;
255
256 rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res);
257 /* The tsd->res structure has been copied to async.dns and perhaps the DNS
258 cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it.
259 */
260 tsd->res = NULL;
261
262 return rc;
263}
264
265
266#ifdef HAVE_GETADDRINFO
267
268/*
269 * getaddrinfo_thread() resolves a name and then exits.
270 *
271 * For builds without ARES, but with ENABLE_IPV6, create a resolver thread
272 * and wait on it.
273 */
Elliott Hughes82be86d2017-09-20 17:00:17 -0700274static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700275{
276 struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
277 struct thread_data *td = tsd->td;
278 char service[12];
279 int rc;
280
281 snprintf(service, sizeof(service), "%d", tsd->port);
282
283 rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
284
285 if(rc != 0) {
286 tsd->sock_error = SOCKERRNO?SOCKERRNO:rc;
287 if(tsd->sock_error == 0)
288 tsd->sock_error = RESOLVER_ENOMEM;
289 }
Alex Deymoe3149cc2016-10-05 11:18:42 -0700290 else {
291 Curl_addrinfo_set_port(tsd->res, tsd->port);
292 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700293
294 Curl_mutex_acquire(tsd->mtx);
295 if(tsd->done) {
296 /* too late, gotta clean up the mess */
297 Curl_mutex_release(tsd->mtx);
298 destroy_thread_sync_data(tsd);
299 free(td);
300 }
301 else {
302 tsd->done = 1;
303 Curl_mutex_release(tsd->mtx);
304 }
305
306 return 0;
307}
308
309#else /* HAVE_GETADDRINFO */
310
311/*
312 * gethostbyname_thread() resolves a name and then exits.
313 */
Elliott Hughes82be86d2017-09-20 17:00:17 -0700314static unsigned int CURL_STDCALL gethostbyname_thread(void *arg)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700315{
316 struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
317 struct thread_data *td = tsd->td;
318
319 tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port);
320
321 if(!tsd->res) {
322 tsd->sock_error = SOCKERRNO;
323 if(tsd->sock_error == 0)
324 tsd->sock_error = RESOLVER_ENOMEM;
325 }
326
327 Curl_mutex_acquire(tsd->mtx);
328 if(tsd->done) {
329 /* too late, gotta clean up the mess */
330 Curl_mutex_release(tsd->mtx);
331 destroy_thread_sync_data(tsd);
332 free(td);
333 }
334 else {
335 tsd->done = 1;
336 Curl_mutex_release(tsd->mtx);
337 }
338
339 return 0;
340}
341
342#endif /* HAVE_GETADDRINFO */
343
344/*
345 * destroy_async_data() cleans up async resolver data and thread handle.
346 */
Elliott Hughes82be86d2017-09-20 17:00:17 -0700347static void destroy_async_data(struct Curl_async *async)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700348{
349 if(async->os_specific) {
350 struct thread_data *td = (struct thread_data*) async->os_specific;
351 int done;
352
353 /*
354 * if the thread is still blocking in the resolve syscall, detach it and
355 * let the thread do the cleanup...
356 */
357 Curl_mutex_acquire(td->tsd.mtx);
358 done = td->tsd.done;
359 td->tsd.done = 1;
360 Curl_mutex_release(td->tsd.mtx);
361
362 if(!done) {
363 Curl_thread_destroy(td->thread_hnd);
364 }
365 else {
366 if(td->thread_hnd != curl_thread_t_null)
367 Curl_thread_join(&td->thread_hnd);
368
369 destroy_thread_sync_data(&td->tsd);
370
371 free(async->os_specific);
372 }
373 }
374 async->os_specific = NULL;
375
376 free(async->hostname);
377 async->hostname = NULL;
378}
379
380/*
381 * init_resolve_thread() starts a new thread that performs the actual
382 * resolve. This function returns before the resolve is done.
383 *
384 * Returns FALSE in case of failure, otherwise TRUE.
385 */
Elliott Hughes82be86d2017-09-20 17:00:17 -0700386static bool init_resolve_thread(struct connectdata *conn,
387 const char *hostname, int port,
388 const struct addrinfo *hints)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700389{
390 struct thread_data *td = calloc(1, sizeof(struct thread_data));
Alex Deymo486467e2017-12-19 19:04:07 +0100391 int err = ENOMEM;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700392
Elliott Hughescee03382017-06-23 12:17:18 -0700393 conn->async.os_specific = (void *)td;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700394 if(!td)
Alex Deymo486467e2017-12-19 19:04:07 +0100395 goto errno_exit;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700396
397 conn->async.port = port;
398 conn->async.done = FALSE;
399 conn->async.status = 0;
400 conn->async.dns = NULL;
401 td->thread_hnd = curl_thread_t_null;
402
Alex Deymo486467e2017-12-19 19:04:07 +0100403 if(!init_thread_sync_data(td, hostname, port, hints)) {
404 conn->async.os_specific = NULL;
405 free(td);
406 goto errno_exit;
407 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700408
409 free(conn->async.hostname);
410 conn->async.hostname = strdup(hostname);
411 if(!conn->async.hostname)
412 goto err_exit;
413
Alex Deymo486467e2017-12-19 19:04:07 +0100414 /* The thread will set this to 1 when complete. */
415 td->tsd.done = 0;
416
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700417#ifdef HAVE_GETADDRINFO
418 td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
419#else
420 td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd);
421#endif
422
423 if(!td->thread_hnd) {
Alex Deymo486467e2017-12-19 19:04:07 +0100424 /* The thread never started, so mark it as done here for proper cleanup. */
425 td->tsd.done = 1;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700426 err = errno;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700427 goto err_exit;
428 }
429
430 return TRUE;
431
432 err_exit:
433 destroy_async_data(&conn->async);
434
Alex Deymo486467e2017-12-19 19:04:07 +0100435 errno_exit:
Elliott Hughes82be86d2017-09-20 17:00:17 -0700436 errno = err;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700437 return FALSE;
438}
439
440/*
441 * resolver_error() calls failf() with the appropriate message after a resolve
442 * error
443 */
444
445static CURLcode resolver_error(struct connectdata *conn)
446{
447 const char *host_or_proxy;
448 CURLcode result;
449
450 if(conn->bits.httpproxy) {
451 host_or_proxy = "proxy";
452 result = CURLE_COULDNT_RESOLVE_PROXY;
453 }
454 else {
455 host_or_proxy = "host";
456 result = CURLE_COULDNT_RESOLVE_HOST;
457 }
458
459 failf(conn->data, "Could not resolve %s: %s", host_or_proxy,
460 conn->async.hostname);
461
462 return result;
463}
464
465/*
466 * Curl_resolver_wait_resolv()
467 *
468 * waits for a resolve to finish. This function should be avoided since using
469 * this risk getting the multi interface to "hang".
470 *
471 * If 'entry' is non-NULL, make it point to the resolved dns entry
472 *
473 * This is the version for resolves-in-a-thread.
474 */
475CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
476 struct Curl_dns_entry **entry)
477{
478 struct thread_data *td = (struct thread_data*) conn->async.os_specific;
479 CURLcode result = CURLE_OK;
480
481 DEBUGASSERT(conn && td);
482
483 /* wait for the thread to resolve the name */
484 if(Curl_thread_join(&td->thread_hnd))
485 result = getaddrinfo_complete(conn);
486 else
487 DEBUGASSERT(0);
488
489 conn->async.done = TRUE;
490
491 if(entry)
492 *entry = conn->async.dns;
493
494 if(!conn->async.dns)
495 /* a name was not resolved, report error */
496 result = resolver_error(conn);
497
498 destroy_async_data(&conn->async);
499
500 if(!conn->async.dns)
501 connclose(conn, "asynch resolve failed");
502
503 return result;
504}
505
506/*
507 * Curl_resolver_is_resolved() is called repeatedly to check if a previous
508 * name resolve request has completed. It should also make sure to time-out if
509 * the operation seems to take too long.
510 */
511CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
512 struct Curl_dns_entry **entry)
513{
Alex Deymoe3149cc2016-10-05 11:18:42 -0700514 struct Curl_easy *data = conn->data;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700515 struct thread_data *td = (struct thread_data*) conn->async.os_specific;
516 int done = 0;
517
518 *entry = NULL;
519
520 if(!td) {
521 DEBUGASSERT(td);
522 return CURLE_COULDNT_RESOLVE_HOST;
523 }
524
525 Curl_mutex_acquire(td->tsd.mtx);
526 done = td->tsd.done;
527 Curl_mutex_release(td->tsd.mtx);
528
529 if(done) {
530 getaddrinfo_complete(conn);
531
532 if(!conn->async.dns) {
533 CURLcode result = resolver_error(conn);
534 destroy_async_data(&conn->async);
535 return result;
536 }
537 destroy_async_data(&conn->async);
538 *entry = conn->async.dns;
539 }
540 else {
541 /* poll for name lookup done with exponential backoff up to 250ms */
Alex Deymo486467e2017-12-19 19:04:07 +0100542 timediff_t elapsed = Curl_timediff(Curl_now(),
543 data->progress.t_startsingle);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700544 if(elapsed < 0)
545 elapsed = 0;
546
547 if(td->poll_interval == 0)
548 /* Start at 1ms poll interval */
549 td->poll_interval = 1;
550 else if(elapsed >= td->interval_end)
551 /* Back-off exponentially if last interval expired */
552 td->poll_interval *= 2;
553
554 if(td->poll_interval > 250)
555 td->poll_interval = 250;
556
557 td->interval_end = elapsed + td->poll_interval;
Elliott Hughes82be86d2017-09-20 17:00:17 -0700558 Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700559 }
560
561 return CURLE_OK;
562}
563
564int Curl_resolver_getsock(struct connectdata *conn,
565 curl_socket_t *socks,
566 int numsocks)
567{
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700568 time_t milli;
569 timediff_t ms;
570 struct Curl_easy *data = conn->data;
571 struct resdata *reslv = (struct resdata *)data->state.resolver;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700572 (void)socks;
573 (void)numsocks;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700574 ms = Curl_timediff(Curl_now(), reslv->start);
575 if(ms < 10)
576 milli = ms/3;
577 else if(ms <= 50)
578 milli = 10;
579 else if(ms <= 250)
580 milli = 50;
581 else
582 milli = 200;
583 Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700584 return 0;
585}
586
587#ifndef HAVE_GETADDRINFO
588/*
589 * Curl_getaddrinfo() - for platforms without getaddrinfo
590 */
591Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
592 const char *hostname,
593 int port,
594 int *waitp)
595{
596 struct in_addr in;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700597 struct Curl_easy *data = conn->data;
598 struct resdata *reslv = (struct resdata *)data->state.resolver;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700599
600 *waitp = 0; /* default to synchronous response */
601
602 if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
603 /* This is a dotted IP address 123.123.123.123-style */
604 return Curl_ip2addr(AF_INET, &in, hostname, port);
605
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700606 reslv->start = Curl_now();
607
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700608 /* fire up a new resolver thread! */
609 if(init_resolve_thread(conn, hostname, port, NULL)) {
610 *waitp = 1; /* expect asynchronous response */
611 return NULL;
612 }
613
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700614 failf(conn->data, "getaddrinfo() thread failed\n");
615
616 return NULL;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700617}
618
619#else /* !HAVE_GETADDRINFO */
620
621/*
622 * Curl_resolver_getaddrinfo() - for getaddrinfo
623 */
624Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
625 const char *hostname,
626 int port,
627 int *waitp)
628{
629 struct addrinfo hints;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700630 char sbuf[12];
631 int pf = PF_INET;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700632 struct Curl_easy *data = conn->data;
633 struct resdata *reslv = (struct resdata *)data->state.resolver;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700634
635 *waitp = 0; /* default to synchronous response */
636
Alex Deymoe3149cc2016-10-05 11:18:42 -0700637#ifndef USE_RESOLVE_ON_IPS
Elliott Hughes82be86d2017-09-20 17:00:17 -0700638 {
639 struct in_addr in;
640 /* First check if this is an IPv4 address string */
641 if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
642 /* This is a dotted IP address 123.123.123.123-style */
643 return Curl_ip2addr(AF_INET, &in, hostname, port);
644 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700645#ifdef CURLRES_IPV6
Elliott Hughes82be86d2017-09-20 17:00:17 -0700646 {
647 struct in6_addr in6;
648 /* check if this is an IPv6 address string */
649 if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0)
650 /* This is an IPv6 address literal */
651 return Curl_ip2addr(AF_INET6, &in6, hostname, port);
652 }
Alex Deymoe3149cc2016-10-05 11:18:42 -0700653#endif /* CURLRES_IPV6 */
654#endif /* !USE_RESOLVE_ON_IPS */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700655
Alex Deymoe3149cc2016-10-05 11:18:42 -0700656#ifdef CURLRES_IPV6
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700657 /*
658 * Check if a limited name resolve has been requested.
659 */
660 switch(conn->ip_version) {
661 case CURL_IPRESOLVE_V4:
662 pf = PF_INET;
663 break;
664 case CURL_IPRESOLVE_V6:
665 pf = PF_INET6;
666 break;
667 default:
668 pf = PF_UNSPEC;
669 break;
670 }
671
672 if((pf != PF_INET) && !Curl_ipv6works())
673 /* The stack seems to be a non-IPv6 one */
674 pf = PF_INET;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700675#endif /* CURLRES_IPV6 */
676
677 memset(&hints, 0, sizeof(hints));
678 hints.ai_family = pf;
679 hints.ai_socktype = conn->socktype;
680
681 snprintf(sbuf, sizeof(sbuf), "%d", port);
682
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700683 reslv->start = Curl_now();
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700684 /* fire up a new resolver thread! */
685 if(init_resolve_thread(conn, hostname, port, &hints)) {
686 *waitp = 1; /* expect asynchronous response */
687 return NULL;
688 }
689
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700690 failf(data, "getaddrinfo() thread failed to start\n");
691 return NULL;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700692
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700693}
694
695#endif /* !HAVE_GETADDRINFO */
696
Alex Deymoe3149cc2016-10-05 11:18:42 -0700697CURLcode Curl_set_dns_servers(struct Curl_easy *data,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700698 char *servers)
699{
700 (void)data;
701 (void)servers;
702 return CURLE_NOT_BUILT_IN;
703
704}
705
Alex Deymoe3149cc2016-10-05 11:18:42 -0700706CURLcode Curl_set_dns_interface(struct Curl_easy *data,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700707 const char *interf)
708{
709 (void)data;
710 (void)interf;
711 return CURLE_NOT_BUILT_IN;
712}
713
Alex Deymoe3149cc2016-10-05 11:18:42 -0700714CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700715 const char *local_ip4)
716{
717 (void)data;
718 (void)local_ip4;
719 return CURLE_NOT_BUILT_IN;
720}
721
Alex Deymoe3149cc2016-10-05 11:18:42 -0700722CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700723 const char *local_ip6)
724{
725 (void)data;
726 (void)local_ip6;
727 return CURLE_NOT_BUILT_IN;
728}
729
730#endif /* CURLRES_THREADED */