hostip.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2002, Daniel Stenberg, <[email protected]>, 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 http://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. * $Id$
  22. ***************************************************************************/
  23. #include "setup.h"
  24. #include <string.h>
  25. #include <errno.h>
  26. #define _REENTRANT
  27. #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
  28. #include <winsock.h>
  29. #else
  30. #ifdef HAVE_SYS_TYPES_H
  31. #include <sys/types.h>
  32. #endif
  33. #ifdef HAVE_SYS_SOCKET_H
  34. #include <sys/socket.h>
  35. #endif
  36. #ifdef HAVE_NETINET_IN_H
  37. #include <netinet/in.h>
  38. #endif
  39. #ifdef HAVE_NETDB_H
  40. #include <netdb.h>
  41. #endif
  42. #ifdef HAVE_ARPA_INET_H
  43. #include <arpa/inet.h>
  44. #endif
  45. #ifdef HAVE_STDLIB_H
  46. #include <stdlib.h> /* required for free() prototypes */
  47. #endif
  48. #ifdef VMS
  49. #include <in.h>
  50. #include <inet.h>
  51. #include <stdlib.h>
  52. #endif
  53. #endif
  54. #ifdef HAVE_SETJMP_H
  55. #include <setjmp.h>
  56. #endif
  57. #include "urldata.h"
  58. #include "sendf.h"
  59. #include "hostip.h"
  60. #include "hash.h"
  61. #define _MPRINTF_REPLACE /* use our functions only */
  62. #include <curl/mprintf.h>
  63. #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
  64. #include "inet_ntoa_r.h"
  65. #endif
  66. /* The last #include file should be: */
  67. #ifdef MALLOCDEBUG
  68. #include "memdebug.h"
  69. #endif
  70. static curl_hash hostname_cache;
  71. static int host_cache_initialized;
  72. static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data,
  73. char *hostname,
  74. int port,
  75. char **bufp);
  76. void Curl_global_host_cache_init(void)
  77. {
  78. if (!host_cache_initialized) {
  79. Curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo);
  80. host_cache_initialized = 1;
  81. }
  82. }
  83. curl_hash *Curl_global_host_cache_get(void)
  84. {
  85. return &hostname_cache;
  86. }
  87. void Curl_global_host_cache_dtor(void)
  88. {
  89. if (host_cache_initialized) {
  90. Curl_hash_clean(&hostname_cache);
  91. host_cache_initialized = 0;
  92. }
  93. }
  94. /* count the number of characters that an integer takes up */
  95. static int _num_chars(int i)
  96. {
  97. int chars = 0;
  98. /* While the number divided by 10 is greater than one,
  99. * re-divide the number by 10, and increment the number of
  100. * characters by 1.
  101. *
  102. * this relies on the fact that for every multiple of 10,
  103. * a new digit is added onto every number
  104. */
  105. do {
  106. chars++;
  107. i = (int) i / 10;
  108. } while (i >= 1);
  109. return chars;
  110. }
  111. /* Create a hostcache id */
  112. static char *
  113. create_hostcache_id(char *server, int port, ssize_t *entry_len)
  114. {
  115. char *id = NULL;
  116. /* Get the length of the new entry id */
  117. *entry_len = *entry_len + /* Hostname length */
  118. 1 + /* The ':' seperator */
  119. _num_chars(port); /* The number of characters the port will take up */
  120. /* Allocate the new entry id */
  121. id = malloc(*entry_len + 1);
  122. if (!id) {
  123. return NULL;
  124. }
  125. /* Create the new entry */
  126. /* If sprintf() doesn't return the entry length, that signals failure */
  127. if (sprintf(id, "%s:%d", server, port) != *entry_len) {
  128. /* Free the allocated id, set length to zero and return NULL */
  129. *entry_len = 0;
  130. free(id);
  131. return NULL;
  132. }
  133. return id;
  134. }
  135. struct hostcache_prune_data {
  136. int cache_timeout;
  137. int now;
  138. };
  139. static int
  140. hostcache_timestamp_remove(void *datap, void *hc)
  141. {
  142. struct hostcache_prune_data *data =
  143. (struct hostcache_prune_data *) datap;
  144. struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
  145. if ((data->now - c->timestamp < data->cache_timeout) ||
  146. c->inuse) {
  147. /* please don't remove */
  148. return 0;
  149. }
  150. /* fine, remove */
  151. return 1;
  152. }
  153. static void
  154. hostcache_prune(curl_hash *hostcache, int cache_timeout, int now)
  155. {
  156. struct hostcache_prune_data user;
  157. user.cache_timeout = cache_timeout;
  158. user.now = now;
  159. Curl_hash_clean_with_criterium(hostcache,
  160. (void *) &user,
  161. hostcache_timestamp_remove);
  162. }
  163. #if defined(MALLOCDEBUG) && defined(AGGRESIVE_TEST)
  164. /* Called from Curl_done() to check that there's no DNS cache entry with
  165. a non-zero counter left. */
  166. void Curl_scan_cache_used(void *user, void *ptr)
  167. {
  168. struct Curl_dns_entry *e = ptr;
  169. (void)user; /* prevent compiler warning */
  170. if(e->inuse) {
  171. fprintf(stderr, "*** WARNING: locked DNS cache entry detected: %s\n",
  172. e->entry_id);
  173. /* perform a segmentation fault to draw attention */
  174. *(void **)0 = 0;
  175. }
  176. }
  177. #endif
  178. /* Macro to save redundant free'ing of entry_id */
  179. #define HOSTCACHE_RETURN(dns) \
  180. { \
  181. free(entry_id); \
  182. return dns; \
  183. }
  184. #ifdef HAVE_SIGSETJMP
  185. /* Beware this is a global and unique instance */
  186. sigjmp_buf curl_jmpenv;
  187. #endif
  188. struct Curl_dns_entry *Curl_resolv(struct SessionHandle *data,
  189. char *hostname,
  190. int port)
  191. {
  192. char *entry_id = NULL;
  193. struct Curl_dns_entry *dns = NULL;
  194. ssize_t entry_len;
  195. time_t now;
  196. char *bufp;
  197. #ifdef HAVE_SIGSETJMP
  198. /* this allows us to time-out from the name resolver, as the timeout
  199. will generate a signal and we will siglongjmp() from that here */
  200. if(!data->set.no_signal && sigsetjmp(curl_jmpenv, 1)) {
  201. /* this is coming from a siglongjmp() */
  202. failf(data, "name lookup time-outed");
  203. return NULL;
  204. }
  205. #endif
  206. /* Create an entry id, based upon the hostname and port */
  207. entry_len = strlen(hostname);
  208. entry_id = create_hostcache_id(hostname, port, &entry_len);
  209. /* If we can't create the entry id, fail */
  210. if (!entry_id)
  211. return NULL;
  212. /* See if its already in our dns cache */
  213. dns = Curl_hash_pick(data->hostcache, entry_id, entry_len+1);
  214. if (!dns) {
  215. Curl_addrinfo *addr = my_getaddrinfo(data, hostname, port, &bufp);
  216. if (!addr) {
  217. HOSTCACHE_RETURN(NULL);
  218. }
  219. /* Create a new cache entry */
  220. dns = (struct Curl_dns_entry *) malloc(sizeof(struct Curl_dns_entry));
  221. if (!dns) {
  222. Curl_freeaddrinfo(addr);
  223. HOSTCACHE_RETURN(NULL);
  224. }
  225. dns->inuse = 0;
  226. dns->addr = addr;
  227. /* Save it in our host cache */
  228. Curl_hash_add(data->hostcache, entry_id, entry_len+1, (const void *) dns);
  229. }
  230. time(&now);
  231. dns->timestamp = now;
  232. dns->inuse++; /* mark entry as in-use */
  233. #ifdef MALLOCDEBUG
  234. dns->entry_id = entry_id;
  235. #endif
  236. /* Remove outdated and unused entries from the hostcache */
  237. hostcache_prune(data->hostcache,
  238. data->set.dns_cache_timeout,
  239. now);
  240. HOSTCACHE_RETURN(dns);
  241. }
  242. /*
  243. * This is a wrapper function for freeing name information in a protocol
  244. * independent way. This takes care of using the appropriate underlaying
  245. * proper function.
  246. */
  247. void Curl_freeaddrinfo(void *freethis)
  248. {
  249. struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis;
  250. #ifdef ENABLE_IPV6
  251. freeaddrinfo(p->addr);
  252. #else
  253. free(p->addr);
  254. #endif
  255. free(p);
  256. }
  257. /* --- resolve name or IP-number --- */
  258. #ifdef ENABLE_IPV6
  259. #ifdef MALLOCDEBUG
  260. /* These two are strictly for memory tracing and are using the same
  261. * style as the family otherwise present in memdebug.c. I put these ones
  262. * here since they require a bunch of struct types I didn't wanna include
  263. * in memdebug.c
  264. */
  265. int curl_getaddrinfo(char *hostname, char *service,
  266. struct addrinfo *hints,
  267. struct addrinfo **result,
  268. int line, const char *source)
  269. {
  270. int res=(getaddrinfo)(hostname, service, hints, result);
  271. if(0 == res) {
  272. /* success */
  273. if(logfile)
  274. fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
  275. source, line, (void *)*result);
  276. }
  277. else {
  278. if(logfile)
  279. fprintf(logfile, "ADDR %s:%d getaddrinfo() failed\n",
  280. source, line);
  281. }
  282. return res;
  283. }
  284. void curl_freeaddrinfo(struct addrinfo *freethis,
  285. int line, const char *source)
  286. {
  287. (freeaddrinfo)(freethis);
  288. if(logfile)
  289. fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
  290. source, line, (void *)freethis);
  291. }
  292. #endif
  293. /*
  294. * Return name information about the given hostname and port number. If
  295. * successful, the 'addrinfo' is returned and the forth argument will point to
  296. * memory we need to free after use. That meory *MUST* be freed with
  297. * Curl_freeaddrinfo(), nothing else.
  298. */
  299. static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data,
  300. char *hostname,
  301. int port,
  302. char **bufp)
  303. {
  304. struct addrinfo hints, *res;
  305. int error;
  306. char sbuf[NI_MAXSERV];
  307. int s, pf = PF_UNSPEC;
  308. /* see if we have an IPv6 stack */
  309. s = socket(PF_INET6, SOCK_DGRAM, 0);
  310. if (s < 0)
  311. /* Some non-IPv6 stacks have been found to make very slow name resolves
  312. * when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
  313. * the stack seems to be a non-ipv6 one. */
  314. pf = PF_INET;
  315. else
  316. /* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
  317. * possible checks. And close the socket again.
  318. */
  319. sclose(s);
  320. memset(&hints, 0, sizeof(hints));
  321. hints.ai_family = pf;
  322. hints.ai_socktype = SOCK_STREAM;
  323. hints.ai_flags = AI_CANONNAME;
  324. snprintf(sbuf, sizeof(sbuf), "%d", port);
  325. error = getaddrinfo(hostname, sbuf, &hints, &res);
  326. if (error) {
  327. infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
  328. return NULL;
  329. }
  330. *bufp=(char *)res; /* make it point to the result struct */
  331. return res;
  332. }
  333. #else /* following code is IPv4-only */
  334. #ifndef HAVE_GETHOSTBYNAME_R
  335. static void hostcache_fixoffset(struct hostent *h, int offset);
  336. /**
  337. * Performs a "deep" copy of a hostent into a buffer (returns a pointer to the
  338. * copy). Make absolutely sure the destination buffer is big enough!
  339. *
  340. * Keith McGuigan
  341. * 10/3/2001 */
  342. static struct hostent* pack_hostent(char** buf, struct hostent* orig)
  343. {
  344. char *bufptr;
  345. char *newbuf;
  346. struct hostent* copy;
  347. int i;
  348. char *str;
  349. int len;
  350. bufptr = *buf;
  351. copy = (struct hostent*)bufptr;
  352. bufptr += sizeof(struct hostent);
  353. copy->h_name = bufptr;
  354. len = strlen(orig->h_name) + 1;
  355. strncpy(bufptr, orig->h_name, len);
  356. bufptr += len;
  357. /* we align on even 64bit boundaries for safety */
  358. #define MEMALIGN(x) ((x)+(8-(((unsigned long)(x))&0x7)))
  359. /* This must be aligned properly to work on many CPU architectures! */
  360. bufptr = MEMALIGN(bufptr);
  361. copy->h_aliases = (char**)bufptr;
  362. /* Figure out how many aliases there are */
  363. for (i = 0; orig->h_aliases[i] != NULL; ++i);
  364. /* Reserve room for the array */
  365. bufptr += (i + 1) * sizeof(char*);
  366. /* Clone all known aliases */
  367. for(i = 0; (str = orig->h_aliases[i]); i++) {
  368. len = strlen(str) + 1;
  369. strncpy(bufptr, str, len);
  370. copy->h_aliases[i] = bufptr;
  371. bufptr += len;
  372. }
  373. /* Terminate the alias list with a NULL */
  374. copy->h_aliases[i] = NULL;
  375. copy->h_addrtype = orig->h_addrtype;
  376. copy->h_length = orig->h_length;
  377. /* align it for (at least) 32bit accesses */
  378. bufptr = MEMALIGN(bufptr);
  379. copy->h_addr_list = (char**)bufptr;
  380. /* Figure out how many addresses there are */
  381. for (i = 0; orig->h_addr_list[i] != NULL; ++i);
  382. /* Reserve room for the array */
  383. bufptr += (i + 1) * sizeof(char*);
  384. i = 0;
  385. len = orig->h_length;
  386. str = orig->h_addr_list[i];
  387. while (str != NULL) {
  388. memcpy(bufptr, str, len);
  389. copy->h_addr_list[i] = bufptr;
  390. bufptr += len;
  391. str = orig->h_addr_list[++i];
  392. }
  393. copy->h_addr_list[i] = NULL;
  394. /* now, shrink the allocated buffer to the size we actually need, which
  395. most often is only a fraction of the original alloc */
  396. newbuf=(char *)realloc(*buf, (int)bufptr-(int)(*buf));
  397. /* if the alloc moved, we need to adjust things again */
  398. if(newbuf != *buf)
  399. hostcache_fixoffset((struct hostent*)newbuf, (int)newbuf-(int)*buf);
  400. /* setup the return */
  401. *buf = newbuf;
  402. copy = (struct hostent*)newbuf;
  403. return copy;
  404. }
  405. #endif
  406. static char *MakeIP(unsigned long num,char *addr, int addr_len)
  407. {
  408. #if defined(HAVE_INET_NTOA) || defined(HAVE_INET_NTOA_R)
  409. struct in_addr in;
  410. in.s_addr = htonl(num);
  411. #if defined(HAVE_INET_NTOA_R)
  412. inet_ntoa_r(in,addr,addr_len);
  413. #else
  414. strncpy(addr,inet_ntoa(in),addr_len);
  415. #endif
  416. #else
  417. unsigned char *paddr;
  418. num = htonl(num); /* htonl() added to avoid endian probs */
  419. paddr = (unsigned char *)&num;
  420. sprintf(addr, "%u.%u.%u.%u", paddr[0], paddr[1], paddr[2], paddr[3]);
  421. #endif
  422. return (addr);
  423. }
  424. #ifndef INADDR_NONE
  425. #define INADDR_NONE (in_addr_t) ~0
  426. #endif
  427. static void hostcache_fixoffset(struct hostent *h, int offset)
  428. {
  429. int i=0;
  430. h->h_name=(char *)((long)h->h_name+offset);
  431. h->h_aliases=(char **)((long)h->h_aliases+offset);
  432. while(h->h_aliases[i]) {
  433. h->h_aliases[i]=(char *)((long)h->h_aliases[i]+offset);
  434. i++;
  435. }
  436. h->h_addr_list=(char **)((long)h->h_addr_list+offset);
  437. i=0;
  438. while(h->h_addr_list[i]) {
  439. h->h_addr_list[i]=(char *)((long)h->h_addr_list[i]+offset);
  440. i++;
  441. }
  442. }
  443. /* The original code to this function was once stolen from the Dancer source
  444. code, written by Bjorn Reese, it has since been patched and modified
  445. considerably. */
  446. static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data,
  447. char *hostname,
  448. int port,
  449. char **bufp)
  450. {
  451. struct hostent *h = NULL;
  452. in_addr_t in;
  453. int ret; /* this variable is unused on several platforms but used on some */
  454. #define CURL_NAMELOOKUP_SIZE 9000
  455. /* Allocate enough memory to hold the full name information structs and
  456. * everything. OSF1 is known to require at least 8872 bytes. The buffer
  457. * required for storing all possible aliases and IP numbers is according to
  458. * Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes! */
  459. port=0; /* unused in IPv4 code */
  460. ret = 0; /* to prevent the compiler warning */
  461. if ( (in=inet_addr(hostname)) != INADDR_NONE ) {
  462. struct in_addr *addrentry;
  463. struct namebuf {
  464. struct hostent hostentry;
  465. char *h_addr_list[2];
  466. struct in_addr addrentry;
  467. char h_name[128];
  468. } *buf = (struct namebuf *)malloc(sizeof(struct namebuf));
  469. if(!buf)
  470. return NULL; /* major failure */
  471. *bufp = (char *)buf;
  472. h = &buf->hostentry;
  473. h->h_addr_list = &buf->h_addr_list[0];
  474. addrentry = &buf->addrentry;
  475. addrentry->s_addr = in;
  476. h->h_addr_list[0] = (char*)addrentry;
  477. h->h_addr_list[1] = NULL;
  478. h->h_addrtype = AF_INET;
  479. h->h_length = sizeof(*addrentry);
  480. h->h_name = &buf->h_name[0];
  481. MakeIP(ntohl(in), h->h_name, sizeof(buf->h_name));
  482. }
  483. #if defined(HAVE_GETHOSTBYNAME_R)
  484. else {
  485. int h_errnop;
  486. int res=ERANGE;
  487. int step_size=200;
  488. int *buf = (int *)malloc(CURL_NAMELOOKUP_SIZE);
  489. if(!buf)
  490. return NULL; /* major failure */
  491. *bufp=(char *)buf;
  492. /* Workaround for gethostbyname_r bug in qnx nto. It is also _required_
  493. for some of these functions. */
  494. memset(buf, 0, CURL_NAMELOOKUP_SIZE);
  495. #ifdef HAVE_GETHOSTBYNAME_R_5
  496. /* Solaris, IRIX and more */
  497. (void)res; /* prevent compiler warning */
  498. while(!h) {
  499. h = gethostbyname_r(hostname,
  500. (struct hostent *)buf,
  501. (char *)buf + sizeof(struct hostent),
  502. step_size - sizeof(struct hostent),
  503. &h_errnop);
  504. /* If the buffer is too small, it returns NULL and sets errno to
  505. ERANGE. The errno is thread safe if this is compiled with
  506. -D_REENTRANT as then the 'errno' variable is a macro defined to
  507. get used properly for threads. */
  508. if(h || (errno != ERANGE))
  509. break;
  510. step_size+=200;
  511. }
  512. #ifdef MALLOCDEBUG
  513. infof(data, "gethostbyname_r() uses %d bytes\n", step_size);
  514. #endif
  515. if(h) {
  516. int offset;
  517. h=(struct hostent *)realloc(buf, step_size);
  518. offset=(long)h-(long)buf;
  519. hostcache_fixoffset(h, offset);
  520. buf=(int *)h;
  521. *bufp=(char *)buf;
  522. }
  523. else
  524. #endif
  525. #ifdef HAVE_GETHOSTBYNAME_R_6
  526. /* Linux */
  527. do {
  528. res=gethostbyname_r(hostname,
  529. (struct hostent *)buf,
  530. (char *)buf + sizeof(struct hostent),
  531. step_size - sizeof(struct hostent),
  532. &h, /* DIFFERENCE */
  533. &h_errnop);
  534. /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a
  535. sudden this function seems to be setting EAGAIN if the given buffer
  536. size is too small. Previous versions are known to return ERANGE for
  537. the same. */
  538. if((ERANGE == res) || (EAGAIN == res)) {
  539. step_size+=200;
  540. continue;
  541. }
  542. break;
  543. } while(1);
  544. if(!h) /* failure */
  545. res=1;
  546. #ifdef MALLOCDEBUG
  547. infof(data, "gethostbyname_r() uses %d bytes\n", step_size);
  548. #endif
  549. if(!res) {
  550. int offset;
  551. h=(struct hostent *)realloc(buf, step_size);
  552. offset=(long)h-(long)buf;
  553. hostcache_fixoffset(h, offset);
  554. buf=(int *)h;
  555. *bufp=(char *)buf;
  556. }
  557. else
  558. #endif
  559. #ifdef HAVE_GETHOSTBYNAME_R_3
  560. /* AIX, Digital Unix, HPUX 10, more? */
  561. if(CURL_NAMELOOKUP_SIZE >=
  562. (sizeof(struct hostent)+sizeof(struct hostent_data)))
  563. /* August 22nd, 2000: Albert Chin-A-Young brought an updated version
  564. * that should work! September 20: Richard Prescott worked on the buffer
  565. * size dilemma. */
  566. ret = gethostbyname_r(hostname,
  567. (struct hostent *)buf,
  568. (struct hostent_data *)((char *)buf + sizeof(struct hostent)));
  569. else
  570. ret = -1; /* failure, too smallish buffer size */
  571. /* result expected in h */
  572. h = (struct hostent*)buf;
  573. h_errnop= errno; /* we don't deal with this, but set it anyway */
  574. if(ret)
  575. #endif
  576. {
  577. infof(data, "gethostbyname_r(2) failed for %s\n", hostname);
  578. h = NULL; /* set return code to NULL */
  579. free(buf);
  580. *bufp=NULL;
  581. }
  582. #else
  583. else {
  584. if ((h = gethostbyname(hostname)) == NULL ) {
  585. infof(data, "gethostbyname(2) failed for %s\n", hostname);
  586. *bufp=NULL;
  587. }
  588. else
  589. {
  590. char *buf=(char *)malloc(CURL_NAMELOOKUP_SIZE);
  591. /* we make a copy of the hostent right now, right here, as the
  592. static one we got a pointer to might get removed when we don't
  593. want/expect that */
  594. h = pack_hostent(&buf, h);
  595. *bufp=(char *)buf;
  596. }
  597. #endif
  598. }
  599. return (h);
  600. }
  601. #endif /* end of IPv4-specific code */
  602. /*
  603. * local variables:
  604. * eval: (load-file "../curl-mode.el")
  605. * end:
  606. * vim600: fdm=marker
  607. * vim: et sw=2 ts=2 sts=2 tw=78
  608. */