00001 /*************************************************************************** 00002 * _ _ ____ _ 00003 * Project ___| | | | _ \| | 00004 * / __| | | | |_) | | 00005 * | (__| |_| | _ <| |___ 00006 * \___|\___/|_| \_\_____| 00007 * 00008 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. 00009 * 00010 * This software is licensed as described in the file COPYING, which 00011 * you should have received as part of this distribution. The terms 00012 * are also available at http://curl.haxx.se/docs/copyright.html. 00013 * 00014 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 00015 * copies of the Software, and permit persons to whom the Software is 00016 * furnished to do so, under the terms of the COPYING file. 00017 * 00018 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 00019 * KIND, either express or implied. 00020 * 00021 * $Id: hostip4.c,v 1.40 2007-07-01 22:01:19 bagder Exp $ 00022 ***************************************************************************/ 00023 00024 #include "setup.h" 00025 00026 #include <string.h> 00027 #include <errno.h> 00028 00029 #ifdef NEED_MALLOC_H 00030 #include <malloc.h> 00031 #endif 00032 #ifdef HAVE_SYS_SOCKET_H 00033 #include <sys/socket.h> 00034 #endif 00035 #ifdef HAVE_NETINET_IN_H 00036 #include <netinet/in.h> 00037 #endif 00038 #ifdef HAVE_NETDB_H 00039 #include <netdb.h> 00040 #endif 00041 #ifdef HAVE_ARPA_INET_H 00042 #include <arpa/inet.h> 00043 #endif 00044 #ifdef HAVE_STDLIB_H 00045 #include <stdlib.h> /* required for free() prototypes */ 00046 #endif 00047 #ifdef HAVE_UNISTD_H 00048 #include <unistd.h> /* for the close() proto */ 00049 #endif 00050 #ifdef VMS 00051 #include <in.h> 00052 #include <inet.h> 00053 #include <stdlib.h> 00054 #endif 00055 00056 #ifdef HAVE_SETJMP_H 00057 #include <setjmp.h> 00058 #endif 00059 00060 #ifdef HAVE_PROCESS_H 00061 #include <process.h> 00062 #endif 00063 00064 #include "urldata.h" 00065 #include "sendf.h" 00066 #include "hostip.h" 00067 #include "hash.h" 00068 #include "share.h" 00069 #include "strerror.h" 00070 #include "url.h" 00071 #include "inet_pton.h" 00072 00073 #define _MPRINTF_REPLACE /* use our functions only */ 00074 #include <curl/mprintf.h> 00075 00076 #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) 00077 #include "inet_ntoa_r.h" 00078 #endif 00079 00080 #include "memory.h" 00081 /* The last #include file should be: */ 00082 #include "memdebug.h" 00083 00084 /*********************************************************************** 00085 * Only for plain-ipv4 builds 00086 **********************************************************************/ 00087 #ifdef CURLRES_IPV4 /* plain ipv4 code coming up */ 00088 /* 00089 * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've 00090 * been set and returns TRUE if they are OK. 00091 */ 00092 bool Curl_ipvalid(struct SessionHandle *data) 00093 { 00094 if(data->set.ip_version == CURL_IPRESOLVE_V6) 00095 /* an ipv6 address was requested and we can't get/use one */ 00096 return FALSE; 00097 00098 return TRUE; /* OK, proceed */ 00099 } 00100 00101 #ifdef CURLRES_SYNCH /* the functions below are for synchronous resolves */ 00102 00103 /* 00104 * Curl_getaddrinfo() - the ipv4 synchronous version. 00105 * 00106 * The original code to this function was from the Dancer source code, written 00107 * by Bjorn Reese, it has since been patched and modified considerably. 00108 * 00109 * gethostbyname_r() is the thread-safe version of the gethostbyname() 00110 * function. When we build for plain IPv4, we attempt to use this 00111 * function. There are _three_ different gethostbyname_r() versions, and we 00112 * detect which one this platform supports in the configure script and set up 00113 * the HAVE_GETHOSTBYNAME_R_3, HAVE_GETHOSTBYNAME_R_5 or 00114 * HAVE_GETHOSTBYNAME_R_6 defines accordingly. Note that HAVE_GETADDRBYNAME 00115 * has the corresponding rules. This is primarily on *nix. Note that some unix 00116 * flavours have thread-safe versions of the plain gethostbyname() etc. 00117 * 00118 */ 00119 Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, 00120 const char *hostname, 00121 int port, 00122 int *waitp) 00123 { 00124 #if defined(HAVE_GETHOSTBYNAME_R_3) 00125 int res; 00126 #endif 00127 Curl_addrinfo *ai = NULL; 00128 struct hostent *h = NULL; 00129 in_addr_t in; 00130 struct hostent *buf = NULL; 00131 00132 #ifdef CURL_DISABLE_VERBOSE_STRINGS 00133 (void)conn; 00134 #endif 00135 00136 (void)port; /* unused in IPv4 code */ 00137 00138 *waitp = 0; /* don't wait, we act synchronously */ 00139 00140 if(1 == Curl_inet_pton(AF_INET, hostname, &in)) 00141 /* This is a dotted IP address 123.123.123.123-style */ 00142 return Curl_ip2addr(in, hostname, port); 00143 00144 #if defined(HAVE_GETHOSTBYNAME_R) 00145 /* 00146 * gethostbyname_r() is the preferred resolve function for many platforms. 00147 * Since there are three different versions of it, the following code is 00148 * somewhat #ifdef-ridden. 00149 */ 00150 else { 00151 int h_errnop; 00152 00153 buf = (struct hostent *)calloc(CURL_HOSTENT_SIZE, 1); 00154 if(!buf) 00155 return NULL; /* major failure */ 00156 /* 00157 * The clearing of the buffer is a workaround for a gethostbyname_r bug in 00158 * qnx nto and it is also _required_ for some of these functions on some 00159 * platforms. 00160 */ 00161 00162 #ifdef HAVE_GETHOSTBYNAME_R_5 00163 /* Solaris, IRIX and more */ 00164 h = gethostbyname_r(hostname, 00165 (struct hostent *)buf, 00166 (char *)buf + sizeof(struct hostent), 00167 CURL_HOSTENT_SIZE - sizeof(struct hostent), 00168 &h_errnop); 00169 00170 /* If the buffer is too small, it returns NULL and sets errno to 00171 * ERANGE. The errno is thread safe if this is compiled with 00172 * -D_REENTRANT as then the 'errno' variable is a macro defined to get 00173 * used properly for threads. 00174 */ 00175 00176 if(h) { 00177 ; 00178 } 00179 else 00180 #endif /* HAVE_GETHOSTBYNAME_R_5 */ 00181 #ifdef HAVE_GETHOSTBYNAME_R_6 00182 /* Linux */ 00183 00184 (void)gethostbyname_r(hostname, 00185 (struct hostent *)buf, 00186 (char *)buf + sizeof(struct hostent), 00187 CURL_HOSTENT_SIZE - sizeof(struct hostent), 00188 &h, /* DIFFERENCE */ 00189 &h_errnop); 00190 /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a 00191 * sudden this function returns EAGAIN if the given buffer size is too 00192 * small. Previous versions are known to return ERANGE for the same 00193 * problem. 00194 * 00195 * This wouldn't be such a big problem if older versions wouldn't 00196 * sometimes return EAGAIN on a common failure case. Alas, we can't 00197 * assume that EAGAIN *or* ERANGE means ERANGE for any given version of 00198 * glibc. 00199 * 00200 * For now, we do that and thus we may call the function repeatedly and 00201 * fail for older glibc versions that return EAGAIN, until we run out of 00202 * buffer size (step_size grows beyond CURL_HOSTENT_SIZE). 00203 * 00204 * If anyone has a better fix, please tell us! 00205 * 00206 * ------------------------------------------------------------------- 00207 * 00208 * On October 23rd 2003, Dan C dug up more details on the mysteries of 00209 * gethostbyname_r() in glibc: 00210 * 00211 * In glibc 2.2.5 the interface is different (this has also been 00212 * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't 00213 * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32 00214 * (shipped/upgraded by Redhat 7.2) don't show this behavior! 00215 * 00216 * In this "buggy" version, the return code is -1 on error and 'errno' 00217 * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a 00218 * thread-safe variable. 00219 */ 00220 00221 if(!h) /* failure */ 00222 #endif/* HAVE_GETHOSTBYNAME_R_6 */ 00223 #ifdef HAVE_GETHOSTBYNAME_R_3 00224 /* AIX, Digital Unix/Tru64, HPUX 10, more? */ 00225 00226 /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of 00227 * the plain fact that it does not return unique full buffers on each 00228 * call, but instead several of the pointers in the hostent structs will 00229 * point to the same actual data! This have the unfortunate down-side that 00230 * our caching system breaks down horribly. Luckily for us though, AIX 4.3 00231 * and more recent versions have a "completely thread-safe"[*] libc where 00232 * all the data is stored in thread-specific memory areas making calls to 00233 * the plain old gethostbyname() work fine even for multi-threaded 00234 * programs. 00235 * 00236 * This AIX 4.3 or later detection is all made in the configure script. 00237 * 00238 * Troels Walsted Hansen helped us work this out on March 3rd, 2003. 00239 * 00240 * [*] = much later we've found out that it isn't at all "completely 00241 * thread-safe", but at least the gethostbyname() function is. 00242 */ 00243 00244 if(CURL_HOSTENT_SIZE >= 00245 (sizeof(struct hostent)+sizeof(struct hostent_data))) { 00246 00247 /* August 22nd, 2000: Albert Chin-A-Young brought an updated version 00248 * that should work! September 20: Richard Prescott worked on the buffer 00249 * size dilemma. 00250 */ 00251 00252 res = gethostbyname_r(hostname, 00253 (struct hostent *)buf, 00254 (struct hostent_data *)((char *)buf + 00255 sizeof(struct hostent))); 00256 h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */ 00257 } 00258 else 00259 res = -1; /* failure, too smallish buffer size */ 00260 00261 if(!res) { /* success */ 00262 00263 h = buf; /* result expected in h */ 00264 00265 /* This is the worst kind of the different gethostbyname_r() interfaces. 00266 * Since we don't know how big buffer this particular lookup required, 00267 * we can't realloc down the huge alloc without doing closer analysis of 00268 * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every 00269 * name lookup. Fixing this would require an extra malloc() and then 00270 * calling Curl_addrinfo_copy() that subsequent realloc()s down the new 00271 * memory area to the actually used amount. 00272 */ 00273 } 00274 else 00275 #endif /* HAVE_GETHOSTBYNAME_R_3 */ 00276 { 00277 infof(conn->data, "gethostbyname_r(2) failed for %s\n", hostname); 00278 h = NULL; /* set return code to NULL */ 00279 free(buf); 00280 } 00281 #else /* HAVE_GETHOSTBYNAME_R */ 00282 /* 00283 * Here is code for platforms that don't have gethostbyname_r() or for 00284 * which the gethostbyname() is the preferred() function. 00285 */ 00286 else { 00287 #if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) 00288 NETDB_DEFINE_CONTEXT 00289 h = gethostbyname((char*)hostname); 00290 #else 00291 h = gethostbyname(hostname); 00292 #endif 00293 if (!h) 00294 infof(conn->data, "gethostbyname(2) failed for %s\n", hostname); 00295 #endif /*HAVE_GETHOSTBYNAME_R */ 00296 } 00297 00298 if(h) { 00299 ai = Curl_he2ai(h, port); 00300 00301 if (buf) /* used a *_r() function */ 00302 free(buf); 00303 } 00304 00305 return ai; 00306 } 00307 00308 #endif /* CURLRES_SYNCH */ 00309 #endif /* CURLRES_IPV4 */ 00310 00311 /* 00312 * Curl_he2ai() translates from a hostent struct to a Curl_addrinfo struct. 00313 * The Curl_addrinfo is meant to work like the addrinfo struct does for IPv6 00314 * stacks, but for all hosts and environments. 00315 * 00316 * Curl_addrinfo defined in "lib/hostip.h" 00317 * 00318 * struct Curl_addrinfo { 00319 * int ai_flags; 00320 * int ai_family; 00321 * int ai_socktype; 00322 * int ai_protocol; 00323 * socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo * 00324 * char *ai_canonname; 00325 * struct sockaddr *ai_addr; 00326 * struct Curl_addrinfo *ai_next; 00327 * }; 00328 * 00329 * hostent defined in <netdb.h> 00330 * 00331 * struct hostent { 00332 * char *h_name; 00333 * char **h_aliases; 00334 * int h_addrtype; 00335 * int h_length; 00336 * char **h_addr_list; 00337 * }; 00338 * 00339 * for backward compatibility: 00340 * 00341 * #define h_addr h_addr_list[0] 00342 */ 00343 00344 Curl_addrinfo *Curl_he2ai(const struct hostent *he, int port) 00345 { 00346 Curl_addrinfo *ai; 00347 Curl_addrinfo *prevai = NULL; 00348 Curl_addrinfo *firstai = NULL; 00349 struct sockaddr_in *addr; 00350 int i; 00351 struct in_addr *curr; 00352 00353 if(!he) 00354 /* no input == no output! */ 00355 return NULL; 00356 00357 for(i=0; (curr = (struct in_addr *)he->h_addr_list[i]) != NULL; i++) { 00358 00359 ai = calloc(1, sizeof(Curl_addrinfo) + sizeof(struct sockaddr_in)); 00360 00361 if(!ai) 00362 break; 00363 00364 if(!firstai) 00365 /* store the pointer we want to return from this function */ 00366 firstai = ai; 00367 00368 if(prevai) 00369 /* make the previous entry point to this */ 00370 prevai->ai_next = ai; 00371 00372 ai->ai_family = AF_INET; /* we only support this */ 00373 00374 /* we return all names as STREAM, so when using this address for TFTP 00375 the type must be ignored and conn->socktype be used instead! */ 00376 ai->ai_socktype = SOCK_STREAM; 00377 00378 ai->ai_addrlen = sizeof(struct sockaddr_in); 00379 /* make the ai_addr point to the address immediately following this struct 00380 and use that area to store the address */ 00381 ai->ai_addr = (struct sockaddr *) ((char*)ai + sizeof(Curl_addrinfo)); 00382 00383 /* FIXME: need to free this eventually */ 00384 ai->ai_canonname = strdup(he->h_name); 00385 00386 /* leave the rest of the struct filled with zero */ 00387 00388 addr = (struct sockaddr_in *)ai->ai_addr; /* storage area for this info */ 00389 00390 memcpy((char *)&(addr->sin_addr), curr, sizeof(struct in_addr)); 00391 addr->sin_family = (unsigned short)(he->h_addrtype); 00392 addr->sin_port = htons((unsigned short)port); 00393 00394 prevai = ai; 00395 } 00396 return firstai; 00397 } 00398
1.5.6