1e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/*************************************************************************** 2e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * _ _ ____ _ 3e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Project ___| | | | _ \| | 4e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * / __| | | | |_) | | 5e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * | (__| |_| | _ <| |___ 6e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * \___|\___/|_| \_\_____| 7e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 8d15eaac64ca1a7244824d660ea84e8815a23d058Alex Deymo * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. 9e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 10e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is licensed as described in the file COPYING, which 11e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * you should have received as part of this distribution. The terms 12d15eaac64ca1a7244824d660ea84e8815a23d058Alex Deymo * are also available at https://curl.haxx.se/docs/copyright.html. 13e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 14e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * copies of the Software, and permit persons to whom the Software is 16e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * furnished to do so, under the terms of the COPYING file. 17e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 18e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * KIND, either express or implied. 20e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 21e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ***************************************************************************/ 22e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 23e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "curl_setup.h" 24e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 25e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef HAVE_LIMITS_H 26e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <limits.h> 27e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 28e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef HAVE_NETINET_IN_H 29e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <netinet/in.h> 30e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 31e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef HAVE_NETDB_H 32e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <netdb.h> 33e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 34e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef HAVE_ARPA_INET_H 35e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <arpa/inet.h> 36e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 37e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef __VMS 38e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <in.h> 39e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <inet.h> 40e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 41e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 42e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef HAVE_PROCESS_H 43e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <process.h> 44e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 45e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 46e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) 47e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#undef in_addr_t 48e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#define in_addr_t unsigned long 49e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 50e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 51e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/*********************************************************************** 52e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Only for ares-enabled builds 53e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * And only for functions that fulfill the asynch resolver backend API 54e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * as defined in asyn.h, nothing else belongs in this file! 55e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET **********************************************************************/ 56e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 57e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef CURLRES_ARES 58e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 59e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "urldata.h" 60e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "sendf.h" 61e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "hostip.h" 62e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "hash.h" 63e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "share.h" 64e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "strerror.h" 65e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "url.h" 66e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "multiif.h" 67e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "inet_pton.h" 68e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "connect.h" 69e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "select.h" 70e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "progress.h" 71e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 72e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ 73e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) 74e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET# define CARES_STATICLIB 75e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET# endif 76e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET# include <ares.h> 77e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET# include <ares_version.h> /* really old c-ares didn't include this by 78e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET itself */ 79e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 80e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if ARES_VERSION >= 0x010500 81e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* c-ares 1.5.0 or later, the callback proto is modified */ 82e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#define HAVE_CARES_CALLBACK_TIMEOUTS 1 83e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 84e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 85d15eaac64ca1a7244824d660ea84e8815a23d058Alex Deymo/* The last 3 #include files should be in this order */ 86d15eaac64ca1a7244824d660ea84e8815a23d058Alex Deymo#include "curl_printf.h" 87e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "curl_memory.h" 88e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "memdebug.h" 89e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 90e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstruct ResolverResults { 91e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int num_pending; /* number of ares_gethostbyname() requests */ 92e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */ 93e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int last_status; 94e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET}; 95e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 96e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 97e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Curl_resolver_global_init() - the generic low-level asynchronous name 98e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * resolve API. Called from curl_global_init() to initialize global resolver 99e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * environment. Initializes ares library. 100e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 101e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETint Curl_resolver_global_init(void) 102e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 103e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef CARES_HAVE_ARES_LIBRARY_INIT 104e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(ares_library_init(ARES_LIB_INIT_ALL)) { 105e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_FAILED_INIT; 106e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 107e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 108e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_OK; 109e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 110e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 111e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 112e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Curl_resolver_global_cleanup() 113e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 114e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Called from curl_global_cleanup() to destroy global resolver environment. 115e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Deinitializes ares library. 116e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 117e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETvoid Curl_resolver_global_cleanup(void) 118e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 119e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP 120e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_library_cleanup(); 121e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 122e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 123e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 124e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 125e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Curl_resolver_init() 126e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 127e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Called from curl_easy_init() -> Curl_open() to initialize resolver 128e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * URL-state specific environment ('resolver' member of the UrlState 129e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * structure). Fills the passed pointer by the initialized ares_channel. 130e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 131e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETCURLcode Curl_resolver_init(void **resolver) 132e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 133e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int status = ares_init((ares_channel*)resolver); 134e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(status != ARES_SUCCESS) { 135e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(status == ARES_ENOMEM) 136e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_OUT_OF_MEMORY; 137e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 138e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_FAILED_INIT; 139e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 140e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_OK; 141e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* make sure that all other returns from this function should destroy the 142e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares channel before returning error! */ 143e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 144e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 145e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 146e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Curl_resolver_cleanup() 147e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 148e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver 149e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * URL-state specific environment ('resolver' member of the UrlState 150e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * structure). Destroys the ares channel. 151e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 152e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETvoid Curl_resolver_cleanup(void *resolver) 153e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 154e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_destroy((ares_channel)resolver); 155e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 156e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 157e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 158e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Curl_resolver_duphandle() 159e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 160e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Called from curl_easy_duphandle() to duplicate resolver URL-state specific 161e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * environment ('resolver' member of the UrlState structure). Duplicates the 162e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 'from' ares channel and passes the resulting channel to the 'to' pointer. 163e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 164e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETint Curl_resolver_duphandle(void **to, void *from) 165e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 166e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Clone the ares channel for the new handle */ 167e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(ARES_SUCCESS != ares_dup((ares_channel*)to, (ares_channel)from)) 168e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_FAILED_INIT; 169e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_OK; 170e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 171e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 172e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic void destroy_async_data (struct Curl_async *async); 173e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 174e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 175e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Cancel all possibly still on-going resolves for this connection. 176e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 177e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETvoid Curl_resolver_cancel(struct connectdata *conn) 178e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 179e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(conn->data && conn->data->state.resolver) 180e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_cancel((ares_channel)conn->data->state.resolver); 181e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET destroy_async_data(&conn->async); 182e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 183e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 184e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 185e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * destroy_async_data() cleans up async resolver data. 186e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 187e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic void destroy_async_data (struct Curl_async *async) 188e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 189e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET free(async->hostname); 190e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 191e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(async->os_specific) { 192e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct ResolverResults *res = (struct ResolverResults *)async->os_specific; 193e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(res) { 194e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(res->temp_ai) { 195e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET Curl_freeaddrinfo(res->temp_ai); 196e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res->temp_ai = NULL; 197e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 198e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET free(res); 199e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 200e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET async->os_specific = NULL; 201e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 202e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 203e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET async->hostname = NULL; 204e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 205e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 206e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 207e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Curl_resolver_getsock() is called when someone from the outside world 208e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * (using curl_multi_fdset()) wants to get our fd_set setup and we're talking 209e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * with ares. The caller must make sure that this function is only called when 210e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * we have a working ares channel. 211e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 212e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Returns: sockets-in-use-bitmap 213e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 214e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 215e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETint Curl_resolver_getsock(struct connectdata *conn, 216e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_socket_t *socks, 217e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int numsocks) 218e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 219e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 220e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct timeval maxtime; 221e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct timeval timebuf; 222e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct timeval *timeout; 223e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET long milli; 224e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int max = ares_getsock((ares_channel)conn->data->state.resolver, 225e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (ares_socket_t *)socks, numsocks); 226e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 227e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET maxtime.tv_sec = CURL_TIMEOUT_RESOLVE; 228e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET maxtime.tv_usec = 0; 229e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 230e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime, 231e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET &timebuf); 232e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000); 233e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(milli == 0) 234e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET milli += 10; 235e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET Curl_expire_latest(conn->data, milli); 236e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 237e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return max; 238e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 239e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 240e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 241e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * waitperform() 242e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 243e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 1) Ask ares what sockets it currently plays with, then 244e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 2) wait for the timeout period to check for action on ares' sockets. 245e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 3) tell ares to act on all the sockets marked as "with action" 246e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 247e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * return number of sockets it worked on 248e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 249e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 250e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic int waitperform(struct connectdata *conn, int timeout_ms) 251e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 252e3149cc1cf501b46caba8d47652ac90b95c78eacAlex Deymo struct Curl_easy *data = conn->data; 253e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int nfds; 254e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int bitmask; 255e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_socket_t socks[ARES_GETSOCK_MAXNUM]; 256e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct pollfd pfd[ARES_GETSOCK_MAXNUM]; 257e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int i; 258e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int num = 0; 259e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 260e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET bitmask = ares_getsock((ares_channel)data->state.resolver, socks, 261e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ARES_GETSOCK_MAXNUM); 262e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 263e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET for(i=0; i < ARES_GETSOCK_MAXNUM; i++) { 264e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET pfd[i].events = 0; 265e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET pfd[i].revents = 0; 266e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(ARES_GETSOCK_READABLE(bitmask, i)) { 267e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET pfd[i].fd = socks[i]; 268e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET pfd[i].events |= POLLRDNORM|POLLIN; 269e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 270e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(ARES_GETSOCK_WRITABLE(bitmask, i)) { 271e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET pfd[i].fd = socks[i]; 272e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET pfd[i].events |= POLLWRNORM|POLLOUT; 273e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 274e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(pfd[i].events != 0) 275e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET num++; 276e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 277e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 278e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 279e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 280e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(num) 281e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET nfds = Curl_poll(pfd, num, timeout_ms); 282e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 283e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET nfds = 0; 284e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 285e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!nfds) 286e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Call ares_process() unconditonally here, even if we simply timed out 287e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET above, as otherwise the ares name resolve won't timeout! */ 288e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD, 289e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ARES_SOCKET_BAD); 290e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else { 291e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* move through the descriptors and ask for processing on them */ 292e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET for(i=0; i < num; i++) 293e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_process_fd((ares_channel)data->state.resolver, 294e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET pfd[i].revents & (POLLRDNORM|POLLIN)? 295e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET pfd[i].fd:ARES_SOCKET_BAD, 296e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET pfd[i].revents & (POLLWRNORM|POLLOUT)? 297e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET pfd[i].fd:ARES_SOCKET_BAD); 298e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 299e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return nfds; 300e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 301e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 302e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 303e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Curl_resolver_is_resolved() is called repeatedly to check if a previous 304e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * name resolve request has completed. It should also make sure to time-out if 305e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * the operation seems to take too long. 306e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 307e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Returns normal CURLcode errors. 308e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 309e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETCURLcode Curl_resolver_is_resolved(struct connectdata *conn, 310e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct Curl_dns_entry **dns) 311e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 312e3149cc1cf501b46caba8d47652ac90b95c78eacAlex Deymo struct Curl_easy *data = conn->data; 313e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct ResolverResults *res = (struct ResolverResults *) 314e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET conn->async.os_specific; 315e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET CURLcode result = CURLE_OK; 316e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 317e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *dns = NULL; 318e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 319e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET waitperform(conn, 0); 320e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 321e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(res && !res->num_pending) { 322e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai); 323e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* temp_ai ownership is moved to the connection, so we need not free-up 324e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET them */ 325e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res->temp_ai = NULL; 326e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!conn->async.dns) { 327e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET failf(data, "Could not resolve: %s (%s)", 328e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET conn->async.hostname, ares_strerror(conn->async.status)); 329e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: 330e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET CURLE_COULDNT_RESOLVE_HOST; 331e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 332e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 333e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *dns = conn->async.dns; 334e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 335e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET destroy_async_data(&conn->async); 336e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 337e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 338e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return result; 339e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 340e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 341e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 342e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Curl_resolver_wait_resolv() 343e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 344e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * waits for a resolve to finish. This function should be avoided since using 345e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * this risk getting the multi interface to "hang". 346e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 347e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * If 'entry' is non-NULL, make it point to the resolved dns entry 348e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 349e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and 350e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * CURLE_OPERATION_TIMEDOUT if a time-out occurred. 351e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 352e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETCURLcode Curl_resolver_wait_resolv(struct connectdata *conn, 353e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct Curl_dns_entry **entry) 354e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 355e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET CURLcode result = CURLE_OK; 356e3149cc1cf501b46caba8d47652ac90b95c78eacAlex Deymo struct Curl_easy *data = conn->data; 357e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET long timeout; 358e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct timeval now = Curl_tvnow(); 359e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct Curl_dns_entry *temp_entry; 360e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 361e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout = Curl_timeleft(data, &now, TRUE); 362e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!timeout) 363e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */ 364e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 365e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Wait for the name resolve query to complete. */ 366e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET for(;;) { 367e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct timeval *tvp, tv, store; 368e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET long timediff; 369e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int itimeout; 370e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int timeout_ms; 371e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 372e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout; 373e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 374e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET store.tv_sec = itimeout/1000; 375e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET store.tv_usec = (itimeout%1000)*1000; 376e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 377e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv); 378e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 379e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* use the timeout period ares returned to us above if less than one 380e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET second is left, otherwise just use 1000ms to make sure the progress 381e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET callback gets called frequent enough */ 382e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!tvp->tv_sec) 383e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout_ms = (int)(tvp->tv_usec/1000); 384e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 385e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout_ms = 1000; 386e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 387e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET waitperform(conn, timeout_ms); 388e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET Curl_resolver_is_resolved(conn, &temp_entry); 389e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 390e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(conn->async.done) 391e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 392e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 393e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(Curl_pgrsUpdate(conn)) { 394e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET result = CURLE_ABORTED_BY_CALLBACK; 395e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout = -1; /* trigger the cancel below */ 396e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 397e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else { 398e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct timeval now2 = Curl_tvnow(); 399e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timediff = Curl_tvdiff(now2, now); /* spent time */ 400e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout -= timediff?timediff:1; /* always deduct at least 1 */ 401e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET now = now2; /* for next loop */ 402e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 403e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 404e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(timeout < 0) { 405e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* our timeout, so we cancel the ares operation */ 406e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_cancel((ares_channel)data->state.resolver); 407e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 408e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 409e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 410e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 411e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Operation complete, if the lookup was successful we now have the entry 412e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET in the cache. */ 413e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(entry) 414e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *entry = conn->async.dns; 415e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 416e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(result) 417e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* close the connection, since we can't return failure here without 418e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET cleaning up this connection properly. 419e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET TODO: remove this action from here, it is not a name resolver decision. 420e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 421e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET connclose(conn, "c-ares resolve failed"); 422e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 423e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return result; 424e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 425e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 426e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* Connects results to the list */ 427e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic void compound_results(struct ResolverResults *res, 428e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET Curl_addrinfo *ai) 429e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 430e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET Curl_addrinfo *ai_tail; 431e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!ai) 432e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return; 433e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ai_tail = ai; 434e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 435e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET while(ai_tail->ai_next) 436e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ai_tail = ai_tail->ai_next; 437e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 438e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Add the new results to the list of old results. */ 439e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ai_tail->ai_next = res->temp_ai; 440e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res->temp_ai = ai; 441e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 442e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 443e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 444e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * ares_query_completed_cb() is the callback that ares will call when 445e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(), 446e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * when using ares, is completed either successfully or with failure. 447e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 448e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic void query_completed_cb(void *arg, /* (struct connectdata *) */ 449e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int status, 450e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef HAVE_CARES_CALLBACK_TIMEOUTS 451e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int timeouts, 452e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 453e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct hostent *hostent) 454e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 455e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct connectdata *conn = (struct connectdata *)arg; 456e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct ResolverResults *res; 457e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 458e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef HAVE_CARES_CALLBACK_TIMEOUTS 459e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)timeouts; /* ignored */ 460e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 461e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 462e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(ARES_EDESTRUCTION == status) 463e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* when this ares handle is getting destroyed, the 'arg' pointer may not 464e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET be valid so only defer it when we know the 'status' says its fine! */ 465e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return; 466e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 467e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res = (struct ResolverResults *)conn->async.os_specific; 468e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res->num_pending--; 469e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 470e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(CURL_ASYNC_SUCCESS == status) { 471e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port); 472e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(ai) { 473e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET compound_results(res, ai); 474e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 475e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 476e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* A successful result overwrites any previous error */ 477e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(res->last_status != ARES_SUCCESS) 478e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res->last_status = status; 479e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 480e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 481e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 482e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Curl_resolver_getaddrinfo() - when using ares 483e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 484e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Returns name information about the given hostname and port number. If 485e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * successful, the 'hostent' is returned and the forth argument will point to 486e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * memory we need to free after use. That memory *MUST* be freed with 487e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Curl_freeaddrinfo(), nothing else. 488e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 489e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETCurl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, 490e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET const char *hostname, 491e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int port, 492e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int *waitp) 493e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 494e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET char *bufp; 495e3149cc1cf501b46caba8d47652ac90b95c78eacAlex Deymo struct Curl_easy *data = conn->data; 496e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct in_addr in; 497e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int family = PF_INET; 498e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ 499e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct in6_addr in6; 500e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif /* CURLRES_IPV6 */ 501e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 502e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *waitp = 0; /* default to synchronous response */ 503e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 504e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* First check if this is an IPv4 address string */ 505e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(Curl_inet_pton(AF_INET, hostname, &in) > 0) { 506e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* This is a dotted IP address 123.123.123.123-style */ 507e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return Curl_ip2addr(AF_INET, &in, hostname, port); 508e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 509e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 510e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ 511e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Otherwise, check if this is an IPv6 address string */ 512e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0) 513e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* This must be an IPv6 address literal. */ 514e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return Curl_ip2addr(AF_INET6, &in6, hostname, port); 515e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 516e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET switch(conn->ip_version) { 517e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET default: 518e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if ARES_VERSION >= 0x010601 519e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older 520e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET c-ares versions this just falls through and defaults 521e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET to PF_INET */ 522e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 523e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 524e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURL_IPRESOLVE_V4: 525e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET family = PF_INET; 526e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 527e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURL_IPRESOLVE_V6: 528e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET family = PF_INET6; 529e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 530e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 531e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif /* CURLRES_IPV6 */ 532e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 533e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET bufp = strdup(hostname); 534e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(bufp) { 535e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct ResolverResults *res = NULL; 536e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET free(conn->async.hostname); 537e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET conn->async.hostname = bufp; 538e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET conn->async.port = port; 539e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET conn->async.done = FALSE; /* not done */ 540e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET conn->async.status = 0; /* clear */ 541e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET conn->async.dns = NULL; /* clear */ 542e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res = calloc(sizeof(struct ResolverResults), 1); 543e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!res) { 544e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET free(conn->async.hostname); 545e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET conn->async.hostname = NULL; 546e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return NULL; 547e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 548e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET conn->async.os_specific = res; 549e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 550e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* initial status - failed */ 551e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res->last_status = ARES_ENOTFOUND; 552e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ 553e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(family == PF_UNSPEC) { 554e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(Curl_ipv6works()) { 555e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res->num_pending = 2; 556e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 557e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* areschannel is already setup in the Curl_open() function */ 558e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_gethostbyname((ares_channel)data->state.resolver, hostname, 559e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET PF_INET, query_completed_cb, conn); 560e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_gethostbyname((ares_channel)data->state.resolver, hostname, 561e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET PF_INET6, query_completed_cb, conn); 562e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 563e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else { 564e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res->num_pending = 1; 565e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 566e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* areschannel is already setup in the Curl_open() function */ 567e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_gethostbyname((ares_channel)data->state.resolver, hostname, 568e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET PF_INET, query_completed_cb, conn); 569e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 570e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 571e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 572e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif /* CURLRES_IPV6 */ 573e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET { 574e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res->num_pending = 1; 575e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 576e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* areschannel is already setup in the Curl_open() function */ 577e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_gethostbyname((ares_channel)data->state.resolver, hostname, family, 578e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET query_completed_cb, conn); 579e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 580e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 581e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *waitp = 1; /* expect asynchronous response */ 582e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 583e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return NULL; /* no struct yet */ 584e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 585e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 586e3149cc1cf501b46caba8d47652ac90b95c78eacAlex DeymoCURLcode Curl_set_dns_servers(struct Curl_easy *data, 587e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET char *servers) 588e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 589e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET CURLcode result = CURLE_NOT_BUILT_IN; 590e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int ares_result; 591e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 592e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* If server is NULL or empty, this would purge all DNS servers 593e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * from ares library, which will cause any and all queries to fail. 594e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * So, just return OK if none are configured and don't actually make 595e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * any changes to c-ares. This lets c-ares use it's defaults, which 596e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * it gets from the OS (for instance from /etc/resolv.conf on Linux). 597e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 598e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!(servers && servers[0])) 599e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_OK; 600e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 601e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if (ARES_VERSION >= 0x010704) 602e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_result = ares_set_servers_csv(data->state.resolver, servers); 603e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET switch(ares_result) { 604e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case ARES_SUCCESS: 605e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET result = CURLE_OK; 606e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 607e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case ARES_ENOMEM: 608e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET result = CURLE_OUT_OF_MEMORY; 609e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 610e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case ARES_ENOTINITIALIZED: 611e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case ARES_ENODATA: 612e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case ARES_EBADSTR: 613e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET default: 614e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET result = CURLE_BAD_FUNCTION_ARGUMENT; 615e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 616e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 617e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#else /* too old c-ares version! */ 618e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)data; 619e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)(ares_result); 620e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 621e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return result; 622e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 623e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 624e3149cc1cf501b46caba8d47652ac90b95c78eacAlex DeymoCURLcode Curl_set_dns_interface(struct Curl_easy *data, 625e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET const char *interf) 626e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 627e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if (ARES_VERSION >= 0x010704) 628e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!interf) 629e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET interf = ""; 630e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 631e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_set_local_dev((ares_channel)data->state.resolver, interf); 632e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 633e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_OK; 634e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#else /* c-ares version too old! */ 635e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)data; 636e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)interf; 637e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_NOT_BUILT_IN; 638e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 639e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 640e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 641e3149cc1cf501b46caba8d47652ac90b95c78eacAlex DeymoCURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, 642e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET const char *local_ip4) 643e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 644e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if (ARES_VERSION >= 0x010704) 645e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct in_addr a4; 646e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 647e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if((!local_ip4) || (local_ip4[0] == 0)) { 648e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET a4.s_addr = 0; /* disabled: do not bind to a specific address */ 649e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 650e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else { 651e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) { 652e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_BAD_FUNCTION_ARGUMENT; 653e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 654e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 655e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 656e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr)); 657e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 658e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_OK; 659e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#else /* c-ares version too old! */ 660e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)data; 661e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)local_ip4; 662e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_NOT_BUILT_IN; 663e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 664e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 665e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 666e3149cc1cf501b46caba8d47652ac90b95c78eacAlex DeymoCURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, 667e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET const char *local_ip6) 668e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 669e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6) 670e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET unsigned char a6[INET6_ADDRSTRLEN]; 671e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 672e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if((!local_ip6) || (local_ip6[0] == 0)) { 673e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* disabled: do not bind to a specific address */ 674e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET memset(a6, 0, sizeof(a6)); 675e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 676e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else { 677e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) { 678e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_BAD_FUNCTION_ARGUMENT; 679e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 680e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 681e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 682e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ares_set_local_ip6((ares_channel)data->state.resolver, a6); 683e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 684e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_OK; 685e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#else /* c-ares version too old! */ 686e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)data; 687e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)local_ip6; 688e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return CURLE_NOT_BUILT_IN; 689e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 690e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 691e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif /* CURLRES_ARES */ 692