| 1 | /*************************************************************************** | 
| 2 |  *                                  _   _ ____  _ | 
| 3 |  *  Project                     ___| | | |  _ \| | | 
| 4 |  *                             / __| | | | |_) | | | 
| 5 |  *                            | (__| |_| |  _ <| |___ | 
| 6 |  *                             \___|\___/|_| \_\_____| | 
| 7 |  * | 
| 8 |  * Copyright (C) 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.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 |  * SPDX-License-Identifier: curl | 
| 22 |  * | 
| 23 |  ***************************************************************************/ | 
| 24 |  | 
| 25 | #include "curl_setup.h" | 
| 26 |  | 
| 27 | /*********************************************************************** | 
| 28 |  * Only for builds using asynchronous name resolves | 
| 29 |  **********************************************************************/ | 
| 30 | #ifdef CURLRES_ASYNCH | 
| 31 |  | 
| 32 | #ifdef HAVE_NETINET_IN_H | 
| 33 | #include <netinet/in.h> | 
| 34 | #endif | 
| 35 | #ifdef HAVE_NETDB_H | 
| 36 | #include <netdb.h> | 
| 37 | #endif | 
| 38 | #ifdef HAVE_ARPA_INET_H | 
| 39 | #include <arpa/inet.h> | 
| 40 | #endif | 
| 41 | #ifdef __VMS | 
| 42 | #include <in.h> | 
| 43 | #include <inet.h> | 
| 44 | #endif | 
| 45 |  | 
| 46 | #include "urldata.h" | 
| 47 | #include "sendf.h" | 
| 48 | #include "hostip.h" | 
| 49 | #include "hash.h" | 
| 50 | #include "share.h" | 
| 51 | #include "url.h" | 
| 52 | #include "curl_memory.h" | 
| 53 | /* The last #include file should be: */ | 
| 54 | #include "memdebug.h" | 
| 55 |  | 
| 56 | /* | 
| 57 |  * Curl_addrinfo_callback() gets called by ares, gethostbyname_thread() | 
| 58 |  * or getaddrinfo_thread() when we got the name resolved (or not!). | 
| 59 |  * | 
| 60 |  * If the status argument is CURL_ASYNC_SUCCESS, this function takes | 
| 61 |  * ownership of the Curl_addrinfo passed, storing the resolved data | 
| 62 |  * in the DNS cache. | 
| 63 |  * | 
| 64 |  * The storage operation locks and unlocks the DNS cache. | 
| 65 |  */ | 
| 66 | CURLcode Curl_addrinfo_callback(struct Curl_easy *data, | 
| 67 |                                 int status, | 
| 68 |                                 struct Curl_addrinfo *ai) | 
| 69 | { | 
| 70 |   struct Curl_dns_entry *dns = NULL; | 
| 71 |   CURLcode result = CURLE_OK; | 
| 72 |  | 
| 73 |   data->state.async.status = status; | 
| 74 |  | 
| 75 |   if(CURL_ASYNC_SUCCESS == status) { | 
| 76 |     if(ai) { | 
| 77 |       if(data->share) | 
| 78 |         Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); | 
| 79 |  | 
| 80 |       dns = Curl_cache_addr(data, addr: ai, | 
| 81 |                             hostname: data->state.async.hostname, hostlen: 0, | 
| 82 |                             port: data->state.async.port); | 
| 83 |       if(data->share) | 
| 84 |         Curl_share_unlock(data, CURL_LOCK_DATA_DNS); | 
| 85 |  | 
| 86 |       if(!dns) { | 
| 87 |         /* failed to store, cleanup and return error */ | 
| 88 |         Curl_freeaddrinfo(cahead: ai); | 
| 89 |         result = CURLE_OUT_OF_MEMORY; | 
| 90 |       } | 
| 91 |     } | 
| 92 |     else { | 
| 93 |       result = CURLE_OUT_OF_MEMORY; | 
| 94 |     } | 
| 95 |   } | 
| 96 |  | 
| 97 |   data->state.async.dns = dns; | 
| 98 |  | 
| 99 |  /* Set async.done TRUE last in this function since it may be used multi- | 
| 100 |     threaded and once this is TRUE the other thread may read fields from the | 
| 101 |     async struct */ | 
| 102 |   data->state.async.done = TRUE; | 
| 103 |  | 
| 104 |   /* IPv4: The input hostent struct will be freed by ares when we return from | 
| 105 |      this function */ | 
| 106 |   return result; | 
| 107 | } | 
| 108 |  | 
| 109 | /* | 
| 110 |  * Curl_getaddrinfo() is the generic low-level name resolve API within this | 
| 111 |  * source file. There are several versions of this function - for different | 
| 112 |  * name resolve layers (selected at build-time). They all take this same set | 
| 113 |  * of arguments | 
| 114 |  */ | 
| 115 | struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data, | 
| 116 |                                        const char *hostname, | 
| 117 |                                        int port, | 
| 118 |                                        int *waitp) | 
| 119 | { | 
| 120 |   return Curl_resolver_getaddrinfo(data, hostname, port, waitp); | 
| 121 | } | 
| 122 |  | 
| 123 | #endif /* CURLRES_ASYNCH */ | 
| 124 |  |