xref: /aosp_15_r20/external/curl/lib/hostip.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
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 #ifdef HAVE_NETINET_IN_H
28*6236dae4SAndroid Build Coastguard Worker #include <netinet/in.h>
29*6236dae4SAndroid Build Coastguard Worker #endif
30*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN6_H
31*6236dae4SAndroid Build Coastguard Worker #include <netinet/in6.h>
32*6236dae4SAndroid Build Coastguard Worker #endif
33*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETDB_H
34*6236dae4SAndroid Build Coastguard Worker #include <netdb.h>
35*6236dae4SAndroid Build Coastguard Worker #endif
36*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
37*6236dae4SAndroid Build Coastguard Worker #include <arpa/inet.h>
38*6236dae4SAndroid Build Coastguard Worker #endif
39*6236dae4SAndroid Build Coastguard Worker #ifdef __VMS
40*6236dae4SAndroid Build Coastguard Worker #include <in.h>
41*6236dae4SAndroid Build Coastguard Worker #include <inet.h>
42*6236dae4SAndroid Build Coastguard Worker #endif
43*6236dae4SAndroid Build Coastguard Worker 
44*6236dae4SAndroid Build Coastguard Worker #include <setjmp.h>
45*6236dae4SAndroid Build Coastguard Worker #include <signal.h>
46*6236dae4SAndroid Build Coastguard Worker 
47*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
48*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
49*6236dae4SAndroid Build Coastguard Worker #include "hostip.h"
50*6236dae4SAndroid Build Coastguard Worker #include "hash.h"
51*6236dae4SAndroid Build Coastguard Worker #include "rand.h"
52*6236dae4SAndroid Build Coastguard Worker #include "share.h"
53*6236dae4SAndroid Build Coastguard Worker #include "url.h"
54*6236dae4SAndroid Build Coastguard Worker #include "inet_ntop.h"
55*6236dae4SAndroid Build Coastguard Worker #include "inet_pton.h"
56*6236dae4SAndroid Build Coastguard Worker #include "multiif.h"
57*6236dae4SAndroid Build Coastguard Worker #include "doh.h"
58*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
59*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
60*6236dae4SAndroid Build Coastguard Worker #include "easy_lock.h"
61*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
62*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
63*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
64*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
65*6236dae4SAndroid Build Coastguard Worker 
66*6236dae4SAndroid Build Coastguard Worker #if defined(CURLRES_SYNCH) &&                   \
67*6236dae4SAndroid Build Coastguard Worker   defined(HAVE_ALARM) &&                        \
68*6236dae4SAndroid Build Coastguard Worker   defined(SIGALRM) &&                           \
69*6236dae4SAndroid Build Coastguard Worker   defined(HAVE_SIGSETJMP) &&                    \
70*6236dae4SAndroid Build Coastguard Worker   defined(GLOBAL_INIT_IS_THREADSAFE)
71*6236dae4SAndroid Build Coastguard Worker /* alarm-based timeouts can only be used with all the dependencies satisfied */
72*6236dae4SAndroid Build Coastguard Worker #define USE_ALARM_TIMEOUT
73*6236dae4SAndroid Build Coastguard Worker #endif
74*6236dae4SAndroid Build Coastguard Worker 
75*6236dae4SAndroid Build Coastguard Worker #define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */
76*6236dae4SAndroid Build Coastguard Worker 
77*6236dae4SAndroid Build Coastguard Worker #define MAX_DNS_CACHE_SIZE 29999
78*6236dae4SAndroid Build Coastguard Worker 
79*6236dae4SAndroid Build Coastguard Worker /*
80*6236dae4SAndroid Build Coastguard Worker  * hostip.c explained
81*6236dae4SAndroid Build Coastguard Worker  * ==================
82*6236dae4SAndroid Build Coastguard Worker  *
83*6236dae4SAndroid Build Coastguard Worker  * The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c
84*6236dae4SAndroid Build Coastguard Worker  * source file are these:
85*6236dae4SAndroid Build Coastguard Worker  *
86*6236dae4SAndroid Build Coastguard Worker  * CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use
87*6236dae4SAndroid Build Coastguard Worker  * that. The host may not be able to resolve IPv6, but we do not really have to
88*6236dae4SAndroid Build Coastguard Worker  * take that into account. Hosts that are not IPv6-enabled have CURLRES_IPV4
89*6236dae4SAndroid Build Coastguard Worker  * defined.
90*6236dae4SAndroid Build Coastguard Worker  *
91*6236dae4SAndroid Build Coastguard Worker  * CURLRES_ARES - is defined if libcurl is built to use c-ares for
92*6236dae4SAndroid Build Coastguard Worker  * asynchronous name resolves. This can be Windows or *nix.
93*6236dae4SAndroid Build Coastguard Worker  *
94*6236dae4SAndroid Build Coastguard Worker  * CURLRES_THREADED - is defined if libcurl is built to run under (native)
95*6236dae4SAndroid Build Coastguard Worker  * Windows, and then the name resolve will be done in a new thread, and the
96*6236dae4SAndroid Build Coastguard Worker  * supported API will be the same as for ares-builds.
97*6236dae4SAndroid Build Coastguard Worker  *
98*6236dae4SAndroid Build Coastguard Worker  * If any of the two previous are defined, CURLRES_ASYNCH is defined too. If
99*6236dae4SAndroid Build Coastguard Worker  * libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is
100*6236dae4SAndroid Build Coastguard Worker  * defined.
101*6236dae4SAndroid Build Coastguard Worker  *
102*6236dae4SAndroid Build Coastguard Worker  * The host*.c sources files are split up like this:
103*6236dae4SAndroid Build Coastguard Worker  *
104*6236dae4SAndroid Build Coastguard Worker  * hostip.c   - method-independent resolver functions and utility functions
105*6236dae4SAndroid Build Coastguard Worker  * hostasyn.c - functions for asynchronous name resolves
106*6236dae4SAndroid Build Coastguard Worker  * hostsyn.c  - functions for synchronous name resolves
107*6236dae4SAndroid Build Coastguard Worker  * hostip4.c  - IPv4 specific functions
108*6236dae4SAndroid Build Coastguard Worker  * hostip6.c  - IPv6 specific functions
109*6236dae4SAndroid Build Coastguard Worker  *
110*6236dae4SAndroid Build Coastguard Worker  * The two asynchronous name resolver backends are implemented in:
111*6236dae4SAndroid Build Coastguard Worker  * asyn-ares.c   - functions for ares-using name resolves
112*6236dae4SAndroid Build Coastguard Worker  * asyn-thread.c - functions for threaded name resolves
113*6236dae4SAndroid Build Coastguard Worker 
114*6236dae4SAndroid Build Coastguard Worker  * The hostip.h is the united header file for all this. It defines the
115*6236dae4SAndroid Build Coastguard Worker  * CURLRES_* defines based on the config*.h and curl_setup.h defines.
116*6236dae4SAndroid Build Coastguard Worker  */
117*6236dae4SAndroid Build Coastguard Worker 
118*6236dae4SAndroid Build Coastguard Worker static void hostcache_unlink_entry(void *entry);
119*6236dae4SAndroid Build Coastguard Worker 
120*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_VERBOSE_STRINGS
121*6236dae4SAndroid Build Coastguard Worker static void show_resolve_info(struct Curl_easy *data,
122*6236dae4SAndroid Build Coastguard Worker                               struct Curl_dns_entry *dns);
123*6236dae4SAndroid Build Coastguard Worker #else
124*6236dae4SAndroid Build Coastguard Worker #define show_resolve_info(x,y) Curl_nop_stmt
125*6236dae4SAndroid Build Coastguard Worker #endif
126*6236dae4SAndroid Build Coastguard Worker 
127*6236dae4SAndroid Build Coastguard Worker /*
128*6236dae4SAndroid Build Coastguard Worker  * Curl_printable_address() stores a printable version of the 1st address
129*6236dae4SAndroid Build Coastguard Worker  * given in the 'ai' argument. The result will be stored in the buf that is
130*6236dae4SAndroid Build Coastguard Worker  * bufsize bytes big.
131*6236dae4SAndroid Build Coastguard Worker  *
132*6236dae4SAndroid Build Coastguard Worker  * If the conversion fails, the target buffer is empty.
133*6236dae4SAndroid Build Coastguard Worker  */
Curl_printable_address(const struct Curl_addrinfo * ai,char * buf,size_t bufsize)134*6236dae4SAndroid Build Coastguard Worker void Curl_printable_address(const struct Curl_addrinfo *ai, char *buf,
135*6236dae4SAndroid Build Coastguard Worker                             size_t bufsize)
136*6236dae4SAndroid Build Coastguard Worker {
137*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(bufsize);
138*6236dae4SAndroid Build Coastguard Worker   buf[0] = 0;
139*6236dae4SAndroid Build Coastguard Worker 
140*6236dae4SAndroid Build Coastguard Worker   switch(ai->ai_family) {
141*6236dae4SAndroid Build Coastguard Worker   case AF_INET: {
142*6236dae4SAndroid Build Coastguard Worker     const struct sockaddr_in *sa4 = (const void *)ai->ai_addr;
143*6236dae4SAndroid Build Coastguard Worker     const struct in_addr *ipaddr4 = &sa4->sin_addr;
144*6236dae4SAndroid Build Coastguard Worker     (void)Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, bufsize);
145*6236dae4SAndroid Build Coastguard Worker     break;
146*6236dae4SAndroid Build Coastguard Worker   }
147*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
148*6236dae4SAndroid Build Coastguard Worker   case AF_INET6: {
149*6236dae4SAndroid Build Coastguard Worker     const struct sockaddr_in6 *sa6 = (const void *)ai->ai_addr;
150*6236dae4SAndroid Build Coastguard Worker     const struct in6_addr *ipaddr6 = &sa6->sin6_addr;
151*6236dae4SAndroid Build Coastguard Worker     (void)Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, bufsize);
152*6236dae4SAndroid Build Coastguard Worker     break;
153*6236dae4SAndroid Build Coastguard Worker   }
154*6236dae4SAndroid Build Coastguard Worker #endif
155*6236dae4SAndroid Build Coastguard Worker   default:
156*6236dae4SAndroid Build Coastguard Worker     break;
157*6236dae4SAndroid Build Coastguard Worker   }
158*6236dae4SAndroid Build Coastguard Worker }
159*6236dae4SAndroid Build Coastguard Worker 
160*6236dae4SAndroid Build Coastguard Worker /*
161*6236dae4SAndroid Build Coastguard Worker  * Create a hostcache id string for the provided host + port, to be used by
162*6236dae4SAndroid Build Coastguard Worker  * the DNS caching. Without alloc. Return length of the id string.
163*6236dae4SAndroid Build Coastguard Worker  */
164*6236dae4SAndroid Build Coastguard Worker static size_t
create_hostcache_id(const char * name,size_t nlen,int port,char * ptr,size_t buflen)165*6236dae4SAndroid Build Coastguard Worker create_hostcache_id(const char *name,
166*6236dae4SAndroid Build Coastguard Worker                     size_t nlen, /* 0 or actual name length */
167*6236dae4SAndroid Build Coastguard Worker                     int port, char *ptr, size_t buflen)
168*6236dae4SAndroid Build Coastguard Worker {
169*6236dae4SAndroid Build Coastguard Worker   size_t len = nlen ? nlen : strlen(name);
170*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(buflen >= MAX_HOSTCACHE_LEN);
171*6236dae4SAndroid Build Coastguard Worker   if(len > (buflen - 7))
172*6236dae4SAndroid Build Coastguard Worker     len = buflen - 7;
173*6236dae4SAndroid Build Coastguard Worker   /* store and lower case the name */
174*6236dae4SAndroid Build Coastguard Worker   Curl_strntolower(ptr, name, len);
175*6236dae4SAndroid Build Coastguard Worker   return msnprintf(&ptr[len], 7, ":%u", port) + len;
176*6236dae4SAndroid Build Coastguard Worker }
177*6236dae4SAndroid Build Coastguard Worker 
178*6236dae4SAndroid Build Coastguard Worker struct hostcache_prune_data {
179*6236dae4SAndroid Build Coastguard Worker   time_t now;
180*6236dae4SAndroid Build Coastguard Worker   time_t oldest; /* oldest time in cache not pruned. */
181*6236dae4SAndroid Build Coastguard Worker   int max_age_sec;
182*6236dae4SAndroid Build Coastguard Worker };
183*6236dae4SAndroid Build Coastguard Worker 
184*6236dae4SAndroid Build Coastguard Worker /*
185*6236dae4SAndroid Build Coastguard Worker  * This function is set as a callback to be called for every entry in the DNS
186*6236dae4SAndroid Build Coastguard Worker  * cache when we want to prune old unused entries.
187*6236dae4SAndroid Build Coastguard Worker  *
188*6236dae4SAndroid Build Coastguard Worker  * Returning non-zero means remove the entry, return 0 to keep it in the
189*6236dae4SAndroid Build Coastguard Worker  * cache.
190*6236dae4SAndroid Build Coastguard Worker  */
191*6236dae4SAndroid Build Coastguard Worker static int
hostcache_entry_is_stale(void * datap,void * hc)192*6236dae4SAndroid Build Coastguard Worker hostcache_entry_is_stale(void *datap, void *hc)
193*6236dae4SAndroid Build Coastguard Worker {
194*6236dae4SAndroid Build Coastguard Worker   struct hostcache_prune_data *prune =
195*6236dae4SAndroid Build Coastguard Worker     (struct hostcache_prune_data *) datap;
196*6236dae4SAndroid Build Coastguard Worker   struct Curl_dns_entry *dns = (struct Curl_dns_entry *) hc;
197*6236dae4SAndroid Build Coastguard Worker 
198*6236dae4SAndroid Build Coastguard Worker   if(dns->timestamp) {
199*6236dae4SAndroid Build Coastguard Worker     /* age in seconds */
200*6236dae4SAndroid Build Coastguard Worker     time_t age = prune->now - dns->timestamp;
201*6236dae4SAndroid Build Coastguard Worker     if(age >= prune->max_age_sec)
202*6236dae4SAndroid Build Coastguard Worker       return TRUE;
203*6236dae4SAndroid Build Coastguard Worker     if(age > prune->oldest)
204*6236dae4SAndroid Build Coastguard Worker       prune->oldest = age;
205*6236dae4SAndroid Build Coastguard Worker   }
206*6236dae4SAndroid Build Coastguard Worker   return FALSE;
207*6236dae4SAndroid Build Coastguard Worker }
208*6236dae4SAndroid Build Coastguard Worker 
209*6236dae4SAndroid Build Coastguard Worker /*
210*6236dae4SAndroid Build Coastguard Worker  * Prune the DNS cache. This assumes that a lock has already been taken.
211*6236dae4SAndroid Build Coastguard Worker  * Returns the 'age' of the oldest still kept entry.
212*6236dae4SAndroid Build Coastguard Worker  */
213*6236dae4SAndroid Build Coastguard Worker static time_t
hostcache_prune(struct Curl_hash * hostcache,int cache_timeout,time_t now)214*6236dae4SAndroid Build Coastguard Worker hostcache_prune(struct Curl_hash *hostcache, int cache_timeout,
215*6236dae4SAndroid Build Coastguard Worker                 time_t now)
216*6236dae4SAndroid Build Coastguard Worker {
217*6236dae4SAndroid Build Coastguard Worker   struct hostcache_prune_data user;
218*6236dae4SAndroid Build Coastguard Worker 
219*6236dae4SAndroid Build Coastguard Worker   user.max_age_sec = cache_timeout;
220*6236dae4SAndroid Build Coastguard Worker   user.now = now;
221*6236dae4SAndroid Build Coastguard Worker   user.oldest = 0;
222*6236dae4SAndroid Build Coastguard Worker 
223*6236dae4SAndroid Build Coastguard Worker   Curl_hash_clean_with_criterium(hostcache,
224*6236dae4SAndroid Build Coastguard Worker                                  (void *) &user,
225*6236dae4SAndroid Build Coastguard Worker                                  hostcache_entry_is_stale);
226*6236dae4SAndroid Build Coastguard Worker 
227*6236dae4SAndroid Build Coastguard Worker   return user.oldest;
228*6236dae4SAndroid Build Coastguard Worker }
229*6236dae4SAndroid Build Coastguard Worker 
230*6236dae4SAndroid Build Coastguard Worker /*
231*6236dae4SAndroid Build Coastguard Worker  * Library-wide function for pruning the DNS cache. This function takes and
232*6236dae4SAndroid Build Coastguard Worker  * returns the appropriate locks.
233*6236dae4SAndroid Build Coastguard Worker  */
Curl_hostcache_prune(struct Curl_easy * data)234*6236dae4SAndroid Build Coastguard Worker void Curl_hostcache_prune(struct Curl_easy *data)
235*6236dae4SAndroid Build Coastguard Worker {
236*6236dae4SAndroid Build Coastguard Worker   time_t now;
237*6236dae4SAndroid Build Coastguard Worker   /* the timeout may be set -1 (forever) */
238*6236dae4SAndroid Build Coastguard Worker   int timeout = data->set.dns_cache_timeout;
239*6236dae4SAndroid Build Coastguard Worker 
240*6236dae4SAndroid Build Coastguard Worker   if(!data->dns.hostcache)
241*6236dae4SAndroid Build Coastguard Worker     /* NULL hostcache means we cannot do it */
242*6236dae4SAndroid Build Coastguard Worker     return;
243*6236dae4SAndroid Build Coastguard Worker 
244*6236dae4SAndroid Build Coastguard Worker   if(data->share)
245*6236dae4SAndroid Build Coastguard Worker     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
246*6236dae4SAndroid Build Coastguard Worker 
247*6236dae4SAndroid Build Coastguard Worker   now = time(NULL);
248*6236dae4SAndroid Build Coastguard Worker 
249*6236dae4SAndroid Build Coastguard Worker   do {
250*6236dae4SAndroid Build Coastguard Worker     /* Remove outdated and unused entries from the hostcache */
251*6236dae4SAndroid Build Coastguard Worker     time_t oldest = hostcache_prune(data->dns.hostcache, timeout, now);
252*6236dae4SAndroid Build Coastguard Worker 
253*6236dae4SAndroid Build Coastguard Worker     if(oldest < INT_MAX)
254*6236dae4SAndroid Build Coastguard Worker       timeout = (int)oldest; /* we know it fits */
255*6236dae4SAndroid Build Coastguard Worker     else
256*6236dae4SAndroid Build Coastguard Worker       timeout = INT_MAX - 1;
257*6236dae4SAndroid Build Coastguard Worker 
258*6236dae4SAndroid Build Coastguard Worker     /* if the cache size is still too big, use the oldest age as new
259*6236dae4SAndroid Build Coastguard Worker        prune limit */
260*6236dae4SAndroid Build Coastguard Worker   } while(timeout &&
261*6236dae4SAndroid Build Coastguard Worker           (Curl_hash_count(data->dns.hostcache) > MAX_DNS_CACHE_SIZE));
262*6236dae4SAndroid Build Coastguard Worker 
263*6236dae4SAndroid Build Coastguard Worker   if(data->share)
264*6236dae4SAndroid Build Coastguard Worker     Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
265*6236dae4SAndroid Build Coastguard Worker }
266*6236dae4SAndroid Build Coastguard Worker 
267*6236dae4SAndroid Build Coastguard Worker #ifdef USE_ALARM_TIMEOUT
268*6236dae4SAndroid Build Coastguard Worker /* Beware this is a global and unique instance. This is used to store the
269*6236dae4SAndroid Build Coastguard Worker    return address that we can jump back to from inside a signal handler. This
270*6236dae4SAndroid Build Coastguard Worker    is not thread-safe stuff. */
271*6236dae4SAndroid Build Coastguard Worker static sigjmp_buf curl_jmpenv;
272*6236dae4SAndroid Build Coastguard Worker static curl_simple_lock curl_jmpenv_lock;
273*6236dae4SAndroid Build Coastguard Worker #endif
274*6236dae4SAndroid Build Coastguard Worker 
275*6236dae4SAndroid Build Coastguard Worker /* lookup address, returns entry if found and not stale */
fetch_addr(struct Curl_easy * data,const char * hostname,int port)276*6236dae4SAndroid Build Coastguard Worker static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
277*6236dae4SAndroid Build Coastguard Worker                                          const char *hostname,
278*6236dae4SAndroid Build Coastguard Worker                                          int port)
279*6236dae4SAndroid Build Coastguard Worker {
280*6236dae4SAndroid Build Coastguard Worker   struct Curl_dns_entry *dns = NULL;
281*6236dae4SAndroid Build Coastguard Worker   char entry_id[MAX_HOSTCACHE_LEN];
282*6236dae4SAndroid Build Coastguard Worker 
283*6236dae4SAndroid Build Coastguard Worker   /* Create an entry id, based upon the hostname and port */
284*6236dae4SAndroid Build Coastguard Worker   size_t entry_len = create_hostcache_id(hostname, 0, port,
285*6236dae4SAndroid Build Coastguard Worker                                          entry_id, sizeof(entry_id));
286*6236dae4SAndroid Build Coastguard Worker 
287*6236dae4SAndroid Build Coastguard Worker   /* See if it is already in our dns cache */
288*6236dae4SAndroid Build Coastguard Worker   dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
289*6236dae4SAndroid Build Coastguard Worker 
290*6236dae4SAndroid Build Coastguard Worker   /* No entry found in cache, check if we might have a wildcard entry */
291*6236dae4SAndroid Build Coastguard Worker   if(!dns && data->state.wildcard_resolve) {
292*6236dae4SAndroid Build Coastguard Worker     entry_len = create_hostcache_id("*", 1, port, entry_id, sizeof(entry_id));
293*6236dae4SAndroid Build Coastguard Worker 
294*6236dae4SAndroid Build Coastguard Worker     /* See if it is already in our dns cache */
295*6236dae4SAndroid Build Coastguard Worker     dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
296*6236dae4SAndroid Build Coastguard Worker   }
297*6236dae4SAndroid Build Coastguard Worker 
298*6236dae4SAndroid Build Coastguard Worker   if(dns && (data->set.dns_cache_timeout != -1)) {
299*6236dae4SAndroid Build Coastguard Worker     /* See whether the returned entry is stale. Done before we release lock */
300*6236dae4SAndroid Build Coastguard Worker     struct hostcache_prune_data user;
301*6236dae4SAndroid Build Coastguard Worker 
302*6236dae4SAndroid Build Coastguard Worker     user.now = time(NULL);
303*6236dae4SAndroid Build Coastguard Worker     user.max_age_sec = data->set.dns_cache_timeout;
304*6236dae4SAndroid Build Coastguard Worker     user.oldest = 0;
305*6236dae4SAndroid Build Coastguard Worker 
306*6236dae4SAndroid Build Coastguard Worker     if(hostcache_entry_is_stale(&user, dns)) {
307*6236dae4SAndroid Build Coastguard Worker       infof(data, "Hostname in DNS cache was stale, zapped");
308*6236dae4SAndroid Build Coastguard Worker       dns = NULL; /* the memory deallocation is being handled by the hash */
309*6236dae4SAndroid Build Coastguard Worker       Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
310*6236dae4SAndroid Build Coastguard Worker     }
311*6236dae4SAndroid Build Coastguard Worker   }
312*6236dae4SAndroid Build Coastguard Worker 
313*6236dae4SAndroid Build Coastguard Worker   /* See if the returned entry matches the required resolve mode */
314*6236dae4SAndroid Build Coastguard Worker   if(dns && data->conn->ip_version != CURL_IPRESOLVE_WHATEVER) {
315*6236dae4SAndroid Build Coastguard Worker     int pf = PF_INET;
316*6236dae4SAndroid Build Coastguard Worker     bool found = FALSE;
317*6236dae4SAndroid Build Coastguard Worker     struct Curl_addrinfo *addr = dns->addr;
318*6236dae4SAndroid Build Coastguard Worker 
319*6236dae4SAndroid Build Coastguard Worker #ifdef PF_INET6
320*6236dae4SAndroid Build Coastguard Worker     if(data->conn->ip_version == CURL_IPRESOLVE_V6)
321*6236dae4SAndroid Build Coastguard Worker       pf = PF_INET6;
322*6236dae4SAndroid Build Coastguard Worker #endif
323*6236dae4SAndroid Build Coastguard Worker 
324*6236dae4SAndroid Build Coastguard Worker     while(addr) {
325*6236dae4SAndroid Build Coastguard Worker       if(addr->ai_family == pf) {
326*6236dae4SAndroid Build Coastguard Worker         found = TRUE;
327*6236dae4SAndroid Build Coastguard Worker         break;
328*6236dae4SAndroid Build Coastguard Worker       }
329*6236dae4SAndroid Build Coastguard Worker       addr = addr->ai_next;
330*6236dae4SAndroid Build Coastguard Worker     }
331*6236dae4SAndroid Build Coastguard Worker 
332*6236dae4SAndroid Build Coastguard Worker     if(!found) {
333*6236dae4SAndroid Build Coastguard Worker       infof(data, "Hostname in DNS cache does not have needed family, zapped");
334*6236dae4SAndroid Build Coastguard Worker       dns = NULL; /* the memory deallocation is being handled by the hash */
335*6236dae4SAndroid Build Coastguard Worker       Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
336*6236dae4SAndroid Build Coastguard Worker     }
337*6236dae4SAndroid Build Coastguard Worker   }
338*6236dae4SAndroid Build Coastguard Worker   return dns;
339*6236dae4SAndroid Build Coastguard Worker }
340*6236dae4SAndroid Build Coastguard Worker 
341*6236dae4SAndroid Build Coastguard Worker /*
342*6236dae4SAndroid Build Coastguard Worker  * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
343*6236dae4SAndroid Build Coastguard Worker  *
344*6236dae4SAndroid Build Coastguard Worker  * Curl_resolv() checks initially and multi_runsingle() checks each time
345*6236dae4SAndroid Build Coastguard Worker  * it discovers the handle in the state WAITRESOLVE whether the hostname
346*6236dae4SAndroid Build Coastguard Worker  * has already been resolved and the address has already been stored in
347*6236dae4SAndroid Build Coastguard Worker  * the DNS cache. This short circuits waiting for a lot of pending
348*6236dae4SAndroid Build Coastguard Worker  * lookups for the same hostname requested by different handles.
349*6236dae4SAndroid Build Coastguard Worker  *
350*6236dae4SAndroid Build Coastguard Worker  * Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
351*6236dae4SAndroid Build Coastguard Worker  *
352*6236dae4SAndroid Build Coastguard Worker  * The returned data *MUST* be "released" with Curl_resolv_unlink() after
353*6236dae4SAndroid Build Coastguard Worker  * use, or we will leak memory!
354*6236dae4SAndroid Build Coastguard Worker  */
355*6236dae4SAndroid Build Coastguard Worker struct Curl_dns_entry *
Curl_fetch_addr(struct Curl_easy * data,const char * hostname,int port)356*6236dae4SAndroid Build Coastguard Worker Curl_fetch_addr(struct Curl_easy *data,
357*6236dae4SAndroid Build Coastguard Worker                 const char *hostname,
358*6236dae4SAndroid Build Coastguard Worker                 int port)
359*6236dae4SAndroid Build Coastguard Worker {
360*6236dae4SAndroid Build Coastguard Worker   struct Curl_dns_entry *dns = NULL;
361*6236dae4SAndroid Build Coastguard Worker 
362*6236dae4SAndroid Build Coastguard Worker   if(data->share)
363*6236dae4SAndroid Build Coastguard Worker     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
364*6236dae4SAndroid Build Coastguard Worker 
365*6236dae4SAndroid Build Coastguard Worker   dns = fetch_addr(data, hostname, port);
366*6236dae4SAndroid Build Coastguard Worker 
367*6236dae4SAndroid Build Coastguard Worker   if(dns)
368*6236dae4SAndroid Build Coastguard Worker     dns->refcount++; /* we use it! */
369*6236dae4SAndroid Build Coastguard Worker 
370*6236dae4SAndroid Build Coastguard Worker   if(data->share)
371*6236dae4SAndroid Build Coastguard Worker     Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
372*6236dae4SAndroid Build Coastguard Worker 
373*6236dae4SAndroid Build Coastguard Worker   return dns;
374*6236dae4SAndroid Build Coastguard Worker }
375*6236dae4SAndroid Build Coastguard Worker 
376*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_SHUFFLE_DNS
377*6236dae4SAndroid Build Coastguard Worker /*
378*6236dae4SAndroid Build Coastguard Worker  * Return # of addresses in a Curl_addrinfo struct
379*6236dae4SAndroid Build Coastguard Worker  */
num_addresses(const struct Curl_addrinfo * addr)380*6236dae4SAndroid Build Coastguard Worker static int num_addresses(const struct Curl_addrinfo *addr)
381*6236dae4SAndroid Build Coastguard Worker {
382*6236dae4SAndroid Build Coastguard Worker   int i = 0;
383*6236dae4SAndroid Build Coastguard Worker   while(addr) {
384*6236dae4SAndroid Build Coastguard Worker     addr = addr->ai_next;
385*6236dae4SAndroid Build Coastguard Worker     i++;
386*6236dae4SAndroid Build Coastguard Worker   }
387*6236dae4SAndroid Build Coastguard Worker   return i;
388*6236dae4SAndroid Build Coastguard Worker }
389*6236dae4SAndroid Build Coastguard Worker 
390*6236dae4SAndroid Build Coastguard Worker UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
391*6236dae4SAndroid Build Coastguard Worker                                     struct Curl_addrinfo **addr);
392*6236dae4SAndroid Build Coastguard Worker /*
393*6236dae4SAndroid Build Coastguard Worker  * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
394*6236dae4SAndroid Build Coastguard Worker  * struct by re-linking its linked list.
395*6236dae4SAndroid Build Coastguard Worker  *
396*6236dae4SAndroid Build Coastguard Worker  * The addr argument should be the address of a pointer to the head node of a
397*6236dae4SAndroid Build Coastguard Worker  * `Curl_addrinfo` list and it will be modified to point to the new head after
398*6236dae4SAndroid Build Coastguard Worker  * shuffling.
399*6236dae4SAndroid Build Coastguard Worker  *
400*6236dae4SAndroid Build Coastguard Worker  * Not declared static only to make it easy to use in a unit test!
401*6236dae4SAndroid Build Coastguard Worker  *
402*6236dae4SAndroid Build Coastguard Worker  * @unittest: 1608
403*6236dae4SAndroid Build Coastguard Worker  */
Curl_shuffle_addr(struct Curl_easy * data,struct Curl_addrinfo ** addr)404*6236dae4SAndroid Build Coastguard Worker UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
405*6236dae4SAndroid Build Coastguard Worker                                     struct Curl_addrinfo **addr)
406*6236dae4SAndroid Build Coastguard Worker {
407*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
408*6236dae4SAndroid Build Coastguard Worker   const int num_addrs = num_addresses(*addr);
409*6236dae4SAndroid Build Coastguard Worker 
410*6236dae4SAndroid Build Coastguard Worker   if(num_addrs > 1) {
411*6236dae4SAndroid Build Coastguard Worker     struct Curl_addrinfo **nodes;
412*6236dae4SAndroid Build Coastguard Worker     infof(data, "Shuffling %i addresses", num_addrs);
413*6236dae4SAndroid Build Coastguard Worker 
414*6236dae4SAndroid Build Coastguard Worker     nodes = malloc(num_addrs*sizeof(*nodes));
415*6236dae4SAndroid Build Coastguard Worker     if(nodes) {
416*6236dae4SAndroid Build Coastguard Worker       int i;
417*6236dae4SAndroid Build Coastguard Worker       unsigned int *rnd;
418*6236dae4SAndroid Build Coastguard Worker       const size_t rnd_size = num_addrs * sizeof(*rnd);
419*6236dae4SAndroid Build Coastguard Worker 
420*6236dae4SAndroid Build Coastguard Worker       /* build a plain array of Curl_addrinfo pointers */
421*6236dae4SAndroid Build Coastguard Worker       nodes[0] = *addr;
422*6236dae4SAndroid Build Coastguard Worker       for(i = 1; i < num_addrs; i++) {
423*6236dae4SAndroid Build Coastguard Worker         nodes[i] = nodes[i-1]->ai_next;
424*6236dae4SAndroid Build Coastguard Worker       }
425*6236dae4SAndroid Build Coastguard Worker 
426*6236dae4SAndroid Build Coastguard Worker       rnd = malloc(rnd_size);
427*6236dae4SAndroid Build Coastguard Worker       if(rnd) {
428*6236dae4SAndroid Build Coastguard Worker         /* Fisher-Yates shuffle */
429*6236dae4SAndroid Build Coastguard Worker         if(Curl_rand(data, (unsigned char *)rnd, rnd_size) == CURLE_OK) {
430*6236dae4SAndroid Build Coastguard Worker           struct Curl_addrinfo *swap_tmp;
431*6236dae4SAndroid Build Coastguard Worker           for(i = num_addrs - 1; i > 0; i--) {
432*6236dae4SAndroid Build Coastguard Worker             swap_tmp = nodes[rnd[i] % (unsigned int)(i + 1)];
433*6236dae4SAndroid Build Coastguard Worker             nodes[rnd[i] % (unsigned int)(i + 1)] = nodes[i];
434*6236dae4SAndroid Build Coastguard Worker             nodes[i] = swap_tmp;
435*6236dae4SAndroid Build Coastguard Worker           }
436*6236dae4SAndroid Build Coastguard Worker 
437*6236dae4SAndroid Build Coastguard Worker           /* relink list in the new order */
438*6236dae4SAndroid Build Coastguard Worker           for(i = 1; i < num_addrs; i++) {
439*6236dae4SAndroid Build Coastguard Worker             nodes[i-1]->ai_next = nodes[i];
440*6236dae4SAndroid Build Coastguard Worker           }
441*6236dae4SAndroid Build Coastguard Worker 
442*6236dae4SAndroid Build Coastguard Worker           nodes[num_addrs-1]->ai_next = NULL;
443*6236dae4SAndroid Build Coastguard Worker           *addr = nodes[0];
444*6236dae4SAndroid Build Coastguard Worker         }
445*6236dae4SAndroid Build Coastguard Worker         free(rnd);
446*6236dae4SAndroid Build Coastguard Worker       }
447*6236dae4SAndroid Build Coastguard Worker       else
448*6236dae4SAndroid Build Coastguard Worker         result = CURLE_OUT_OF_MEMORY;
449*6236dae4SAndroid Build Coastguard Worker       free(nodes);
450*6236dae4SAndroid Build Coastguard Worker     }
451*6236dae4SAndroid Build Coastguard Worker     else
452*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
453*6236dae4SAndroid Build Coastguard Worker   }
454*6236dae4SAndroid Build Coastguard Worker   return result;
455*6236dae4SAndroid Build Coastguard Worker }
456*6236dae4SAndroid Build Coastguard Worker #endif
457*6236dae4SAndroid Build Coastguard Worker 
458*6236dae4SAndroid Build Coastguard Worker /*
459*6236dae4SAndroid Build Coastguard Worker  * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
460*6236dae4SAndroid Build Coastguard Worker  *
461*6236dae4SAndroid Build Coastguard Worker  * When calling Curl_resolv() has resulted in a response with a returned
462*6236dae4SAndroid Build Coastguard Worker  * address, we call this function to store the information in the dns
463*6236dae4SAndroid Build Coastguard Worker  * cache etc
464*6236dae4SAndroid Build Coastguard Worker  *
465*6236dae4SAndroid Build Coastguard Worker  * Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
466*6236dae4SAndroid Build Coastguard Worker  */
467*6236dae4SAndroid Build Coastguard Worker struct Curl_dns_entry *
Curl_cache_addr(struct Curl_easy * data,struct Curl_addrinfo * addr,const char * hostname,size_t hostlen,int port,bool permanent)468*6236dae4SAndroid Build Coastguard Worker Curl_cache_addr(struct Curl_easy *data,
469*6236dae4SAndroid Build Coastguard Worker                 struct Curl_addrinfo *addr,
470*6236dae4SAndroid Build Coastguard Worker                 const char *hostname,
471*6236dae4SAndroid Build Coastguard Worker                 size_t hostlen, /* length or zero */
472*6236dae4SAndroid Build Coastguard Worker                 int port,
473*6236dae4SAndroid Build Coastguard Worker                 bool permanent)
474*6236dae4SAndroid Build Coastguard Worker {
475*6236dae4SAndroid Build Coastguard Worker   char entry_id[MAX_HOSTCACHE_LEN];
476*6236dae4SAndroid Build Coastguard Worker   size_t entry_len;
477*6236dae4SAndroid Build Coastguard Worker   struct Curl_dns_entry *dns;
478*6236dae4SAndroid Build Coastguard Worker   struct Curl_dns_entry *dns2;
479*6236dae4SAndroid Build Coastguard Worker 
480*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_SHUFFLE_DNS
481*6236dae4SAndroid Build Coastguard Worker   /* shuffle addresses if requested */
482*6236dae4SAndroid Build Coastguard Worker   if(data->set.dns_shuffle_addresses) {
483*6236dae4SAndroid Build Coastguard Worker     CURLcode result = Curl_shuffle_addr(data, &addr);
484*6236dae4SAndroid Build Coastguard Worker     if(result)
485*6236dae4SAndroid Build Coastguard Worker       return NULL;
486*6236dae4SAndroid Build Coastguard Worker   }
487*6236dae4SAndroid Build Coastguard Worker #endif
488*6236dae4SAndroid Build Coastguard Worker   if(!hostlen)
489*6236dae4SAndroid Build Coastguard Worker     hostlen = strlen(hostname);
490*6236dae4SAndroid Build Coastguard Worker 
491*6236dae4SAndroid Build Coastguard Worker   /* Create a new cache entry */
492*6236dae4SAndroid Build Coastguard Worker   dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen);
493*6236dae4SAndroid Build Coastguard Worker   if(!dns) {
494*6236dae4SAndroid Build Coastguard Worker     return NULL;
495*6236dae4SAndroid Build Coastguard Worker   }
496*6236dae4SAndroid Build Coastguard Worker 
497*6236dae4SAndroid Build Coastguard Worker   /* Create an entry id, based upon the hostname and port */
498*6236dae4SAndroid Build Coastguard Worker   entry_len = create_hostcache_id(hostname, hostlen, port,
499*6236dae4SAndroid Build Coastguard Worker                                   entry_id, sizeof(entry_id));
500*6236dae4SAndroid Build Coastguard Worker 
501*6236dae4SAndroid Build Coastguard Worker   dns->refcount = 1; /* the cache has the first reference */
502*6236dae4SAndroid Build Coastguard Worker   dns->addr = addr; /* this is the address(es) */
503*6236dae4SAndroid Build Coastguard Worker   if(permanent)
504*6236dae4SAndroid Build Coastguard Worker     dns->timestamp = 0; /* an entry that never goes stale */
505*6236dae4SAndroid Build Coastguard Worker   else {
506*6236dae4SAndroid Build Coastguard Worker     dns->timestamp = time(NULL);
507*6236dae4SAndroid Build Coastguard Worker     if(dns->timestamp == 0)
508*6236dae4SAndroid Build Coastguard Worker       dns->timestamp = 1;
509*6236dae4SAndroid Build Coastguard Worker   }
510*6236dae4SAndroid Build Coastguard Worker   dns->hostport = port;
511*6236dae4SAndroid Build Coastguard Worker   if(hostlen)
512*6236dae4SAndroid Build Coastguard Worker     memcpy(dns->hostname, hostname, hostlen);
513*6236dae4SAndroid Build Coastguard Worker 
514*6236dae4SAndroid Build Coastguard Worker   /* Store the resolved data in our DNS cache. */
515*6236dae4SAndroid Build Coastguard Worker   dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
516*6236dae4SAndroid Build Coastguard Worker                        (void *)dns);
517*6236dae4SAndroid Build Coastguard Worker   if(!dns2) {
518*6236dae4SAndroid Build Coastguard Worker     free(dns);
519*6236dae4SAndroid Build Coastguard Worker     return NULL;
520*6236dae4SAndroid Build Coastguard Worker   }
521*6236dae4SAndroid Build Coastguard Worker 
522*6236dae4SAndroid Build Coastguard Worker   dns = dns2;
523*6236dae4SAndroid Build Coastguard Worker   dns->refcount++;         /* mark entry as in-use */
524*6236dae4SAndroid Build Coastguard Worker   return dns;
525*6236dae4SAndroid Build Coastguard Worker }
526*6236dae4SAndroid Build Coastguard Worker 
527*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
528*6236dae4SAndroid Build Coastguard Worker /* return a static IPv6 ::1 for the name */
get_localhost6(int port,const char * name)529*6236dae4SAndroid Build Coastguard Worker static struct Curl_addrinfo *get_localhost6(int port, const char *name)
530*6236dae4SAndroid Build Coastguard Worker {
531*6236dae4SAndroid Build Coastguard Worker   struct Curl_addrinfo *ca;
532*6236dae4SAndroid Build Coastguard Worker   const size_t ss_size = sizeof(struct sockaddr_in6);
533*6236dae4SAndroid Build Coastguard Worker   const size_t hostlen = strlen(name);
534*6236dae4SAndroid Build Coastguard Worker   struct sockaddr_in6 sa6;
535*6236dae4SAndroid Build Coastguard Worker   unsigned char ipv6[16];
536*6236dae4SAndroid Build Coastguard Worker   unsigned short port16 = (unsigned short)(port & 0xffff);
537*6236dae4SAndroid Build Coastguard Worker   ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1);
538*6236dae4SAndroid Build Coastguard Worker   if(!ca)
539*6236dae4SAndroid Build Coastguard Worker     return NULL;
540*6236dae4SAndroid Build Coastguard Worker 
541*6236dae4SAndroid Build Coastguard Worker   sa6.sin6_family = AF_INET6;
542*6236dae4SAndroid Build Coastguard Worker   sa6.sin6_port = htons(port16);
543*6236dae4SAndroid Build Coastguard Worker   sa6.sin6_flowinfo = 0;
544*6236dae4SAndroid Build Coastguard Worker   sa6.sin6_scope_id = 0;
545*6236dae4SAndroid Build Coastguard Worker 
546*6236dae4SAndroid Build Coastguard Worker   (void)Curl_inet_pton(AF_INET6, "::1", ipv6);
547*6236dae4SAndroid Build Coastguard Worker   memcpy(&sa6.sin6_addr, ipv6, sizeof(ipv6));
548*6236dae4SAndroid Build Coastguard Worker 
549*6236dae4SAndroid Build Coastguard Worker   ca->ai_flags     = 0;
550*6236dae4SAndroid Build Coastguard Worker   ca->ai_family    = AF_INET6;
551*6236dae4SAndroid Build Coastguard Worker   ca->ai_socktype  = SOCK_STREAM;
552*6236dae4SAndroid Build Coastguard Worker   ca->ai_protocol  = IPPROTO_TCP;
553*6236dae4SAndroid Build Coastguard Worker   ca->ai_addrlen   = (curl_socklen_t)ss_size;
554*6236dae4SAndroid Build Coastguard Worker   ca->ai_next      = NULL;
555*6236dae4SAndroid Build Coastguard Worker   ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
556*6236dae4SAndroid Build Coastguard Worker   memcpy(ca->ai_addr, &sa6, ss_size);
557*6236dae4SAndroid Build Coastguard Worker   ca->ai_canonname = (char *)ca->ai_addr + ss_size;
558*6236dae4SAndroid Build Coastguard Worker   strcpy(ca->ai_canonname, name);
559*6236dae4SAndroid Build Coastguard Worker   return ca;
560*6236dae4SAndroid Build Coastguard Worker }
561*6236dae4SAndroid Build Coastguard Worker #else
562*6236dae4SAndroid Build Coastguard Worker #define get_localhost6(x,y) NULL
563*6236dae4SAndroid Build Coastguard Worker #endif
564*6236dae4SAndroid Build Coastguard Worker 
565*6236dae4SAndroid Build Coastguard Worker /* return a static IPv4 127.0.0.1 for the given name */
get_localhost(int port,const char * name)566*6236dae4SAndroid Build Coastguard Worker static struct Curl_addrinfo *get_localhost(int port, const char *name)
567*6236dae4SAndroid Build Coastguard Worker {
568*6236dae4SAndroid Build Coastguard Worker   struct Curl_addrinfo *ca;
569*6236dae4SAndroid Build Coastguard Worker   struct Curl_addrinfo *ca6;
570*6236dae4SAndroid Build Coastguard Worker   const size_t ss_size = sizeof(struct sockaddr_in);
571*6236dae4SAndroid Build Coastguard Worker   const size_t hostlen = strlen(name);
572*6236dae4SAndroid Build Coastguard Worker   struct sockaddr_in sa;
573*6236dae4SAndroid Build Coastguard Worker   unsigned int ipv4;
574*6236dae4SAndroid Build Coastguard Worker   unsigned short port16 = (unsigned short)(port & 0xffff);
575*6236dae4SAndroid Build Coastguard Worker 
576*6236dae4SAndroid Build Coastguard Worker   /* memset to clear the sa.sin_zero field */
577*6236dae4SAndroid Build Coastguard Worker   memset(&sa, 0, sizeof(sa));
578*6236dae4SAndroid Build Coastguard Worker   sa.sin_family = AF_INET;
579*6236dae4SAndroid Build Coastguard Worker   sa.sin_port = htons(port16);
580*6236dae4SAndroid Build Coastguard Worker   if(Curl_inet_pton(AF_INET, "127.0.0.1", (char *)&ipv4) < 1)
581*6236dae4SAndroid Build Coastguard Worker     return NULL;
582*6236dae4SAndroid Build Coastguard Worker   memcpy(&sa.sin_addr, &ipv4, sizeof(ipv4));
583*6236dae4SAndroid Build Coastguard Worker 
584*6236dae4SAndroid Build Coastguard Worker   ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1);
585*6236dae4SAndroid Build Coastguard Worker   if(!ca)
586*6236dae4SAndroid Build Coastguard Worker     return NULL;
587*6236dae4SAndroid Build Coastguard Worker   ca->ai_flags     = 0;
588*6236dae4SAndroid Build Coastguard Worker   ca->ai_family    = AF_INET;
589*6236dae4SAndroid Build Coastguard Worker   ca->ai_socktype  = SOCK_STREAM;
590*6236dae4SAndroid Build Coastguard Worker   ca->ai_protocol  = IPPROTO_TCP;
591*6236dae4SAndroid Build Coastguard Worker   ca->ai_addrlen   = (curl_socklen_t)ss_size;
592*6236dae4SAndroid Build Coastguard Worker   ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
593*6236dae4SAndroid Build Coastguard Worker   memcpy(ca->ai_addr, &sa, ss_size);
594*6236dae4SAndroid Build Coastguard Worker   ca->ai_canonname = (char *)ca->ai_addr + ss_size;
595*6236dae4SAndroid Build Coastguard Worker   strcpy(ca->ai_canonname, name);
596*6236dae4SAndroid Build Coastguard Worker 
597*6236dae4SAndroid Build Coastguard Worker   ca6 = get_localhost6(port, name);
598*6236dae4SAndroid Build Coastguard Worker   if(!ca6)
599*6236dae4SAndroid Build Coastguard Worker     return ca;
600*6236dae4SAndroid Build Coastguard Worker   ca6->ai_next = ca;
601*6236dae4SAndroid Build Coastguard Worker   return ca6;
602*6236dae4SAndroid Build Coastguard Worker }
603*6236dae4SAndroid Build Coastguard Worker 
604*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
605*6236dae4SAndroid Build Coastguard Worker /*
606*6236dae4SAndroid Build Coastguard Worker  * Curl_ipv6works() returns TRUE if IPv6 seems to work.
607*6236dae4SAndroid Build Coastguard Worker  */
Curl_ipv6works(struct Curl_easy * data)608*6236dae4SAndroid Build Coastguard Worker bool Curl_ipv6works(struct Curl_easy *data)
609*6236dae4SAndroid Build Coastguard Worker {
610*6236dae4SAndroid Build Coastguard Worker   if(data) {
611*6236dae4SAndroid Build Coastguard Worker     /* the nature of most system is that IPv6 status does not come and go
612*6236dae4SAndroid Build Coastguard Worker        during a program's lifetime so we only probe the first time and then we
613*6236dae4SAndroid Build Coastguard Worker        have the info kept for fast reuse */
614*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(data);
615*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(data->multi);
616*6236dae4SAndroid Build Coastguard Worker     if(data->multi->ipv6_up == IPV6_UNKNOWN) {
617*6236dae4SAndroid Build Coastguard Worker       bool works = Curl_ipv6works(NULL);
618*6236dae4SAndroid Build Coastguard Worker       data->multi->ipv6_up = works ? IPV6_WORKS : IPV6_DEAD;
619*6236dae4SAndroid Build Coastguard Worker     }
620*6236dae4SAndroid Build Coastguard Worker     return data->multi->ipv6_up == IPV6_WORKS;
621*6236dae4SAndroid Build Coastguard Worker   }
622*6236dae4SAndroid Build Coastguard Worker   else {
623*6236dae4SAndroid Build Coastguard Worker     int ipv6_works = -1;
624*6236dae4SAndroid Build Coastguard Worker     /* probe to see if we have a working IPv6 stack */
625*6236dae4SAndroid Build Coastguard Worker     curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
626*6236dae4SAndroid Build Coastguard Worker     if(s == CURL_SOCKET_BAD)
627*6236dae4SAndroid Build Coastguard Worker       /* an IPv6 address was requested but we cannot get/use one */
628*6236dae4SAndroid Build Coastguard Worker       ipv6_works = 0;
629*6236dae4SAndroid Build Coastguard Worker     else {
630*6236dae4SAndroid Build Coastguard Worker       ipv6_works = 1;
631*6236dae4SAndroid Build Coastguard Worker       sclose(s);
632*6236dae4SAndroid Build Coastguard Worker     }
633*6236dae4SAndroid Build Coastguard Worker     return (ipv6_works > 0);
634*6236dae4SAndroid Build Coastguard Worker   }
635*6236dae4SAndroid Build Coastguard Worker }
636*6236dae4SAndroid Build Coastguard Worker #endif /* USE_IPV6 */
637*6236dae4SAndroid Build Coastguard Worker 
638*6236dae4SAndroid Build Coastguard Worker /*
639*6236dae4SAndroid Build Coastguard Worker  * Curl_host_is_ipnum() returns TRUE if the given string is a numerical IPv4
640*6236dae4SAndroid Build Coastguard Worker  * (or IPv6 if supported) address.
641*6236dae4SAndroid Build Coastguard Worker  */
Curl_host_is_ipnum(const char * hostname)642*6236dae4SAndroid Build Coastguard Worker bool Curl_host_is_ipnum(const char *hostname)
643*6236dae4SAndroid Build Coastguard Worker {
644*6236dae4SAndroid Build Coastguard Worker   struct in_addr in;
645*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
646*6236dae4SAndroid Build Coastguard Worker   struct in6_addr in6;
647*6236dae4SAndroid Build Coastguard Worker #endif
648*6236dae4SAndroid Build Coastguard Worker   if(Curl_inet_pton(AF_INET, hostname, &in) > 0
649*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
650*6236dae4SAndroid Build Coastguard Worker      || Curl_inet_pton(AF_INET6, hostname, &in6) > 0
651*6236dae4SAndroid Build Coastguard Worker #endif
652*6236dae4SAndroid Build Coastguard Worker     )
653*6236dae4SAndroid Build Coastguard Worker     return TRUE;
654*6236dae4SAndroid Build Coastguard Worker   return FALSE;
655*6236dae4SAndroid Build Coastguard Worker }
656*6236dae4SAndroid Build Coastguard Worker 
657*6236dae4SAndroid Build Coastguard Worker 
658*6236dae4SAndroid Build Coastguard Worker /* return TRUE if 'part' is a case insensitive tail of 'full' */
tailmatch(const char * full,const char * part)659*6236dae4SAndroid Build Coastguard Worker static bool tailmatch(const char *full, const char *part)
660*6236dae4SAndroid Build Coastguard Worker {
661*6236dae4SAndroid Build Coastguard Worker   size_t plen = strlen(part);
662*6236dae4SAndroid Build Coastguard Worker   size_t flen = strlen(full);
663*6236dae4SAndroid Build Coastguard Worker   if(plen > flen)
664*6236dae4SAndroid Build Coastguard Worker     return FALSE;
665*6236dae4SAndroid Build Coastguard Worker   return strncasecompare(part, &full[flen - plen], plen);
666*6236dae4SAndroid Build Coastguard Worker }
667*6236dae4SAndroid Build Coastguard Worker 
668*6236dae4SAndroid Build Coastguard Worker /*
669*6236dae4SAndroid Build Coastguard Worker  * Curl_resolv() is the main name resolve function within libcurl. It resolves
670*6236dae4SAndroid Build Coastguard Worker  * a name and returns a pointer to the entry in the 'entry' argument (if one
671*6236dae4SAndroid Build Coastguard Worker  * is provided). This function might return immediately if we are using asynch
672*6236dae4SAndroid Build Coastguard Worker  * resolves. See the return codes.
673*6236dae4SAndroid Build Coastguard Worker  *
674*6236dae4SAndroid Build Coastguard Worker  * The cache entry we return will get its 'inuse' counter increased when this
675*6236dae4SAndroid Build Coastguard Worker  * function is used. You MUST call Curl_resolv_unlink() later (when you are
676*6236dae4SAndroid Build Coastguard Worker  * done using this struct) to decrease the reference counter again.
677*6236dae4SAndroid Build Coastguard Worker  *
678*6236dae4SAndroid Build Coastguard Worker  * Return codes:
679*6236dae4SAndroid Build Coastguard Worker  *
680*6236dae4SAndroid Build Coastguard Worker  * CURLRESOLV_ERROR   (-1) = error, no pointer
681*6236dae4SAndroid Build Coastguard Worker  * CURLRESOLV_RESOLVED (0) = OK, pointer provided
682*6236dae4SAndroid Build Coastguard Worker  * CURLRESOLV_PENDING  (1) = waiting for response, no pointer
683*6236dae4SAndroid Build Coastguard Worker  */
684*6236dae4SAndroid Build Coastguard Worker 
Curl_resolv(struct Curl_easy * data,const char * hostname,int port,bool allowDOH,struct Curl_dns_entry ** entry)685*6236dae4SAndroid Build Coastguard Worker enum resolve_t Curl_resolv(struct Curl_easy *data,
686*6236dae4SAndroid Build Coastguard Worker                            const char *hostname,
687*6236dae4SAndroid Build Coastguard Worker                            int port,
688*6236dae4SAndroid Build Coastguard Worker                            bool allowDOH,
689*6236dae4SAndroid Build Coastguard Worker                            struct Curl_dns_entry **entry)
690*6236dae4SAndroid Build Coastguard Worker {
691*6236dae4SAndroid Build Coastguard Worker   struct Curl_dns_entry *dns = NULL;
692*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
693*6236dae4SAndroid Build Coastguard Worker   enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
694*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
695*6236dae4SAndroid Build Coastguard Worker   /* We should intentionally error and not resolve .onion TLDs */
696*6236dae4SAndroid Build Coastguard Worker   size_t hostname_len = strlen(hostname);
697*6236dae4SAndroid Build Coastguard Worker   if(hostname_len >= 7 &&
698*6236dae4SAndroid Build Coastguard Worker      (curl_strequal(&hostname[hostname_len - 6], ".onion") ||
699*6236dae4SAndroid Build Coastguard Worker       curl_strequal(&hostname[hostname_len - 7], ".onion."))) {
700*6236dae4SAndroid Build Coastguard Worker     failf(data, "Not resolving .onion address (RFC 7686)");
701*6236dae4SAndroid Build Coastguard Worker     return CURLRESOLV_ERROR;
702*6236dae4SAndroid Build Coastguard Worker   }
703*6236dae4SAndroid Build Coastguard Worker   *entry = NULL;
704*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_DOH
705*6236dae4SAndroid Build Coastguard Worker   conn->bits.doh = FALSE; /* default is not */
706*6236dae4SAndroid Build Coastguard Worker #else
707*6236dae4SAndroid Build Coastguard Worker   (void)allowDOH;
708*6236dae4SAndroid Build Coastguard Worker #endif
709*6236dae4SAndroid Build Coastguard Worker 
710*6236dae4SAndroid Build Coastguard Worker   if(data->share)
711*6236dae4SAndroid Build Coastguard Worker     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
712*6236dae4SAndroid Build Coastguard Worker 
713*6236dae4SAndroid Build Coastguard Worker   dns = fetch_addr(data, hostname, port);
714*6236dae4SAndroid Build Coastguard Worker 
715*6236dae4SAndroid Build Coastguard Worker   if(dns) {
716*6236dae4SAndroid Build Coastguard Worker     infof(data, "Hostname %s was found in DNS cache", hostname);
717*6236dae4SAndroid Build Coastguard Worker     dns->refcount++; /* we use it! */
718*6236dae4SAndroid Build Coastguard Worker     rc = CURLRESOLV_RESOLVED;
719*6236dae4SAndroid Build Coastguard Worker   }
720*6236dae4SAndroid Build Coastguard Worker 
721*6236dae4SAndroid Build Coastguard Worker   if(data->share)
722*6236dae4SAndroid Build Coastguard Worker     Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
723*6236dae4SAndroid Build Coastguard Worker 
724*6236dae4SAndroid Build Coastguard Worker   if(!dns) {
725*6236dae4SAndroid Build Coastguard Worker     /* The entry was not in the cache. Resolve it to IP address */
726*6236dae4SAndroid Build Coastguard Worker 
727*6236dae4SAndroid Build Coastguard Worker     struct Curl_addrinfo *addr = NULL;
728*6236dae4SAndroid Build Coastguard Worker     int respwait = 0;
729*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_DOH) || !defined(USE_RESOLVE_ON_IPS)
730*6236dae4SAndroid Build Coastguard Worker     struct in_addr in;
731*6236dae4SAndroid Build Coastguard Worker #endif
732*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_DOH
733*6236dae4SAndroid Build Coastguard Worker #ifndef USE_RESOLVE_ON_IPS
734*6236dae4SAndroid Build Coastguard Worker     const
735*6236dae4SAndroid Build Coastguard Worker #endif
736*6236dae4SAndroid Build Coastguard Worker       bool ipnum = FALSE;
737*6236dae4SAndroid Build Coastguard Worker #endif
738*6236dae4SAndroid Build Coastguard Worker 
739*6236dae4SAndroid Build Coastguard Worker     /* notify the resolver start callback */
740*6236dae4SAndroid Build Coastguard Worker     if(data->set.resolver_start) {
741*6236dae4SAndroid Build Coastguard Worker       int st;
742*6236dae4SAndroid Build Coastguard Worker       Curl_set_in_callback(data, TRUE);
743*6236dae4SAndroid Build Coastguard Worker       st = data->set.resolver_start(
744*6236dae4SAndroid Build Coastguard Worker #ifdef USE_CURL_ASYNC
745*6236dae4SAndroid Build Coastguard Worker         data->state.async.resolver,
746*6236dae4SAndroid Build Coastguard Worker #else
747*6236dae4SAndroid Build Coastguard Worker         NULL,
748*6236dae4SAndroid Build Coastguard Worker #endif
749*6236dae4SAndroid Build Coastguard Worker         NULL,
750*6236dae4SAndroid Build Coastguard Worker         data->set.resolver_start_client);
751*6236dae4SAndroid Build Coastguard Worker       Curl_set_in_callback(data, FALSE);
752*6236dae4SAndroid Build Coastguard Worker       if(st)
753*6236dae4SAndroid Build Coastguard Worker         return CURLRESOLV_ERROR;
754*6236dae4SAndroid Build Coastguard Worker     }
755*6236dae4SAndroid Build Coastguard Worker 
756*6236dae4SAndroid Build Coastguard Worker #ifndef USE_RESOLVE_ON_IPS
757*6236dae4SAndroid Build Coastguard Worker     /* First check if this is an IPv4 address string */
758*6236dae4SAndroid Build Coastguard Worker     if(Curl_inet_pton(AF_INET, hostname, &in) > 0) {
759*6236dae4SAndroid Build Coastguard Worker       /* This is a dotted IP address 123.123.123.123-style */
760*6236dae4SAndroid Build Coastguard Worker       addr = Curl_ip2addr(AF_INET, &in, hostname, port);
761*6236dae4SAndroid Build Coastguard Worker       if(!addr)
762*6236dae4SAndroid Build Coastguard Worker         return CURLRESOLV_ERROR;
763*6236dae4SAndroid Build Coastguard Worker     }
764*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
765*6236dae4SAndroid Build Coastguard Worker     else {
766*6236dae4SAndroid Build Coastguard Worker       struct in6_addr in6;
767*6236dae4SAndroid Build Coastguard Worker       /* check if this is an IPv6 address string */
768*6236dae4SAndroid Build Coastguard Worker       if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) {
769*6236dae4SAndroid Build Coastguard Worker         /* This is an IPv6 address literal */
770*6236dae4SAndroid Build Coastguard Worker         addr = Curl_ip2addr(AF_INET6, &in6, hostname, port);
771*6236dae4SAndroid Build Coastguard Worker         if(!addr)
772*6236dae4SAndroid Build Coastguard Worker           return CURLRESOLV_ERROR;
773*6236dae4SAndroid Build Coastguard Worker       }
774*6236dae4SAndroid Build Coastguard Worker     }
775*6236dae4SAndroid Build Coastguard Worker #endif /* USE_IPV6 */
776*6236dae4SAndroid Build Coastguard Worker 
777*6236dae4SAndroid Build Coastguard Worker #else /* if USE_RESOLVE_ON_IPS */
778*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_DOH
779*6236dae4SAndroid Build Coastguard Worker     /* First check if this is an IPv4 address string */
780*6236dae4SAndroid Build Coastguard Worker     if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
781*6236dae4SAndroid Build Coastguard Worker       /* This is a dotted IP address 123.123.123.123-style */
782*6236dae4SAndroid Build Coastguard Worker       ipnum = TRUE;
783*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
784*6236dae4SAndroid Build Coastguard Worker     else {
785*6236dae4SAndroid Build Coastguard Worker       struct in6_addr in6;
786*6236dae4SAndroid Build Coastguard Worker       /* check if this is an IPv6 address string */
787*6236dae4SAndroid Build Coastguard Worker       if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0)
788*6236dae4SAndroid Build Coastguard Worker         /* This is an IPv6 address literal */
789*6236dae4SAndroid Build Coastguard Worker         ipnum = TRUE;
790*6236dae4SAndroid Build Coastguard Worker     }
791*6236dae4SAndroid Build Coastguard Worker #endif /* USE_IPV6 */
792*6236dae4SAndroid Build Coastguard Worker #endif /* CURL_DISABLE_DOH */
793*6236dae4SAndroid Build Coastguard Worker 
794*6236dae4SAndroid Build Coastguard Worker #endif /* !USE_RESOLVE_ON_IPS */
795*6236dae4SAndroid Build Coastguard Worker 
796*6236dae4SAndroid Build Coastguard Worker     if(!addr) {
797*6236dae4SAndroid Build Coastguard Worker       if(conn->ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data))
798*6236dae4SAndroid Build Coastguard Worker         return CURLRESOLV_ERROR;
799*6236dae4SAndroid Build Coastguard Worker 
800*6236dae4SAndroid Build Coastguard Worker       if(strcasecompare(hostname, "localhost") ||
801*6236dae4SAndroid Build Coastguard Worker          tailmatch(hostname, ".localhost"))
802*6236dae4SAndroid Build Coastguard Worker         addr = get_localhost(port, hostname);
803*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_DOH
804*6236dae4SAndroid Build Coastguard Worker       else if(allowDOH && data->set.doh && !ipnum)
805*6236dae4SAndroid Build Coastguard Worker         addr = Curl_doh(data, hostname, port, &respwait);
806*6236dae4SAndroid Build Coastguard Worker #endif
807*6236dae4SAndroid Build Coastguard Worker       else {
808*6236dae4SAndroid Build Coastguard Worker         /* Check what IP specifics the app has requested and if we can provide
809*6236dae4SAndroid Build Coastguard Worker          * it. If not, bail out. */
810*6236dae4SAndroid Build Coastguard Worker         if(!Curl_ipvalid(data, conn))
811*6236dae4SAndroid Build Coastguard Worker           return CURLRESOLV_ERROR;
812*6236dae4SAndroid Build Coastguard Worker         /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
813*6236dae4SAndroid Build Coastguard Worker            non-zero value indicating that we need to wait for the response to
814*6236dae4SAndroid Build Coastguard Worker            the resolve call */
815*6236dae4SAndroid Build Coastguard Worker         addr = Curl_getaddrinfo(data, hostname, port, &respwait);
816*6236dae4SAndroid Build Coastguard Worker       }
817*6236dae4SAndroid Build Coastguard Worker     }
818*6236dae4SAndroid Build Coastguard Worker     if(!addr) {
819*6236dae4SAndroid Build Coastguard Worker       if(respwait) {
820*6236dae4SAndroid Build Coastguard Worker         /* the response to our resolve call will come asynchronously at
821*6236dae4SAndroid Build Coastguard Worker            a later time, good or bad */
822*6236dae4SAndroid Build Coastguard Worker         /* First, check that we have not received the info by now */
823*6236dae4SAndroid Build Coastguard Worker         result = Curl_resolv_check(data, &dns);
824*6236dae4SAndroid Build Coastguard Worker         if(result) /* error detected */
825*6236dae4SAndroid Build Coastguard Worker           return CURLRESOLV_ERROR;
826*6236dae4SAndroid Build Coastguard Worker         if(dns)
827*6236dae4SAndroid Build Coastguard Worker           rc = CURLRESOLV_RESOLVED; /* pointer provided */
828*6236dae4SAndroid Build Coastguard Worker         else
829*6236dae4SAndroid Build Coastguard Worker           rc = CURLRESOLV_PENDING; /* no info yet */
830*6236dae4SAndroid Build Coastguard Worker       }
831*6236dae4SAndroid Build Coastguard Worker     }
832*6236dae4SAndroid Build Coastguard Worker     else {
833*6236dae4SAndroid Build Coastguard Worker       if(data->share)
834*6236dae4SAndroid Build Coastguard Worker         Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
835*6236dae4SAndroid Build Coastguard Worker 
836*6236dae4SAndroid Build Coastguard Worker       /* we got a response, store it in the cache */
837*6236dae4SAndroid Build Coastguard Worker       dns = Curl_cache_addr(data, addr, hostname, 0, port, FALSE);
838*6236dae4SAndroid Build Coastguard Worker 
839*6236dae4SAndroid Build Coastguard Worker       if(data->share)
840*6236dae4SAndroid Build Coastguard Worker         Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
841*6236dae4SAndroid Build Coastguard Worker 
842*6236dae4SAndroid Build Coastguard Worker       if(!dns)
843*6236dae4SAndroid Build Coastguard Worker         /* returned failure, bail out nicely */
844*6236dae4SAndroid Build Coastguard Worker         Curl_freeaddrinfo(addr);
845*6236dae4SAndroid Build Coastguard Worker       else {
846*6236dae4SAndroid Build Coastguard Worker         rc = CURLRESOLV_RESOLVED;
847*6236dae4SAndroid Build Coastguard Worker         show_resolve_info(data, dns);
848*6236dae4SAndroid Build Coastguard Worker       }
849*6236dae4SAndroid Build Coastguard Worker     }
850*6236dae4SAndroid Build Coastguard Worker   }
851*6236dae4SAndroid Build Coastguard Worker 
852*6236dae4SAndroid Build Coastguard Worker   *entry = dns;
853*6236dae4SAndroid Build Coastguard Worker 
854*6236dae4SAndroid Build Coastguard Worker   return rc;
855*6236dae4SAndroid Build Coastguard Worker }
856*6236dae4SAndroid Build Coastguard Worker 
857*6236dae4SAndroid Build Coastguard Worker #ifdef USE_ALARM_TIMEOUT
858*6236dae4SAndroid Build Coastguard Worker /*
859*6236dae4SAndroid Build Coastguard Worker  * This signal handler jumps back into the main libcurl code and continues
860*6236dae4SAndroid Build Coastguard Worker  * execution. This effectively causes the remainder of the application to run
861*6236dae4SAndroid Build Coastguard Worker  * within a signal handler which is nonportable and could lead to problems.
862*6236dae4SAndroid Build Coastguard Worker  */
863*6236dae4SAndroid Build Coastguard Worker CURL_NORETURN static
alarmfunc(int sig)864*6236dae4SAndroid Build Coastguard Worker void alarmfunc(int sig)
865*6236dae4SAndroid Build Coastguard Worker {
866*6236dae4SAndroid Build Coastguard Worker   (void)sig;
867*6236dae4SAndroid Build Coastguard Worker   siglongjmp(curl_jmpenv, 1);
868*6236dae4SAndroid Build Coastguard Worker }
869*6236dae4SAndroid Build Coastguard Worker #endif /* USE_ALARM_TIMEOUT */
870*6236dae4SAndroid Build Coastguard Worker 
871*6236dae4SAndroid Build Coastguard Worker /*
872*6236dae4SAndroid Build Coastguard Worker  * Curl_resolv_timeout() is the same as Curl_resolv() but specifies a
873*6236dae4SAndroid Build Coastguard Worker  * timeout. This function might return immediately if we are using asynch
874*6236dae4SAndroid Build Coastguard Worker  * resolves. See the return codes.
875*6236dae4SAndroid Build Coastguard Worker  *
876*6236dae4SAndroid Build Coastguard Worker  * The cache entry we return will get its 'inuse' counter increased when this
877*6236dae4SAndroid Build Coastguard Worker  * function is used. You MUST call Curl_resolv_unlink() later (when you are
878*6236dae4SAndroid Build Coastguard Worker  * done using this struct) to decrease the reference counter again.
879*6236dae4SAndroid Build Coastguard Worker  *
880*6236dae4SAndroid Build Coastguard Worker  * If built with a synchronous resolver and use of signals is not
881*6236dae4SAndroid Build Coastguard Worker  * disabled by the application, then a nonzero timeout will cause a
882*6236dae4SAndroid Build Coastguard Worker  * timeout after the specified number of milliseconds. Otherwise, timeout
883*6236dae4SAndroid Build Coastguard Worker  * is ignored.
884*6236dae4SAndroid Build Coastguard Worker  *
885*6236dae4SAndroid Build Coastguard Worker  * Return codes:
886*6236dae4SAndroid Build Coastguard Worker  *
887*6236dae4SAndroid Build Coastguard Worker  * CURLRESOLV_TIMEDOUT(-2) = warning, time too short or previous alarm expired
888*6236dae4SAndroid Build Coastguard Worker  * CURLRESOLV_ERROR   (-1) = error, no pointer
889*6236dae4SAndroid Build Coastguard Worker  * CURLRESOLV_RESOLVED (0) = OK, pointer provided
890*6236dae4SAndroid Build Coastguard Worker  * CURLRESOLV_PENDING  (1) = waiting for response, no pointer
891*6236dae4SAndroid Build Coastguard Worker  */
892*6236dae4SAndroid Build Coastguard Worker 
Curl_resolv_timeout(struct Curl_easy * data,const char * hostname,int port,struct Curl_dns_entry ** entry,timediff_t timeoutms)893*6236dae4SAndroid Build Coastguard Worker enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
894*6236dae4SAndroid Build Coastguard Worker                                    const char *hostname,
895*6236dae4SAndroid Build Coastguard Worker                                    int port,
896*6236dae4SAndroid Build Coastguard Worker                                    struct Curl_dns_entry **entry,
897*6236dae4SAndroid Build Coastguard Worker                                    timediff_t timeoutms)
898*6236dae4SAndroid Build Coastguard Worker {
899*6236dae4SAndroid Build Coastguard Worker #ifdef USE_ALARM_TIMEOUT
900*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SIGACTION
901*6236dae4SAndroid Build Coastguard Worker   struct sigaction keep_sigact;   /* store the old struct here */
902*6236dae4SAndroid Build Coastguard Worker   volatile bool keep_copysig = FALSE; /* whether old sigact has been saved */
903*6236dae4SAndroid Build Coastguard Worker   struct sigaction sigact;
904*6236dae4SAndroid Build Coastguard Worker #else
905*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SIGNAL
906*6236dae4SAndroid Build Coastguard Worker   void (*keep_sigact)(int);       /* store the old handler here */
907*6236dae4SAndroid Build Coastguard Worker #endif /* HAVE_SIGNAL */
908*6236dae4SAndroid Build Coastguard Worker #endif /* HAVE_SIGACTION */
909*6236dae4SAndroid Build Coastguard Worker   volatile long timeout;
910*6236dae4SAndroid Build Coastguard Worker   volatile unsigned int prev_alarm = 0;
911*6236dae4SAndroid Build Coastguard Worker #endif /* USE_ALARM_TIMEOUT */
912*6236dae4SAndroid Build Coastguard Worker   enum resolve_t rc;
913*6236dae4SAndroid Build Coastguard Worker 
914*6236dae4SAndroid Build Coastguard Worker   *entry = NULL;
915*6236dae4SAndroid Build Coastguard Worker 
916*6236dae4SAndroid Build Coastguard Worker   if(timeoutms < 0)
917*6236dae4SAndroid Build Coastguard Worker     /* got an already expired timeout */
918*6236dae4SAndroid Build Coastguard Worker     return CURLRESOLV_TIMEDOUT;
919*6236dae4SAndroid Build Coastguard Worker 
920*6236dae4SAndroid Build Coastguard Worker #ifdef USE_ALARM_TIMEOUT
921*6236dae4SAndroid Build Coastguard Worker   if(data->set.no_signal)
922*6236dae4SAndroid Build Coastguard Worker     /* Ignore the timeout when signals are disabled */
923*6236dae4SAndroid Build Coastguard Worker     timeout = 0;
924*6236dae4SAndroid Build Coastguard Worker   else
925*6236dae4SAndroid Build Coastguard Worker     timeout = (timeoutms > LONG_MAX) ? LONG_MAX : (long)timeoutms;
926*6236dae4SAndroid Build Coastguard Worker 
927*6236dae4SAndroid Build Coastguard Worker   if(!timeout)
928*6236dae4SAndroid Build Coastguard Worker     /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
929*6236dae4SAndroid Build Coastguard Worker     return Curl_resolv(data, hostname, port, TRUE, entry);
930*6236dae4SAndroid Build Coastguard Worker 
931*6236dae4SAndroid Build Coastguard Worker   if(timeout < 1000) {
932*6236dae4SAndroid Build Coastguard Worker     /* The alarm() function only provides integer second resolution, so if
933*6236dae4SAndroid Build Coastguard Worker        we want to wait less than one second we must bail out already now. */
934*6236dae4SAndroid Build Coastguard Worker     failf(data,
935*6236dae4SAndroid Build Coastguard Worker         "remaining timeout of %ld too small to resolve via SIGALRM method",
936*6236dae4SAndroid Build Coastguard Worker         timeout);
937*6236dae4SAndroid Build Coastguard Worker     return CURLRESOLV_TIMEDOUT;
938*6236dae4SAndroid Build Coastguard Worker   }
939*6236dae4SAndroid Build Coastguard Worker   /* This allows us to time-out from the name resolver, as the timeout
940*6236dae4SAndroid Build Coastguard Worker      will generate a signal and we will siglongjmp() from that here.
941*6236dae4SAndroid Build Coastguard Worker      This technique has problems (see alarmfunc).
942*6236dae4SAndroid Build Coastguard Worker      This should be the last thing we do before calling Curl_resolv(),
943*6236dae4SAndroid Build Coastguard Worker      as otherwise we would have to worry about variables that get modified
944*6236dae4SAndroid Build Coastguard Worker      before we invoke Curl_resolv() (and thus use "volatile"). */
945*6236dae4SAndroid Build Coastguard Worker   curl_simple_lock_lock(&curl_jmpenv_lock);
946*6236dae4SAndroid Build Coastguard Worker 
947*6236dae4SAndroid Build Coastguard Worker   if(sigsetjmp(curl_jmpenv, 1)) {
948*6236dae4SAndroid Build Coastguard Worker     /* this is coming from a siglongjmp() after an alarm signal */
949*6236dae4SAndroid Build Coastguard Worker     failf(data, "name lookup timed out");
950*6236dae4SAndroid Build Coastguard Worker     rc = CURLRESOLV_ERROR;
951*6236dae4SAndroid Build Coastguard Worker     goto clean_up;
952*6236dae4SAndroid Build Coastguard Worker   }
953*6236dae4SAndroid Build Coastguard Worker   else {
954*6236dae4SAndroid Build Coastguard Worker     /*************************************************************
955*6236dae4SAndroid Build Coastguard Worker      * Set signal handler to catch SIGALRM
956*6236dae4SAndroid Build Coastguard Worker      * Store the old value to be able to set it back later!
957*6236dae4SAndroid Build Coastguard Worker      *************************************************************/
958*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SIGACTION
959*6236dae4SAndroid Build Coastguard Worker     sigaction(SIGALRM, NULL, &sigact);
960*6236dae4SAndroid Build Coastguard Worker     keep_sigact = sigact;
961*6236dae4SAndroid Build Coastguard Worker     keep_copysig = TRUE; /* yes, we have a copy */
962*6236dae4SAndroid Build Coastguard Worker     sigact.sa_handler = alarmfunc;
963*6236dae4SAndroid Build Coastguard Worker #ifdef SA_RESTART
964*6236dae4SAndroid Build Coastguard Worker     /* HP-UX does not have SA_RESTART but defaults to that behavior! */
965*6236dae4SAndroid Build Coastguard Worker     sigact.sa_flags &= ~SA_RESTART;
966*6236dae4SAndroid Build Coastguard Worker #endif
967*6236dae4SAndroid Build Coastguard Worker     /* now set the new struct */
968*6236dae4SAndroid Build Coastguard Worker     sigaction(SIGALRM, &sigact, NULL);
969*6236dae4SAndroid Build Coastguard Worker #else /* HAVE_SIGACTION */
970*6236dae4SAndroid Build Coastguard Worker     /* no sigaction(), revert to the much lamer signal() */
971*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SIGNAL
972*6236dae4SAndroid Build Coastguard Worker     keep_sigact = signal(SIGALRM, alarmfunc);
973*6236dae4SAndroid Build Coastguard Worker #endif
974*6236dae4SAndroid Build Coastguard Worker #endif /* HAVE_SIGACTION */
975*6236dae4SAndroid Build Coastguard Worker 
976*6236dae4SAndroid Build Coastguard Worker     /* alarm() makes a signal get sent when the timeout fires off, and that
977*6236dae4SAndroid Build Coastguard Worker        will abort system calls */
978*6236dae4SAndroid Build Coastguard Worker     prev_alarm = alarm(curlx_sltoui(timeout/1000L));
979*6236dae4SAndroid Build Coastguard Worker   }
980*6236dae4SAndroid Build Coastguard Worker 
981*6236dae4SAndroid Build Coastguard Worker #else
982*6236dae4SAndroid Build Coastguard Worker #ifndef CURLRES_ASYNCH
983*6236dae4SAndroid Build Coastguard Worker   if(timeoutms)
984*6236dae4SAndroid Build Coastguard Worker     infof(data, "timeout on name lookup is not supported");
985*6236dae4SAndroid Build Coastguard Worker #else
986*6236dae4SAndroid Build Coastguard Worker   (void)timeoutms; /* timeoutms not used with an async resolver */
987*6236dae4SAndroid Build Coastguard Worker #endif
988*6236dae4SAndroid Build Coastguard Worker #endif /* USE_ALARM_TIMEOUT */
989*6236dae4SAndroid Build Coastguard Worker 
990*6236dae4SAndroid Build Coastguard Worker   /* Perform the actual name resolution. This might be interrupted by an
991*6236dae4SAndroid Build Coastguard Worker    * alarm if it takes too long.
992*6236dae4SAndroid Build Coastguard Worker    */
993*6236dae4SAndroid Build Coastguard Worker   rc = Curl_resolv(data, hostname, port, TRUE, entry);
994*6236dae4SAndroid Build Coastguard Worker 
995*6236dae4SAndroid Build Coastguard Worker #ifdef USE_ALARM_TIMEOUT
996*6236dae4SAndroid Build Coastguard Worker clean_up:
997*6236dae4SAndroid Build Coastguard Worker 
998*6236dae4SAndroid Build Coastguard Worker   if(!prev_alarm)
999*6236dae4SAndroid Build Coastguard Worker     /* deactivate a possibly active alarm before uninstalling the handler */
1000*6236dae4SAndroid Build Coastguard Worker     alarm(0);
1001*6236dae4SAndroid Build Coastguard Worker 
1002*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SIGACTION
1003*6236dae4SAndroid Build Coastguard Worker   if(keep_copysig) {
1004*6236dae4SAndroid Build Coastguard Worker     /* we got a struct as it looked before, now put that one back nice
1005*6236dae4SAndroid Build Coastguard Worker        and clean */
1006*6236dae4SAndroid Build Coastguard Worker     sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */
1007*6236dae4SAndroid Build Coastguard Worker   }
1008*6236dae4SAndroid Build Coastguard Worker #else
1009*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SIGNAL
1010*6236dae4SAndroid Build Coastguard Worker   /* restore the previous SIGALRM handler */
1011*6236dae4SAndroid Build Coastguard Worker   signal(SIGALRM, keep_sigact);
1012*6236dae4SAndroid Build Coastguard Worker #endif
1013*6236dae4SAndroid Build Coastguard Worker #endif /* HAVE_SIGACTION */
1014*6236dae4SAndroid Build Coastguard Worker 
1015*6236dae4SAndroid Build Coastguard Worker   curl_simple_lock_unlock(&curl_jmpenv_lock);
1016*6236dae4SAndroid Build Coastguard Worker 
1017*6236dae4SAndroid Build Coastguard Worker   /* switch back the alarm() to either zero or to what it was before minus
1018*6236dae4SAndroid Build Coastguard Worker      the time we spent until now! */
1019*6236dae4SAndroid Build Coastguard Worker   if(prev_alarm) {
1020*6236dae4SAndroid Build Coastguard Worker     /* there was an alarm() set before us, now put it back */
1021*6236dae4SAndroid Build Coastguard Worker     timediff_t elapsed_secs = Curl_timediff(Curl_now(),
1022*6236dae4SAndroid Build Coastguard Worker                                             data->conn->created) / 1000;
1023*6236dae4SAndroid Build Coastguard Worker 
1024*6236dae4SAndroid Build Coastguard Worker     /* the alarm period is counted in even number of seconds */
1025*6236dae4SAndroid Build Coastguard Worker     unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs);
1026*6236dae4SAndroid Build Coastguard Worker 
1027*6236dae4SAndroid Build Coastguard Worker     if(!alarm_set ||
1028*6236dae4SAndroid Build Coastguard Worker        ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
1029*6236dae4SAndroid Build Coastguard Worker       /* if the alarm time-left reached zero or turned "negative" (counted
1030*6236dae4SAndroid Build Coastguard Worker          with unsigned values), we should fire off a SIGALRM here, but we
1031*6236dae4SAndroid Build Coastguard Worker          will not, and zero would be to switch it off so we never set it to
1032*6236dae4SAndroid Build Coastguard Worker          less than 1! */
1033*6236dae4SAndroid Build Coastguard Worker       alarm(1);
1034*6236dae4SAndroid Build Coastguard Worker       rc = CURLRESOLV_TIMEDOUT;
1035*6236dae4SAndroid Build Coastguard Worker       failf(data, "Previous alarm fired off");
1036*6236dae4SAndroid Build Coastguard Worker     }
1037*6236dae4SAndroid Build Coastguard Worker     else
1038*6236dae4SAndroid Build Coastguard Worker       alarm((unsigned int)alarm_set);
1039*6236dae4SAndroid Build Coastguard Worker   }
1040*6236dae4SAndroid Build Coastguard Worker #endif /* USE_ALARM_TIMEOUT */
1041*6236dae4SAndroid Build Coastguard Worker 
1042*6236dae4SAndroid Build Coastguard Worker   return rc;
1043*6236dae4SAndroid Build Coastguard Worker }
1044*6236dae4SAndroid Build Coastguard Worker 
1045*6236dae4SAndroid Build Coastguard Worker /*
1046*6236dae4SAndroid Build Coastguard Worker  * Curl_resolv_unlink() releases a reference to the given cached DNS entry.
1047*6236dae4SAndroid Build Coastguard Worker  * When the reference count reaches 0, the entry is destroyed. It is important
1048*6236dae4SAndroid Build Coastguard Worker  * that only one unlink is made for each Curl_resolv() call.
1049*6236dae4SAndroid Build Coastguard Worker  *
1050*6236dae4SAndroid Build Coastguard Worker  * May be called with 'data' == NULL for global cache.
1051*6236dae4SAndroid Build Coastguard Worker  */
Curl_resolv_unlink(struct Curl_easy * data,struct Curl_dns_entry ** pdns)1052*6236dae4SAndroid Build Coastguard Worker void Curl_resolv_unlink(struct Curl_easy *data, struct Curl_dns_entry **pdns)
1053*6236dae4SAndroid Build Coastguard Worker {
1054*6236dae4SAndroid Build Coastguard Worker   struct Curl_dns_entry *dns = *pdns;
1055*6236dae4SAndroid Build Coastguard Worker   *pdns = NULL;
1056*6236dae4SAndroid Build Coastguard Worker   if(data && data->share)
1057*6236dae4SAndroid Build Coastguard Worker     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
1058*6236dae4SAndroid Build Coastguard Worker 
1059*6236dae4SAndroid Build Coastguard Worker   hostcache_unlink_entry(dns);
1060*6236dae4SAndroid Build Coastguard Worker 
1061*6236dae4SAndroid Build Coastguard Worker   if(data && data->share)
1062*6236dae4SAndroid Build Coastguard Worker     Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
1063*6236dae4SAndroid Build Coastguard Worker }
1064*6236dae4SAndroid Build Coastguard Worker 
1065*6236dae4SAndroid Build Coastguard Worker /*
1066*6236dae4SAndroid Build Coastguard Worker  * File-internal: release cache dns entry reference, free if inuse drops to 0
1067*6236dae4SAndroid Build Coastguard Worker  */
hostcache_unlink_entry(void * entry)1068*6236dae4SAndroid Build Coastguard Worker static void hostcache_unlink_entry(void *entry)
1069*6236dae4SAndroid Build Coastguard Worker {
1070*6236dae4SAndroid Build Coastguard Worker   struct Curl_dns_entry *dns = (struct Curl_dns_entry *) entry;
1071*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(dns && (dns->refcount > 0));
1072*6236dae4SAndroid Build Coastguard Worker 
1073*6236dae4SAndroid Build Coastguard Worker   dns->refcount--;
1074*6236dae4SAndroid Build Coastguard Worker   if(dns->refcount == 0) {
1075*6236dae4SAndroid Build Coastguard Worker     Curl_freeaddrinfo(dns->addr);
1076*6236dae4SAndroid Build Coastguard Worker #ifdef USE_HTTPSRR
1077*6236dae4SAndroid Build Coastguard Worker     if(dns->hinfo) {
1078*6236dae4SAndroid Build Coastguard Worker       if(dns->hinfo->target)
1079*6236dae4SAndroid Build Coastguard Worker         free(dns->hinfo->target);
1080*6236dae4SAndroid Build Coastguard Worker       if(dns->hinfo->alpns)
1081*6236dae4SAndroid Build Coastguard Worker         free(dns->hinfo->alpns);
1082*6236dae4SAndroid Build Coastguard Worker       if(dns->hinfo->ipv4hints)
1083*6236dae4SAndroid Build Coastguard Worker         free(dns->hinfo->ipv4hints);
1084*6236dae4SAndroid Build Coastguard Worker       if(dns->hinfo->echconfiglist)
1085*6236dae4SAndroid Build Coastguard Worker         free(dns->hinfo->echconfiglist);
1086*6236dae4SAndroid Build Coastguard Worker       if(dns->hinfo->ipv6hints)
1087*6236dae4SAndroid Build Coastguard Worker         free(dns->hinfo->ipv6hints);
1088*6236dae4SAndroid Build Coastguard Worker       if(dns->hinfo->val)
1089*6236dae4SAndroid Build Coastguard Worker         free(dns->hinfo->val);
1090*6236dae4SAndroid Build Coastguard Worker       free(dns->hinfo);
1091*6236dae4SAndroid Build Coastguard Worker     }
1092*6236dae4SAndroid Build Coastguard Worker #endif
1093*6236dae4SAndroid Build Coastguard Worker     free(dns);
1094*6236dae4SAndroid Build Coastguard Worker   }
1095*6236dae4SAndroid Build Coastguard Worker }
1096*6236dae4SAndroid Build Coastguard Worker 
1097*6236dae4SAndroid Build Coastguard Worker /*
1098*6236dae4SAndroid Build Coastguard Worker  * Curl_init_dnscache() inits a new DNS cache.
1099*6236dae4SAndroid Build Coastguard Worker  */
Curl_init_dnscache(struct Curl_hash * hash,size_t size)1100*6236dae4SAndroid Build Coastguard Worker void Curl_init_dnscache(struct Curl_hash *hash, size_t size)
1101*6236dae4SAndroid Build Coastguard Worker {
1102*6236dae4SAndroid Build Coastguard Worker   Curl_hash_init(hash, size, Curl_hash_str, Curl_str_key_compare,
1103*6236dae4SAndroid Build Coastguard Worker                  hostcache_unlink_entry);
1104*6236dae4SAndroid Build Coastguard Worker }
1105*6236dae4SAndroid Build Coastguard Worker 
1106*6236dae4SAndroid Build Coastguard Worker /*
1107*6236dae4SAndroid Build Coastguard Worker  * Curl_hostcache_clean()
1108*6236dae4SAndroid Build Coastguard Worker  *
1109*6236dae4SAndroid Build Coastguard Worker  * This _can_ be called with 'data' == NULL but then of course no locking
1110*6236dae4SAndroid Build Coastguard Worker  * can be done!
1111*6236dae4SAndroid Build Coastguard Worker  */
1112*6236dae4SAndroid Build Coastguard Worker 
Curl_hostcache_clean(struct Curl_easy * data,struct Curl_hash * hash)1113*6236dae4SAndroid Build Coastguard Worker void Curl_hostcache_clean(struct Curl_easy *data,
1114*6236dae4SAndroid Build Coastguard Worker                           struct Curl_hash *hash)
1115*6236dae4SAndroid Build Coastguard Worker {
1116*6236dae4SAndroid Build Coastguard Worker   if(data && data->share)
1117*6236dae4SAndroid Build Coastguard Worker     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
1118*6236dae4SAndroid Build Coastguard Worker 
1119*6236dae4SAndroid Build Coastguard Worker   Curl_hash_clean(hash);
1120*6236dae4SAndroid Build Coastguard Worker 
1121*6236dae4SAndroid Build Coastguard Worker   if(data && data->share)
1122*6236dae4SAndroid Build Coastguard Worker     Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
1123*6236dae4SAndroid Build Coastguard Worker }
1124*6236dae4SAndroid Build Coastguard Worker 
1125*6236dae4SAndroid Build Coastguard Worker 
Curl_loadhostpairs(struct Curl_easy * data)1126*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_loadhostpairs(struct Curl_easy *data)
1127*6236dae4SAndroid Build Coastguard Worker {
1128*6236dae4SAndroid Build Coastguard Worker   struct curl_slist *hostp;
1129*6236dae4SAndroid Build Coastguard Worker   char *host_end;
1130*6236dae4SAndroid Build Coastguard Worker 
1131*6236dae4SAndroid Build Coastguard Worker   /* Default is no wildcard found */
1132*6236dae4SAndroid Build Coastguard Worker   data->state.wildcard_resolve = FALSE;
1133*6236dae4SAndroid Build Coastguard Worker 
1134*6236dae4SAndroid Build Coastguard Worker   for(hostp = data->state.resolve; hostp; hostp = hostp->next) {
1135*6236dae4SAndroid Build Coastguard Worker     char entry_id[MAX_HOSTCACHE_LEN];
1136*6236dae4SAndroid Build Coastguard Worker     if(!hostp->data)
1137*6236dae4SAndroid Build Coastguard Worker       continue;
1138*6236dae4SAndroid Build Coastguard Worker     if(hostp->data[0] == '-') {
1139*6236dae4SAndroid Build Coastguard Worker       unsigned long num = 0;
1140*6236dae4SAndroid Build Coastguard Worker       size_t entry_len;
1141*6236dae4SAndroid Build Coastguard Worker       size_t hlen = 0;
1142*6236dae4SAndroid Build Coastguard Worker       host_end = strchr(&hostp->data[1], ':');
1143*6236dae4SAndroid Build Coastguard Worker 
1144*6236dae4SAndroid Build Coastguard Worker       if(host_end) {
1145*6236dae4SAndroid Build Coastguard Worker         hlen = host_end - &hostp->data[1];
1146*6236dae4SAndroid Build Coastguard Worker         num = strtoul(++host_end, NULL, 10);
1147*6236dae4SAndroid Build Coastguard Worker         if(!hlen || (num > 0xffff))
1148*6236dae4SAndroid Build Coastguard Worker           host_end = NULL;
1149*6236dae4SAndroid Build Coastguard Worker       }
1150*6236dae4SAndroid Build Coastguard Worker       if(!host_end) {
1151*6236dae4SAndroid Build Coastguard Worker         infof(data, "Bad syntax CURLOPT_RESOLVE removal entry '%s'",
1152*6236dae4SAndroid Build Coastguard Worker               hostp->data);
1153*6236dae4SAndroid Build Coastguard Worker         continue;
1154*6236dae4SAndroid Build Coastguard Worker       }
1155*6236dae4SAndroid Build Coastguard Worker       /* Create an entry id, based upon the hostname and port */
1156*6236dae4SAndroid Build Coastguard Worker       entry_len = create_hostcache_id(&hostp->data[1], hlen, (int)num,
1157*6236dae4SAndroid Build Coastguard Worker                                       entry_id, sizeof(entry_id));
1158*6236dae4SAndroid Build Coastguard Worker       if(data->share)
1159*6236dae4SAndroid Build Coastguard Worker         Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
1160*6236dae4SAndroid Build Coastguard Worker 
1161*6236dae4SAndroid Build Coastguard Worker       /* delete entry, ignore if it did not exist */
1162*6236dae4SAndroid Build Coastguard Worker       Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
1163*6236dae4SAndroid Build Coastguard Worker 
1164*6236dae4SAndroid Build Coastguard Worker       if(data->share)
1165*6236dae4SAndroid Build Coastguard Worker         Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
1166*6236dae4SAndroid Build Coastguard Worker     }
1167*6236dae4SAndroid Build Coastguard Worker     else {
1168*6236dae4SAndroid Build Coastguard Worker       struct Curl_dns_entry *dns;
1169*6236dae4SAndroid Build Coastguard Worker       struct Curl_addrinfo *head = NULL, *tail = NULL;
1170*6236dae4SAndroid Build Coastguard Worker       size_t entry_len;
1171*6236dae4SAndroid Build Coastguard Worker       char address[64];
1172*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
1173*6236dae4SAndroid Build Coastguard Worker       char *addresses = NULL;
1174*6236dae4SAndroid Build Coastguard Worker #endif
1175*6236dae4SAndroid Build Coastguard Worker       char *addr_begin;
1176*6236dae4SAndroid Build Coastguard Worker       char *addr_end;
1177*6236dae4SAndroid Build Coastguard Worker       char *port_ptr;
1178*6236dae4SAndroid Build Coastguard Worker       int port = 0;
1179*6236dae4SAndroid Build Coastguard Worker       char *end_ptr;
1180*6236dae4SAndroid Build Coastguard Worker       bool permanent = TRUE;
1181*6236dae4SAndroid Build Coastguard Worker       unsigned long tmp_port;
1182*6236dae4SAndroid Build Coastguard Worker       bool error = TRUE;
1183*6236dae4SAndroid Build Coastguard Worker       char *host_begin = hostp->data;
1184*6236dae4SAndroid Build Coastguard Worker       size_t hlen = 0;
1185*6236dae4SAndroid Build Coastguard Worker 
1186*6236dae4SAndroid Build Coastguard Worker       if(host_begin[0] == '+') {
1187*6236dae4SAndroid Build Coastguard Worker         host_begin++;
1188*6236dae4SAndroid Build Coastguard Worker         permanent = FALSE;
1189*6236dae4SAndroid Build Coastguard Worker       }
1190*6236dae4SAndroid Build Coastguard Worker       host_end = strchr(host_begin, ':');
1191*6236dae4SAndroid Build Coastguard Worker       if(!host_end)
1192*6236dae4SAndroid Build Coastguard Worker         goto err;
1193*6236dae4SAndroid Build Coastguard Worker       hlen = host_end - host_begin;
1194*6236dae4SAndroid Build Coastguard Worker 
1195*6236dae4SAndroid Build Coastguard Worker       port_ptr = host_end + 1;
1196*6236dae4SAndroid Build Coastguard Worker       tmp_port = strtoul(port_ptr, &end_ptr, 10);
1197*6236dae4SAndroid Build Coastguard Worker       if(tmp_port > USHRT_MAX || end_ptr == port_ptr || *end_ptr != ':')
1198*6236dae4SAndroid Build Coastguard Worker         goto err;
1199*6236dae4SAndroid Build Coastguard Worker 
1200*6236dae4SAndroid Build Coastguard Worker       port = (int)tmp_port;
1201*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
1202*6236dae4SAndroid Build Coastguard Worker       addresses = end_ptr + 1;
1203*6236dae4SAndroid Build Coastguard Worker #endif
1204*6236dae4SAndroid Build Coastguard Worker 
1205*6236dae4SAndroid Build Coastguard Worker       while(*end_ptr) {
1206*6236dae4SAndroid Build Coastguard Worker         size_t alen;
1207*6236dae4SAndroid Build Coastguard Worker         struct Curl_addrinfo *ai;
1208*6236dae4SAndroid Build Coastguard Worker 
1209*6236dae4SAndroid Build Coastguard Worker         addr_begin = end_ptr + 1;
1210*6236dae4SAndroid Build Coastguard Worker         addr_end = strchr(addr_begin, ',');
1211*6236dae4SAndroid Build Coastguard Worker         if(!addr_end)
1212*6236dae4SAndroid Build Coastguard Worker           addr_end = addr_begin + strlen(addr_begin);
1213*6236dae4SAndroid Build Coastguard Worker         end_ptr = addr_end;
1214*6236dae4SAndroid Build Coastguard Worker 
1215*6236dae4SAndroid Build Coastguard Worker         /* allow IP(v6) address within [brackets] */
1216*6236dae4SAndroid Build Coastguard Worker         if(*addr_begin == '[') {
1217*6236dae4SAndroid Build Coastguard Worker           if(addr_end == addr_begin || *(addr_end - 1) != ']')
1218*6236dae4SAndroid Build Coastguard Worker             goto err;
1219*6236dae4SAndroid Build Coastguard Worker           ++addr_begin;
1220*6236dae4SAndroid Build Coastguard Worker           --addr_end;
1221*6236dae4SAndroid Build Coastguard Worker         }
1222*6236dae4SAndroid Build Coastguard Worker 
1223*6236dae4SAndroid Build Coastguard Worker         alen = addr_end - addr_begin;
1224*6236dae4SAndroid Build Coastguard Worker         if(!alen)
1225*6236dae4SAndroid Build Coastguard Worker           continue;
1226*6236dae4SAndroid Build Coastguard Worker 
1227*6236dae4SAndroid Build Coastguard Worker         if(alen >= sizeof(address))
1228*6236dae4SAndroid Build Coastguard Worker           goto err;
1229*6236dae4SAndroid Build Coastguard Worker 
1230*6236dae4SAndroid Build Coastguard Worker         memcpy(address, addr_begin, alen);
1231*6236dae4SAndroid Build Coastguard Worker         address[alen] = '\0';
1232*6236dae4SAndroid Build Coastguard Worker 
1233*6236dae4SAndroid Build Coastguard Worker #ifndef USE_IPV6
1234*6236dae4SAndroid Build Coastguard Worker         if(strchr(address, ':')) {
1235*6236dae4SAndroid Build Coastguard Worker           infof(data, "Ignoring resolve address '%s', missing IPv6 support.",
1236*6236dae4SAndroid Build Coastguard Worker                 address);
1237*6236dae4SAndroid Build Coastguard Worker           continue;
1238*6236dae4SAndroid Build Coastguard Worker         }
1239*6236dae4SAndroid Build Coastguard Worker #endif
1240*6236dae4SAndroid Build Coastguard Worker 
1241*6236dae4SAndroid Build Coastguard Worker         ai = Curl_str2addr(address, port);
1242*6236dae4SAndroid Build Coastguard Worker         if(!ai) {
1243*6236dae4SAndroid Build Coastguard Worker           infof(data, "Resolve address '%s' found illegal", address);
1244*6236dae4SAndroid Build Coastguard Worker           goto err;
1245*6236dae4SAndroid Build Coastguard Worker         }
1246*6236dae4SAndroid Build Coastguard Worker 
1247*6236dae4SAndroid Build Coastguard Worker         if(tail) {
1248*6236dae4SAndroid Build Coastguard Worker           tail->ai_next = ai;
1249*6236dae4SAndroid Build Coastguard Worker           tail = tail->ai_next;
1250*6236dae4SAndroid Build Coastguard Worker         }
1251*6236dae4SAndroid Build Coastguard Worker         else {
1252*6236dae4SAndroid Build Coastguard Worker           head = tail = ai;
1253*6236dae4SAndroid Build Coastguard Worker         }
1254*6236dae4SAndroid Build Coastguard Worker       }
1255*6236dae4SAndroid Build Coastguard Worker 
1256*6236dae4SAndroid Build Coastguard Worker       if(!head)
1257*6236dae4SAndroid Build Coastguard Worker         goto err;
1258*6236dae4SAndroid Build Coastguard Worker 
1259*6236dae4SAndroid Build Coastguard Worker       error = FALSE;
1260*6236dae4SAndroid Build Coastguard Worker err:
1261*6236dae4SAndroid Build Coastguard Worker       if(error) {
1262*6236dae4SAndroid Build Coastguard Worker         failf(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'",
1263*6236dae4SAndroid Build Coastguard Worker               hostp->data);
1264*6236dae4SAndroid Build Coastguard Worker         Curl_freeaddrinfo(head);
1265*6236dae4SAndroid Build Coastguard Worker         return CURLE_SETOPT_OPTION_SYNTAX;
1266*6236dae4SAndroid Build Coastguard Worker       }
1267*6236dae4SAndroid Build Coastguard Worker 
1268*6236dae4SAndroid Build Coastguard Worker       /* Create an entry id, based upon the hostname and port */
1269*6236dae4SAndroid Build Coastguard Worker       entry_len = create_hostcache_id(host_begin, hlen, port,
1270*6236dae4SAndroid Build Coastguard Worker                                       entry_id, sizeof(entry_id));
1271*6236dae4SAndroid Build Coastguard Worker 
1272*6236dae4SAndroid Build Coastguard Worker       if(data->share)
1273*6236dae4SAndroid Build Coastguard Worker         Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
1274*6236dae4SAndroid Build Coastguard Worker 
1275*6236dae4SAndroid Build Coastguard Worker       /* See if it is already in our dns cache */
1276*6236dae4SAndroid Build Coastguard Worker       dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
1277*6236dae4SAndroid Build Coastguard Worker 
1278*6236dae4SAndroid Build Coastguard Worker       if(dns) {
1279*6236dae4SAndroid Build Coastguard Worker         infof(data, "RESOLVE %.*s:%d - old addresses discarded",
1280*6236dae4SAndroid Build Coastguard Worker               (int)hlen, host_begin, port);
1281*6236dae4SAndroid Build Coastguard Worker         /* delete old entry, there are two reasons for this
1282*6236dae4SAndroid Build Coastguard Worker          1. old entry may have different addresses.
1283*6236dae4SAndroid Build Coastguard Worker          2. even if entry with correct addresses is already in the cache,
1284*6236dae4SAndroid Build Coastguard Worker             but if it is close to expire, then by the time next http
1285*6236dae4SAndroid Build Coastguard Worker             request is made, it can get expired and pruned because old
1286*6236dae4SAndroid Build Coastguard Worker             entry is not necessarily marked as permanent.
1287*6236dae4SAndroid Build Coastguard Worker          3. when adding a non-permanent entry, we want it to remove and
1288*6236dae4SAndroid Build Coastguard Worker             replace an existing permanent entry.
1289*6236dae4SAndroid Build Coastguard Worker          4. when adding a non-permanent entry, we want it to get a "fresh"
1290*6236dae4SAndroid Build Coastguard Worker             timeout that starts _now_. */
1291*6236dae4SAndroid Build Coastguard Worker 
1292*6236dae4SAndroid Build Coastguard Worker         Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
1293*6236dae4SAndroid Build Coastguard Worker       }
1294*6236dae4SAndroid Build Coastguard Worker 
1295*6236dae4SAndroid Build Coastguard Worker       /* put this new host in the cache */
1296*6236dae4SAndroid Build Coastguard Worker       dns = Curl_cache_addr(data, head, host_begin, hlen, port, permanent);
1297*6236dae4SAndroid Build Coastguard Worker       if(dns) {
1298*6236dae4SAndroid Build Coastguard Worker         /* release the returned reference; the cache itself will keep the
1299*6236dae4SAndroid Build Coastguard Worker          * entry alive: */
1300*6236dae4SAndroid Build Coastguard Worker         dns->refcount--;
1301*6236dae4SAndroid Build Coastguard Worker       }
1302*6236dae4SAndroid Build Coastguard Worker 
1303*6236dae4SAndroid Build Coastguard Worker       if(data->share)
1304*6236dae4SAndroid Build Coastguard Worker         Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
1305*6236dae4SAndroid Build Coastguard Worker 
1306*6236dae4SAndroid Build Coastguard Worker       if(!dns) {
1307*6236dae4SAndroid Build Coastguard Worker         Curl_freeaddrinfo(head);
1308*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
1309*6236dae4SAndroid Build Coastguard Worker       }
1310*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_VERBOSE_STRINGS
1311*6236dae4SAndroid Build Coastguard Worker       infof(data, "Added %.*s:%d:%s to DNS cache%s",
1312*6236dae4SAndroid Build Coastguard Worker             (int)hlen, host_begin, port, addresses,
1313*6236dae4SAndroid Build Coastguard Worker             permanent ? "" : " (non-permanent)");
1314*6236dae4SAndroid Build Coastguard Worker #endif
1315*6236dae4SAndroid Build Coastguard Worker 
1316*6236dae4SAndroid Build Coastguard Worker       /* Wildcard hostname */
1317*6236dae4SAndroid Build Coastguard Worker       if((hlen == 1) && (host_begin[0] == '*')) {
1318*6236dae4SAndroid Build Coastguard Worker         infof(data, "RESOLVE *:%d using wildcard", port);
1319*6236dae4SAndroid Build Coastguard Worker         data->state.wildcard_resolve = TRUE;
1320*6236dae4SAndroid Build Coastguard Worker       }
1321*6236dae4SAndroid Build Coastguard Worker     }
1322*6236dae4SAndroid Build Coastguard Worker   }
1323*6236dae4SAndroid Build Coastguard Worker   data->state.resolve = NULL; /* dealt with now */
1324*6236dae4SAndroid Build Coastguard Worker 
1325*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
1326*6236dae4SAndroid Build Coastguard Worker }
1327*6236dae4SAndroid Build Coastguard Worker 
1328*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_VERBOSE_STRINGS
show_resolve_info(struct Curl_easy * data,struct Curl_dns_entry * dns)1329*6236dae4SAndroid Build Coastguard Worker static void show_resolve_info(struct Curl_easy *data,
1330*6236dae4SAndroid Build Coastguard Worker                               struct Curl_dns_entry *dns)
1331*6236dae4SAndroid Build Coastguard Worker {
1332*6236dae4SAndroid Build Coastguard Worker   struct Curl_addrinfo *a;
1333*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
1334*6236dae4SAndroid Build Coastguard Worker #ifdef CURLRES_IPV6
1335*6236dae4SAndroid Build Coastguard Worker   struct dynbuf out[2];
1336*6236dae4SAndroid Build Coastguard Worker #else
1337*6236dae4SAndroid Build Coastguard Worker   struct dynbuf out[1];
1338*6236dae4SAndroid Build Coastguard Worker #endif
1339*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data);
1340*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(dns);
1341*6236dae4SAndroid Build Coastguard Worker 
1342*6236dae4SAndroid Build Coastguard Worker   if(!data->set.verbose ||
1343*6236dae4SAndroid Build Coastguard Worker      /* ignore no name or numerical IP addresses */
1344*6236dae4SAndroid Build Coastguard Worker      !dns->hostname[0] || Curl_host_is_ipnum(dns->hostname))
1345*6236dae4SAndroid Build Coastguard Worker     return;
1346*6236dae4SAndroid Build Coastguard Worker 
1347*6236dae4SAndroid Build Coastguard Worker   a = dns->addr;
1348*6236dae4SAndroid Build Coastguard Worker 
1349*6236dae4SAndroid Build Coastguard Worker   infof(data, "Host %s:%d was resolved.",
1350*6236dae4SAndroid Build Coastguard Worker         (dns->hostname[0] ? dns->hostname : "(none)"), dns->hostport);
1351*6236dae4SAndroid Build Coastguard Worker 
1352*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_init(&out[0], 1024);
1353*6236dae4SAndroid Build Coastguard Worker #ifdef CURLRES_IPV6
1354*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_init(&out[1], 1024);
1355*6236dae4SAndroid Build Coastguard Worker #endif
1356*6236dae4SAndroid Build Coastguard Worker 
1357*6236dae4SAndroid Build Coastguard Worker   while(a) {
1358*6236dae4SAndroid Build Coastguard Worker     if(
1359*6236dae4SAndroid Build Coastguard Worker #ifdef CURLRES_IPV6
1360*6236dae4SAndroid Build Coastguard Worker        a->ai_family == PF_INET6 ||
1361*6236dae4SAndroid Build Coastguard Worker #endif
1362*6236dae4SAndroid Build Coastguard Worker        a->ai_family == PF_INET) {
1363*6236dae4SAndroid Build Coastguard Worker       char buf[MAX_IPADR_LEN];
1364*6236dae4SAndroid Build Coastguard Worker       struct dynbuf *d = &out[(a->ai_family != PF_INET)];
1365*6236dae4SAndroid Build Coastguard Worker       Curl_printable_address(a, buf, sizeof(buf));
1366*6236dae4SAndroid Build Coastguard Worker       if(Curl_dyn_len(d))
1367*6236dae4SAndroid Build Coastguard Worker         result = Curl_dyn_addn(d, ", ", 2);
1368*6236dae4SAndroid Build Coastguard Worker       if(!result)
1369*6236dae4SAndroid Build Coastguard Worker         result = Curl_dyn_add(d, buf);
1370*6236dae4SAndroid Build Coastguard Worker       if(result) {
1371*6236dae4SAndroid Build Coastguard Worker         infof(data, "too many IP, cannot show");
1372*6236dae4SAndroid Build Coastguard Worker         goto fail;
1373*6236dae4SAndroid Build Coastguard Worker       }
1374*6236dae4SAndroid Build Coastguard Worker     }
1375*6236dae4SAndroid Build Coastguard Worker     a = a->ai_next;
1376*6236dae4SAndroid Build Coastguard Worker   }
1377*6236dae4SAndroid Build Coastguard Worker 
1378*6236dae4SAndroid Build Coastguard Worker #ifdef CURLRES_IPV6
1379*6236dae4SAndroid Build Coastguard Worker   infof(data, "IPv6: %s",
1380*6236dae4SAndroid Build Coastguard Worker         (Curl_dyn_len(&out[1]) ? Curl_dyn_ptr(&out[1]) : "(none)"));
1381*6236dae4SAndroid Build Coastguard Worker #endif
1382*6236dae4SAndroid Build Coastguard Worker   infof(data, "IPv4: %s",
1383*6236dae4SAndroid Build Coastguard Worker         (Curl_dyn_len(&out[0]) ? Curl_dyn_ptr(&out[0]) : "(none)"));
1384*6236dae4SAndroid Build Coastguard Worker 
1385*6236dae4SAndroid Build Coastguard Worker fail:
1386*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_free(&out[0]);
1387*6236dae4SAndroid Build Coastguard Worker #ifdef CURLRES_IPV6
1388*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_free(&out[1]);
1389*6236dae4SAndroid Build Coastguard Worker #endif
1390*6236dae4SAndroid Build Coastguard Worker }
1391*6236dae4SAndroid Build Coastguard Worker #endif
1392*6236dae4SAndroid Build Coastguard Worker 
Curl_resolv_check(struct Curl_easy * data,struct Curl_dns_entry ** dns)1393*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_resolv_check(struct Curl_easy *data,
1394*6236dae4SAndroid Build Coastguard Worker                            struct Curl_dns_entry **dns)
1395*6236dae4SAndroid Build Coastguard Worker {
1396*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
1397*6236dae4SAndroid Build Coastguard Worker #if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
1398*6236dae4SAndroid Build Coastguard Worker   (void)data;
1399*6236dae4SAndroid Build Coastguard Worker   (void)dns;
1400*6236dae4SAndroid Build Coastguard Worker #endif
1401*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_DOH
1402*6236dae4SAndroid Build Coastguard Worker   if(data->conn->bits.doh) {
1403*6236dae4SAndroid Build Coastguard Worker     result = Curl_doh_is_resolved(data, dns);
1404*6236dae4SAndroid Build Coastguard Worker   }
1405*6236dae4SAndroid Build Coastguard Worker   else
1406*6236dae4SAndroid Build Coastguard Worker #endif
1407*6236dae4SAndroid Build Coastguard Worker   result = Curl_resolver_is_resolved(data, dns);
1408*6236dae4SAndroid Build Coastguard Worker   if(*dns)
1409*6236dae4SAndroid Build Coastguard Worker     show_resolve_info(data, *dns);
1410*6236dae4SAndroid Build Coastguard Worker   return result;
1411*6236dae4SAndroid Build Coastguard Worker }
1412*6236dae4SAndroid Build Coastguard Worker 
Curl_resolv_getsock(struct Curl_easy * data,curl_socket_t * socks)1413*6236dae4SAndroid Build Coastguard Worker int Curl_resolv_getsock(struct Curl_easy *data,
1414*6236dae4SAndroid Build Coastguard Worker                         curl_socket_t *socks)
1415*6236dae4SAndroid Build Coastguard Worker {
1416*6236dae4SAndroid Build Coastguard Worker #ifdef CURLRES_ASYNCH
1417*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_DOH
1418*6236dae4SAndroid Build Coastguard Worker   if(data->conn->bits.doh)
1419*6236dae4SAndroid Build Coastguard Worker     /* nothing to wait for during DoH resolve, those handles have their own
1420*6236dae4SAndroid Build Coastguard Worker        sockets */
1421*6236dae4SAndroid Build Coastguard Worker     return GETSOCK_BLANK;
1422*6236dae4SAndroid Build Coastguard Worker #endif
1423*6236dae4SAndroid Build Coastguard Worker   return Curl_resolver_getsock(data, socks);
1424*6236dae4SAndroid Build Coastguard Worker #else
1425*6236dae4SAndroid Build Coastguard Worker   (void)data;
1426*6236dae4SAndroid Build Coastguard Worker   (void)socks;
1427*6236dae4SAndroid Build Coastguard Worker   return GETSOCK_BLANK;
1428*6236dae4SAndroid Build Coastguard Worker #endif
1429*6236dae4SAndroid Build Coastguard Worker }
1430*6236dae4SAndroid Build Coastguard Worker 
1431*6236dae4SAndroid Build Coastguard Worker /* Call this function after Curl_connect() has returned async=TRUE and
1432*6236dae4SAndroid Build Coastguard Worker    then a successful name resolve has been received.
1433*6236dae4SAndroid Build Coastguard Worker 
1434*6236dae4SAndroid Build Coastguard Worker    Note: this function disconnects and frees the conn data in case of
1435*6236dae4SAndroid Build Coastguard Worker    resolve failure */
Curl_once_resolved(struct Curl_easy * data,bool * protocol_done)1436*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
1437*6236dae4SAndroid Build Coastguard Worker {
1438*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
1439*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
1440*6236dae4SAndroid Build Coastguard Worker 
1441*6236dae4SAndroid Build Coastguard Worker #ifdef USE_CURL_ASYNC
1442*6236dae4SAndroid Build Coastguard Worker   if(data->state.async.dns) {
1443*6236dae4SAndroid Build Coastguard Worker     conn->dns_entry = data->state.async.dns;
1444*6236dae4SAndroid Build Coastguard Worker     data->state.async.dns = NULL;
1445*6236dae4SAndroid Build Coastguard Worker   }
1446*6236dae4SAndroid Build Coastguard Worker #endif
1447*6236dae4SAndroid Build Coastguard Worker 
1448*6236dae4SAndroid Build Coastguard Worker   result = Curl_setup_conn(data, protocol_done);
1449*6236dae4SAndroid Build Coastguard Worker 
1450*6236dae4SAndroid Build Coastguard Worker   if(result) {
1451*6236dae4SAndroid Build Coastguard Worker     Curl_detach_connection(data);
1452*6236dae4SAndroid Build Coastguard Worker     Curl_cpool_disconnect(data, conn, TRUE);
1453*6236dae4SAndroid Build Coastguard Worker   }
1454*6236dae4SAndroid Build Coastguard Worker   return result;
1455*6236dae4SAndroid Build Coastguard Worker }
1456*6236dae4SAndroid Build Coastguard Worker 
1457*6236dae4SAndroid Build Coastguard Worker /*
1458*6236dae4SAndroid Build Coastguard Worker  * Curl_resolver_error() calls failf() with the appropriate message after a
1459*6236dae4SAndroid Build Coastguard Worker  * resolve error
1460*6236dae4SAndroid Build Coastguard Worker  */
1461*6236dae4SAndroid Build Coastguard Worker 
1462*6236dae4SAndroid Build Coastguard Worker #ifdef USE_CURL_ASYNC
Curl_resolver_error(struct Curl_easy * data)1463*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_resolver_error(struct Curl_easy *data)
1464*6236dae4SAndroid Build Coastguard Worker {
1465*6236dae4SAndroid Build Coastguard Worker   const char *host_or_proxy;
1466*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
1467*6236dae4SAndroid Build Coastguard Worker 
1468*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
1469*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
1470*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.httpproxy) {
1471*6236dae4SAndroid Build Coastguard Worker     host_or_proxy = "proxy";
1472*6236dae4SAndroid Build Coastguard Worker     result = CURLE_COULDNT_RESOLVE_PROXY;
1473*6236dae4SAndroid Build Coastguard Worker   }
1474*6236dae4SAndroid Build Coastguard Worker   else
1475*6236dae4SAndroid Build Coastguard Worker #endif
1476*6236dae4SAndroid Build Coastguard Worker   {
1477*6236dae4SAndroid Build Coastguard Worker     host_or_proxy = "host";
1478*6236dae4SAndroid Build Coastguard Worker     result = CURLE_COULDNT_RESOLVE_HOST;
1479*6236dae4SAndroid Build Coastguard Worker   }
1480*6236dae4SAndroid Build Coastguard Worker 
1481*6236dae4SAndroid Build Coastguard Worker   failf(data, "Could not resolve %s: %s", host_or_proxy,
1482*6236dae4SAndroid Build Coastguard Worker         data->state.async.hostname);
1483*6236dae4SAndroid Build Coastguard Worker 
1484*6236dae4SAndroid Build Coastguard Worker   return result;
1485*6236dae4SAndroid Build Coastguard Worker }
1486*6236dae4SAndroid Build Coastguard Worker #endif /* USE_CURL_ASYNC */
1487