| 1 | /*************************************************************************** | 
| 2 |  *                                  _   _ ____  _ | 
| 3 |  *  Project                     ___| | | |  _ \| | | 
| 4 |  *                             / __| | | | |_) | | | 
| 5 |  *                            | (__| |_| |  _ <| |___ | 
| 6 |  *                             \___|\___/|_| \_\_____| | 
| 7 |  * | 
| 8 |  * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. | 
| 9 |  * | 
| 10 |  * This software is licensed as described in the file COPYING, which | 
| 11 |  * you should have received as part of this distribution. The terms | 
| 12 |  * are also available at https://curl.haxx.se/docs/copyright.html. | 
| 13 |  * | 
| 14 |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | 
| 15 |  * copies of the Software, and permit persons to whom the Software is | 
| 16 |  * furnished to do so, under the terms of the COPYING file. | 
| 17 |  * | 
| 18 |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | 
| 19 |  * KIND, either express or implied. | 
| 20 |  * | 
| 21 |  ***************************************************************************/ | 
| 22 |  | 
| 23 | #include "curl_setup.h" | 
| 24 |  | 
| 25 | /*********************************************************************** | 
| 26 |  * Only for plain IPv4 builds | 
| 27 |  **********************************************************************/ | 
| 28 | #ifdef CURLRES_IPV4 /* plain IPv4 code coming up */ | 
| 29 |  | 
| 30 | #ifdef HAVE_NETINET_IN_H | 
| 31 | #include <netinet/in.h> | 
| 32 | #endif | 
| 33 | #ifdef HAVE_NETDB_H | 
| 34 | #include <netdb.h> | 
| 35 | #endif | 
| 36 | #ifdef HAVE_ARPA_INET_H | 
| 37 | #include <arpa/inet.h> | 
| 38 | #endif | 
| 39 | #ifdef __VMS | 
| 40 | #include <in.h> | 
| 41 | #include <inet.h> | 
| 42 | #endif | 
| 43 |  | 
| 44 | #ifdef HAVE_PROCESS_H | 
| 45 | #include <process.h> | 
| 46 | #endif | 
| 47 |  | 
| 48 | #include "urldata.h" | 
| 49 | #include "sendf.h" | 
| 50 | #include "hostip.h" | 
| 51 | #include "hash.h" | 
| 52 | #include "share.h" | 
| 53 | #include "strerror.h" | 
| 54 | #include "url.h" | 
| 55 | #include "inet_pton.h" | 
| 56 | /* The last 3 #include files should be in this order */ | 
| 57 | #include "curl_printf.h" | 
| 58 | #include "curl_memory.h" | 
| 59 | #include "memdebug.h" | 
| 60 |  | 
| 61 | /* | 
| 62 |  * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've | 
| 63 |  * been set and returns TRUE if they are OK. | 
| 64 |  */ | 
| 65 | bool Curl_ipvalid(struct connectdata *conn) | 
| 66 | { | 
| 67 |   if(conn->ip_version == CURL_IPRESOLVE_V6) | 
| 68 |     /* An IPv6 address was requested and we can't get/use one */ | 
| 69 |     return FALSE; | 
| 70 |  | 
| 71 |   return TRUE; /* OK, proceed */ | 
| 72 | } | 
| 73 |  | 
| 74 | #ifdef CURLRES_SYNCH | 
| 75 |  | 
| 76 | /* | 
| 77 |  * Curl_getaddrinfo() - the IPv4 synchronous version. | 
| 78 |  * | 
| 79 |  * The original code to this function was from the Dancer source code, written | 
| 80 |  * by Bjorn Reese, it has since been patched and modified considerably. | 
| 81 |  * | 
| 82 |  * gethostbyname_r() is the thread-safe version of the gethostbyname() | 
| 83 |  * function. When we build for plain IPv4, we attempt to use this | 
| 84 |  * function. There are _three_ different gethostbyname_r() versions, and we | 
| 85 |  * detect which one this platform supports in the configure script and set up | 
| 86 |  * the HAVE_GETHOSTBYNAME_R_3, HAVE_GETHOSTBYNAME_R_5 or | 
| 87 |  * HAVE_GETHOSTBYNAME_R_6 defines accordingly. Note that HAVE_GETADDRBYNAME | 
| 88 |  * has the corresponding rules. This is primarily on *nix. Note that some unix | 
| 89 |  * flavours have thread-safe versions of the plain gethostbyname() etc. | 
| 90 |  * | 
| 91 |  */ | 
| 92 | Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, | 
| 93 |                                 const char *hostname, | 
| 94 |                                 int port, | 
| 95 |                                 int *waitp) | 
| 96 | { | 
| 97 |   Curl_addrinfo *ai = NULL; | 
| 98 |  | 
| 99 | #ifdef CURL_DISABLE_VERBOSE_STRINGS | 
| 100 |   (void)conn; | 
| 101 | #endif | 
| 102 |  | 
| 103 |   *waitp = 0; /* synchronous response only */ | 
| 104 |  | 
| 105 |   ai = Curl_ipv4_resolve_r(hostname, port); | 
| 106 |   if(!ai) | 
| 107 |     infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n" , hostname); | 
| 108 |  | 
| 109 |   return ai; | 
| 110 | } | 
| 111 | #endif /* CURLRES_SYNCH */ | 
| 112 | #endif /* CURLRES_IPV4 */ | 
| 113 |  | 
| 114 | #if defined(CURLRES_IPV4) && !defined(CURLRES_ARES) | 
| 115 |  | 
| 116 | /* | 
| 117 |  * Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function. | 
| 118 |  * | 
| 119 |  * This is used for both synchronous and asynchronous resolver builds, | 
| 120 |  * implying that only threadsafe code and function calls may be used. | 
| 121 |  * | 
| 122 |  */ | 
| 123 | Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, | 
| 124 |                                    int port) | 
| 125 | { | 
| 126 | #if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3) | 
| 127 |   int res; | 
| 128 | #endif | 
| 129 |   Curl_addrinfo *ai = NULL; | 
| 130 |   struct hostent *h = NULL; | 
| 131 |   struct in_addr in; | 
| 132 |   struct hostent *buf = NULL; | 
| 133 |  | 
| 134 | #ifdef ENABLE_IPV6 | 
| 135 |   { | 
| 136 |     struct in6_addr in6; | 
| 137 |     /* check if this is an IPv6 address string */ | 
| 138 |     if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) | 
| 139 |       /* This is an IPv6 address literal */ | 
| 140 |       return Curl_ip2addr(AF_INET6, &in6, hostname, port); | 
| 141 |   } | 
| 142 | #endif /* ENABLE_IPV6 */ | 
| 143 |  | 
| 144 |   if(Curl_inet_pton(AF_INET, hostname, &in) > 0) | 
| 145 |     /* This is a dotted IP address 123.123.123.123-style */ | 
| 146 |     return Curl_ip2addr(AF_INET, &in, hostname, port); | 
| 147 |  | 
| 148 | #if defined(HAVE_GETADDRINFO_THREADSAFE) | 
| 149 |   else { | 
| 150 |     struct addrinfo hints; | 
| 151 |     char sbuf[12]; | 
| 152 |     char *sbufptr = NULL; | 
| 153 |  | 
| 154 |     memset(&hints, 0, sizeof(hints)); | 
| 155 |     hints.ai_family = PF_INET; | 
| 156 |     hints.ai_socktype = SOCK_STREAM; | 
| 157 |     if(port) { | 
| 158 |       msnprintf(sbuf, sizeof(sbuf), "%d" , port); | 
| 159 |       sbufptr = sbuf; | 
| 160 |     } | 
| 161 |  | 
| 162 |     (void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai); | 
| 163 |  | 
| 164 | #elif defined(HAVE_GETHOSTBYNAME_R) | 
| 165 |   /* | 
| 166 |    * gethostbyname_r() is the preferred resolve function for many platforms. | 
| 167 |    * Since there are three different versions of it, the following code is | 
| 168 |    * somewhat #ifdef-ridden. | 
| 169 |    */ | 
| 170 |   else { | 
| 171 |     int h_errnop; | 
| 172 |  | 
| 173 |     buf = calloc(1, CURL_HOSTENT_SIZE); | 
| 174 |     if(!buf) | 
| 175 |       return NULL; /* major failure */ | 
| 176 |     /* | 
| 177 |      * The clearing of the buffer is a workaround for a gethostbyname_r bug in | 
| 178 |      * qnx nto and it is also _required_ for some of these functions on some | 
| 179 |      * platforms. | 
| 180 |      */ | 
| 181 |  | 
| 182 | #if defined(HAVE_GETHOSTBYNAME_R_5) | 
| 183 |     /* Solaris, IRIX and more */ | 
| 184 |     h = gethostbyname_r(hostname, | 
| 185 |                         (struct hostent *)buf, | 
| 186 |                         (char *)buf + sizeof(struct hostent), | 
| 187 |                         CURL_HOSTENT_SIZE - sizeof(struct hostent), | 
| 188 |                         &h_errnop); | 
| 189 |  | 
| 190 |     /* If the buffer is too small, it returns NULL and sets errno to | 
| 191 |      * ERANGE. The errno is thread safe if this is compiled with | 
| 192 |      * -D_REENTRANT as then the 'errno' variable is a macro defined to get | 
| 193 |      * used properly for threads. | 
| 194 |      */ | 
| 195 |  | 
| 196 |     if(h) { | 
| 197 |       ; | 
| 198 |     } | 
| 199 |     else | 
| 200 | #elif defined(HAVE_GETHOSTBYNAME_R_6) | 
| 201 |     /* Linux */ | 
| 202 |  | 
| 203 |     (void)gethostbyname_r(hostname, | 
| 204 |                         (struct hostent *)buf, | 
| 205 |                         (char *)buf + sizeof(struct hostent), | 
| 206 |                         CURL_HOSTENT_SIZE - sizeof(struct hostent), | 
| 207 |                         &h, /* DIFFERENCE */ | 
| 208 |                         &h_errnop); | 
| 209 |     /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a | 
| 210 |      * sudden this function returns EAGAIN if the given buffer size is too | 
| 211 |      * small. Previous versions are known to return ERANGE for the same | 
| 212 |      * problem. | 
| 213 |      * | 
| 214 |      * This wouldn't be such a big problem if older versions wouldn't | 
| 215 |      * sometimes return EAGAIN on a common failure case. Alas, we can't | 
| 216 |      * assume that EAGAIN *or* ERANGE means ERANGE for any given version of | 
| 217 |      * glibc. | 
| 218 |      * | 
| 219 |      * For now, we do that and thus we may call the function repeatedly and | 
| 220 |      * fail for older glibc versions that return EAGAIN, until we run out of | 
| 221 |      * buffer size (step_size grows beyond CURL_HOSTENT_SIZE). | 
| 222 |      * | 
| 223 |      * If anyone has a better fix, please tell us! | 
| 224 |      * | 
| 225 |      * ------------------------------------------------------------------- | 
| 226 |      * | 
| 227 |      * On October 23rd 2003, Dan C dug up more details on the mysteries of | 
| 228 |      * gethostbyname_r() in glibc: | 
| 229 |      * | 
| 230 |      * In glibc 2.2.5 the interface is different (this has also been | 
| 231 |      * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't | 
| 232 |      * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32 | 
| 233 |      * (shipped/upgraded by Redhat 7.2) don't show this behavior! | 
| 234 |      * | 
| 235 |      * In this "buggy" version, the return code is -1 on error and 'errno' | 
| 236 |      * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a | 
| 237 |      * thread-safe variable. | 
| 238 |      */ | 
| 239 |  | 
| 240 |     if(!h) /* failure */ | 
| 241 | #elif defined(HAVE_GETHOSTBYNAME_R_3) | 
| 242 |     /* AIX, Digital Unix/Tru64, HPUX 10, more? */ | 
| 243 |  | 
| 244 |     /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of | 
| 245 |      * the plain fact that it does not return unique full buffers on each | 
| 246 |      * call, but instead several of the pointers in the hostent structs will | 
| 247 |      * point to the same actual data! This have the unfortunate down-side that | 
| 248 |      * our caching system breaks down horribly. Luckily for us though, AIX 4.3 | 
| 249 |      * and more recent versions have a "completely thread-safe"[*] libc where | 
| 250 |      * all the data is stored in thread-specific memory areas making calls to | 
| 251 |      * the plain old gethostbyname() work fine even for multi-threaded | 
| 252 |      * programs. | 
| 253 |      * | 
| 254 |      * This AIX 4.3 or later detection is all made in the configure script. | 
| 255 |      * | 
| 256 |      * Troels Walsted Hansen helped us work this out on March 3rd, 2003. | 
| 257 |      * | 
| 258 |      * [*] = much later we've found out that it isn't at all "completely | 
| 259 |      * thread-safe", but at least the gethostbyname() function is. | 
| 260 |      */ | 
| 261 |  | 
| 262 |     if(CURL_HOSTENT_SIZE >= | 
| 263 |        (sizeof(struct hostent) + sizeof(struct hostent_data))) { | 
| 264 |  | 
| 265 |       /* August 22nd, 2000: Albert Chin-A-Young brought an updated version | 
| 266 |        * that should work! September 20: Richard Prescott worked on the buffer | 
| 267 |        * size dilemma. | 
| 268 |        */ | 
| 269 |  | 
| 270 |       res = gethostbyname_r(hostname, | 
| 271 |                             (struct hostent *)buf, | 
| 272 |                             (struct hostent_data *)((char *)buf + | 
| 273 |                                                     sizeof(struct hostent))); | 
| 274 |       h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */ | 
| 275 |     } | 
| 276 |     else | 
| 277 |       res = -1; /* failure, too smallish buffer size */ | 
| 278 |  | 
| 279 |     if(!res) { /* success */ | 
| 280 |  | 
| 281 |       h = buf; /* result expected in h */ | 
| 282 |  | 
| 283 |       /* This is the worst kind of the different gethostbyname_r() interfaces. | 
| 284 |        * Since we don't know how big buffer this particular lookup required, | 
| 285 |        * we can't realloc down the huge alloc without doing closer analysis of | 
| 286 |        * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every | 
| 287 |        * name lookup. Fixing this would require an extra malloc() and then | 
| 288 |        * calling Curl_addrinfo_copy() that subsequent realloc()s down the new | 
| 289 |        * memory area to the actually used amount. | 
| 290 |        */ | 
| 291 |     } | 
| 292 |     else | 
| 293 | #endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */ | 
| 294 |     { | 
| 295 |       h = NULL; /* set return code to NULL */ | 
| 296 |       free(buf); | 
| 297 |     } | 
| 298 | #else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ | 
| 299 |     /* | 
| 300 |      * Here is code for platforms that don't have a thread safe | 
| 301 |      * getaddrinfo() nor gethostbyname_r() function or for which | 
| 302 |      * gethostbyname() is the preferred one. | 
| 303 |      */ | 
| 304 |   else { | 
| 305 |     h = gethostbyname((void *)hostname); | 
| 306 | #endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ | 
| 307 |   } | 
| 308 |  | 
| 309 |   if(h) { | 
| 310 |     ai = Curl_he2ai(h, port); | 
| 311 |  | 
| 312 |     if(buf) /* used a *_r() function */ | 
| 313 |       free(buf); | 
| 314 |   } | 
| 315 |  | 
| 316 |   return ai; | 
| 317 | } | 
| 318 | #endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) */ | 
| 319 |  |