hostares.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2010, 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 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. ***************************************************************************/
  22. #include "setup.h"
  23. #include <string.h>
  24. #ifdef HAVE_LIMITS_H
  25. #include <limits.h>
  26. #endif
  27. #ifdef HAVE_SYS_SOCKET_H
  28. #include <sys/socket.h>
  29. #endif
  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 HAVE_STDLIB_H
  40. #include <stdlib.h> /* required for free() prototypes */
  41. #endif
  42. #ifdef HAVE_UNISTD_H
  43. #include <unistd.h> /* for the close() proto */
  44. #endif
  45. #ifdef __VMS
  46. #include <in.h>
  47. #include <inet.h>
  48. #include <stdlib.h>
  49. #endif
  50. #ifdef HAVE_PROCESS_H
  51. #include <process.h>
  52. #endif
  53. #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
  54. #undef in_addr_t
  55. #define in_addr_t unsigned long
  56. #endif
  57. #include "urldata.h"
  58. #include "sendf.h"
  59. #include "hostip.h"
  60. #include "hash.h"
  61. #include "share.h"
  62. #include "strerror.h"
  63. #include "url.h"
  64. #include "multiif.h"
  65. #include "inet_pton.h"
  66. #include "connect.h"
  67. #include "select.h"
  68. #include "progress.h"
  69. #define _MPRINTF_REPLACE /* use our functions only */
  70. #include <curl/mprintf.h>
  71. #include "curl_memory.h"
  72. /* The last #include file should be: */
  73. #include "memdebug.h"
  74. /***********************************************************************
  75. * Only for ares-enabled builds
  76. **********************************************************************/
  77. #ifdef CURLRES_ARES
  78. /*
  79. * Curl_resolv_fdset() is called when someone from the outside world (using
  80. * curl_multi_fdset()) wants to get our fd_set setup and we're talking with
  81. * ares. The caller must make sure that this function is only called when we
  82. * have a working ares channel.
  83. *
  84. * Returns: CURLE_OK always!
  85. */
  86. int Curl_resolv_getsock(struct connectdata *conn,
  87. curl_socket_t *socks,
  88. int numsocks)
  89. {
  90. struct timeval maxtime;
  91. struct timeval timebuf;
  92. struct timeval *timeout;
  93. int max = ares_getsock(conn->data->state.areschannel,
  94. (ares_socket_t *)socks, numsocks);
  95. maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
  96. maxtime.tv_usec = 0;
  97. timeout = ares_timeout(conn->data->state.areschannel, &maxtime, &timebuf);
  98. Curl_expire(conn->data,
  99. (timeout->tv_sec * 1000) + (timeout->tv_usec/1000));
  100. return max;
  101. }
  102. /*
  103. * waitperform()
  104. *
  105. * 1) Ask ares what sockets it currently plays with, then
  106. * 2) wait for the timeout period to check for action on ares' sockets.
  107. * 3) tell ares to act on all the sockets marked as "with action"
  108. *
  109. * return number of sockets it worked on
  110. */
  111. static int waitperform(struct connectdata *conn, int timeout_ms)
  112. {
  113. struct SessionHandle *data = conn->data;
  114. int nfds;
  115. int bitmask;
  116. ares_socket_t socks[ARES_GETSOCK_MAXNUM];
  117. struct pollfd pfd[ARES_GETSOCK_MAXNUM];
  118. int i;
  119. int num = 0;
  120. bitmask = ares_getsock(data->state.areschannel, socks, ARES_GETSOCK_MAXNUM);
  121. for(i=0; i < ARES_GETSOCK_MAXNUM; i++) {
  122. pfd[i].events = 0;
  123. pfd[i].revents = 0;
  124. if(ARES_GETSOCK_READABLE(bitmask, i)) {
  125. pfd[i].fd = socks[i];
  126. pfd[i].events |= POLLRDNORM|POLLIN;
  127. }
  128. if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
  129. pfd[i].fd = socks[i];
  130. pfd[i].events |= POLLWRNORM|POLLOUT;
  131. }
  132. if(pfd[i].events != 0)
  133. num++;
  134. else
  135. break;
  136. }
  137. if(num)
  138. nfds = Curl_poll(pfd, num, timeout_ms);
  139. else
  140. nfds = 0;
  141. if(!nfds)
  142. /* Call ares_process() unconditonally here, even if we simply timed out
  143. above, as otherwise the ares name resolve won't timeout! */
  144. ares_process_fd(data->state.areschannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
  145. else {
  146. /* move through the descriptors and ask for processing on them */
  147. for(i=0; i < num; i++)
  148. ares_process_fd(data->state.areschannel,
  149. pfd[i].revents & (POLLRDNORM|POLLIN)?
  150. pfd[i].fd:ARES_SOCKET_BAD,
  151. pfd[i].revents & (POLLWRNORM|POLLOUT)?
  152. pfd[i].fd:ARES_SOCKET_BAD);
  153. }
  154. return nfds;
  155. }
  156. /*
  157. * Curl_is_resolved() is called repeatedly to check if a previous name resolve
  158. * request has completed. It should also make sure to time-out if the
  159. * operation seems to take too long.
  160. *
  161. * Returns normal CURLcode errors.
  162. */
  163. CURLcode Curl_is_resolved(struct connectdata *conn,
  164. struct Curl_dns_entry **dns)
  165. {
  166. struct SessionHandle *data = conn->data;
  167. *dns = NULL;
  168. waitperform(conn, 0);
  169. if(conn->async.done) {
  170. /* we're done, kill the ares handle */
  171. if(!conn->async.dns) {
  172. failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
  173. ares_strerror(conn->async.status));
  174. return CURLE_COULDNT_RESOLVE_HOST;
  175. }
  176. *dns = conn->async.dns;
  177. }
  178. return CURLE_OK;
  179. }
  180. /*
  181. * Curl_wait_for_resolv() waits for a resolve to finish. This function should
  182. * be avoided since using this risk getting the multi interface to "hang".
  183. *
  184. * If 'entry' is non-NULL, make it point to the resolved dns entry
  185. *
  186. * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
  187. * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
  188. */
  189. CURLcode Curl_wait_for_resolv(struct connectdata *conn,
  190. struct Curl_dns_entry **entry)
  191. {
  192. CURLcode rc=CURLE_OK;
  193. struct SessionHandle *data = conn->data;
  194. long timeout;
  195. struct timeval now = Curl_tvnow();
  196. timeout = Curl_timeleft(conn, &now, TRUE);
  197. if(!timeout)
  198. timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
  199. /* Wait for the name resolve query to complete. */
  200. for(;;) {
  201. struct timeval *tvp, tv, store;
  202. long timediff;
  203. int itimeout;
  204. int timeout_ms;
  205. itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
  206. store.tv_sec = itimeout/1000;
  207. store.tv_usec = (itimeout%1000)*1000;
  208. tvp = ares_timeout(data->state.areschannel, &store, &tv);
  209. /* use the timeout period ares returned to us above if less than one
  210. second is left, otherwise just use 1000ms to make sure the progress
  211. callback gets called frequent enough */
  212. if(!tvp->tv_sec)
  213. timeout_ms = (int)(tvp->tv_usec/1000);
  214. else
  215. timeout_ms = 1000;
  216. waitperform(conn, timeout_ms);
  217. if(conn->async.done)
  218. break;
  219. if(Curl_pgrsUpdate(conn)) {
  220. rc = CURLE_ABORTED_BY_CALLBACK;
  221. timeout = -1; /* trigger the cancel below */
  222. }
  223. else {
  224. struct timeval now2 = Curl_tvnow();
  225. timediff = Curl_tvdiff(now2, now); /* spent time */
  226. timeout -= timediff?timediff:1; /* always deduct at least 1 */
  227. now = now2; /* for next loop */
  228. }
  229. if(timeout < 0) {
  230. /* our timeout, so we cancel the ares operation */
  231. ares_cancel(data->state.areschannel);
  232. break;
  233. }
  234. }
  235. /* Operation complete, if the lookup was successful we now have the entry
  236. in the cache. */
  237. if(entry)
  238. *entry = conn->async.dns;
  239. if(!conn->async.dns) {
  240. /* a name was not resolved */
  241. if((timeout < 0) || (conn->async.status == ARES_ETIMEOUT)) {
  242. if (conn->bits.httpproxy) {
  243. failf(data, "Resolving proxy timed out: %s", conn->proxy.dispname);
  244. rc = CURLE_COULDNT_RESOLVE_PROXY;
  245. }
  246. else {
  247. failf(data, "Resolving host timed out: %s", conn->host.dispname);
  248. rc = CURLE_COULDNT_RESOLVE_HOST;
  249. }
  250. }
  251. else if(conn->async.done) {
  252. if (conn->bits.httpproxy) {
  253. failf(data, "Could not resolve proxy: %s (%s)", conn->proxy.dispname,
  254. ares_strerror(conn->async.status));
  255. rc = CURLE_COULDNT_RESOLVE_PROXY;
  256. }
  257. else {
  258. failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
  259. ares_strerror(conn->async.status));
  260. rc = CURLE_COULDNT_RESOLVE_HOST;
  261. }
  262. }
  263. else
  264. rc = CURLE_OPERATION_TIMEDOUT;
  265. /* close the connection, since we can't return failure here without
  266. cleaning up this connection properly */
  267. conn->bits.close = TRUE;
  268. }
  269. return rc;
  270. }
  271. /*
  272. * ares_query_completed_cb() is the callback that ares will call when
  273. * the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(),
  274. * when using ares, is completed either successfully or with failure.
  275. */
  276. static void ares_query_completed_cb(void *arg, /* (struct connectdata *) */
  277. int status,
  278. #ifdef HAVE_CARES_CALLBACK_TIMEOUTS
  279. int timeouts,
  280. #endif
  281. struct hostent *hostent)
  282. {
  283. struct connectdata *conn = (struct connectdata *)arg;
  284. struct Curl_addrinfo * ai = NULL;
  285. #ifdef HAVE_CARES_CALLBACK_TIMEOUTS
  286. (void)timeouts; /* ignored */
  287. #endif
  288. if (status == CURL_ASYNC_SUCCESS) {
  289. ai = Curl_he2ai(hostent, conn->async.port);
  290. }
  291. (void)Curl_addrinfo_callback(arg, status, ai);
  292. }
  293. /*
  294. * Curl_getaddrinfo() - when using ares
  295. *
  296. * Returns name information about the given hostname and port number. If
  297. * successful, the 'hostent' is returned and the forth argument will point to
  298. * memory we need to free after use. That memory *MUST* be freed with
  299. * Curl_freeaddrinfo(), nothing else.
  300. */
  301. Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
  302. const char *hostname,
  303. int port,
  304. int *waitp)
  305. {
  306. char *bufp;
  307. struct SessionHandle *data = conn->data;
  308. struct in_addr in;
  309. int family = PF_INET;
  310. #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
  311. struct in6_addr in6;
  312. #endif /* CURLRES_IPV6 */
  313. *waitp = 0; /* default to synchronous response */
  314. /* First check if this is an IPv4 address string */
  315. if(Curl_inet_pton(AF_INET, hostname, &in) > 0) {
  316. /* This is a dotted IP address 123.123.123.123-style */
  317. return Curl_ip2addr(AF_INET, &in, hostname, port);
  318. }
  319. #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
  320. /* Otherwise, check if this is an IPv6 address string */
  321. if (Curl_inet_pton (AF_INET6, hostname, &in6) > 0) {
  322. /* This must be an IPv6 address literal. */
  323. return Curl_ip2addr(AF_INET6, &in6, hostname, port);
  324. }
  325. switch(conn->ip_version) {
  326. default:
  327. #if ARES_VERSION >= 0x010601
  328. family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older
  329. c-ares versions this just falls through and defaults
  330. to PF_INET */
  331. break;
  332. #endif
  333. case CURL_IPRESOLVE_V4:
  334. family = PF_INET;
  335. break;
  336. case CURL_IPRESOLVE_V6:
  337. family = PF_INET6;
  338. break;
  339. }
  340. #endif /* CURLRES_IPV6 */
  341. bufp = strdup(hostname);
  342. if(bufp) {
  343. Curl_safefree(conn->async.hostname);
  344. conn->async.hostname = bufp;
  345. conn->async.port = port;
  346. conn->async.done = FALSE; /* not done */
  347. conn->async.status = 0; /* clear */
  348. conn->async.dns = NULL; /* clear */
  349. /* areschannel is already setup in the Curl_open() function */
  350. ares_gethostbyname(data->state.areschannel, hostname, family,
  351. (ares_host_callback)ares_query_completed_cb, conn);
  352. *waitp = 1; /* expect asynchronous response */
  353. }
  354. return NULL; /* no struct yet */
  355. }
  356. #endif /* CURLRES_ARES */