1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2011, 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
23#include "setup.h"
24
25#ifdef HAVE_SYS_SOCKET_H
26#include <sys/socket.h>
27#endif
28#ifdef HAVE_NETINET_IN_H
29#include <netinet/in.h>
30#endif
31#ifdef HAVE_NETDB_H
32#include <netdb.h>
33#endif
34#ifdef HAVE_ARPA_INET_H
35#include <arpa/inet.h>
36#endif
37#ifdef HAVE_UNISTD_H
38#include <unistd.h>     /* for the close() proto */
39#endif
40#ifdef __VMS
41#include <in.h>
42#include <inet.h>
43#endif
44
45#ifdef HAVE_PROCESS_H
46#include <process.h>
47#endif
48
49#include "urldata.h"
50#include "sendf.h"
51#include "hostip.h"
52#include "hash.h"
53#include "share.h"
54#include "strerror.h"
55#include "url.h"
56
57#define _MPRINTF_REPLACE /* use our functions only */
58#include <curl/mprintf.h>
59
60#include "curl_memory.h"
61/* The last #include file should be: */
62#include "memdebug.h"
63
64/***********************************************************************
65 * Only for builds using asynchronous name resolves
66 **********************************************************************/
67#ifdef CURLRES_ASYNCH
68
69/*
70 * Curl_addrinfo_callback() gets called by ares, gethostbyname_thread()
71 * or getaddrinfo_thread() when we got the name resolved (or not!).
72 *
73 * If the status argument is CURL_ASYNC_SUCCESS, this function takes
74 * ownership of the Curl_addrinfo passed, storing the resolved data
75 * in the DNS cache.
76 *
77 * The storage operation locks and unlocks the DNS cache.
78 */
79CURLcode Curl_addrinfo_callback(struct connectdata *conn,
80                                int status,
81                                struct Curl_addrinfo *ai)
82{
83  struct Curl_dns_entry *dns = NULL;
84  CURLcode rc = CURLE_OK;
85
86  conn->async.status = status;
87
88  if(CURL_ASYNC_SUCCESS == status) {
89    if(ai) {
90      struct SessionHandle *data = conn->data;
91
92      if(data->share)
93        Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
94
95      dns = Curl_cache_addr(data, ai,
96                            conn->async.hostname,
97                            conn->async.port);
98      if(!dns) {
99        /* failed to store, cleanup and return error */
100        Curl_freeaddrinfo(ai);
101        rc = CURLE_OUT_OF_MEMORY;
102      }
103
104      if(data->share)
105        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
106    }
107    else {
108      rc = CURLE_OUT_OF_MEMORY;
109    }
110  }
111
112  conn->async.dns = dns;
113
114 /* Set async.done TRUE last in this function since it may be used multi-
115    threaded and once this is TRUE the other thread may read fields from the
116    async struct */
117  conn->async.done = TRUE;
118
119  /* ipv4: The input hostent struct will be freed by ares when we return from
120     this function */
121  return rc;
122}
123
124/* Call this function after Curl_connect() has returned async=TRUE and
125   then a successful name resolve has been received.
126
127   Note: this function disconnects and frees the conn data in case of
128   resolve failure */
129CURLcode Curl_async_resolved(struct connectdata *conn,
130                             bool *protocol_done)
131{
132  CURLcode code;
133
134  if(conn->async.dns) {
135    conn->dns_entry = conn->async.dns;
136    conn->async.dns = NULL;
137  }
138
139  code = Curl_setup_conn(conn, protocol_done);
140
141  if(code)
142    /* We're not allowed to return failure with memory left allocated
143       in the connectdata struct, free those here */
144    Curl_disconnect(conn, FALSE); /* close the connection */
145
146  return code;
147}
148
149/*
150 * Curl_getaddrinfo() is the generic low-level name resolve API within this
151 * source file. There are several versions of this function - for different
152 * name resolve layers (selected at build-time). They all take this same set
153 * of arguments
154 */
155Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
156                                const char *hostname,
157                                int port,
158                                int *waitp)
159{
160  return Curl_resolver_getaddrinfo(conn, hostname, port, waitp);
161}
162
163#endif /* CURLRES_ASYNCH */
164