blob: 7202fa63978a08a4e57ce21697359ffeed6d7f54 [file] [log] [blame]
Kristian Monsen5ab50182010-05-14 18:53:44 +01001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07008 * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
Kristian Monsen5ab50182010-05-14 18:53:44 +01009 *
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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070023#include "curl_setup.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010024
Kristian Monsen5ab50182010-05-14 18:53:44 +010025#ifdef HAVE_NETINET_IN_H
26#include <netinet/in.h> /* <netinet/tcp.h> may need it */
27#endif
28#ifdef HAVE_SYS_UN_H
29#include <sys/un.h> /* for sockaddr_un */
30#endif
31#ifdef HAVE_NETINET_TCP_H
32#include <netinet/tcp.h> /* for TCP_NODELAY */
33#endif
34#ifdef HAVE_SYS_IOCTL_H
35#include <sys/ioctl.h>
36#endif
Kristian Monsen5ab50182010-05-14 18:53:44 +010037#ifdef HAVE_NETDB_H
38#include <netdb.h>
39#endif
40#ifdef HAVE_FCNTL_H
41#include <fcntl.h>
42#endif
43#ifdef HAVE_ARPA_INET_H
44#include <arpa/inet.h>
45#endif
Kristian Monsen5ab50182010-05-14 18:53:44 +010046
47#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
48#include <sys/filio.h>
49#endif
50#ifdef NETWARE
51#undef in_addr_t
52#define in_addr_t unsigned long
53#endif
54#ifdef __VMS
55#include <in.h>
56#include <inet.h>
57#endif
58
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070059#include "curl_printf.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010060#include "urldata.h"
61#include "sendf.h"
62#include "if2ip.h"
63#include "strerror.h"
64#include "connect.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010065#include "select.h"
66#include "url.h" /* for Curl_safefree() */
67#include "multiif.h"
68#include "sockaddr.h" /* required for Curl_sockaddr_storage */
69#include "inet_ntop.h"
70#include "inet_pton.h"
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070071#include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
Kristian Monsen5ab50182010-05-14 18:53:44 +010072#include "progress.h"
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070073#include "warnless.h"
74#include "conncache.h"
75#include "multihandle.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010076
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070077/* The last #include files should be: */
78#include "curl_memory.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010079#include "memdebug.h"
80
81#ifdef __SYMBIAN32__
82/* This isn't actually supported under Symbian OS */
83#undef SO_NOSIGPIPE
84#endif
85
Kristian Monsen5ab50182010-05-14 18:53:44 +010086static bool verifyconnect(curl_socket_t sockfd, int *error);
87
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070088#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
89/* DragonFlyBSD and Windows use millisecond units */
90#define KEEPALIVE_FACTOR(x) (x *= 1000)
91#else
92#define KEEPALIVE_FACTOR(x)
93#endif
94
95#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
96#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
97
98struct tcp_keepalive {
99 u_long onoff;
100 u_long keepalivetime;
101 u_long keepaliveinterval;
102};
103#endif
104
105static void
106tcpkeepalive(struct SessionHandle *data,
107 curl_socket_t sockfd)
108{
109 int optval = data->set.tcp_keepalive?1:0;
110
111 /* only set IDLE and INTVL if setting KEEPALIVE is successful */
112 if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
113 (void *)&optval, sizeof(optval)) < 0) {
114 infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd);
115 }
116 else {
117#if defined(SIO_KEEPALIVE_VALS)
118 struct tcp_keepalive vals;
119 DWORD dummy;
120 vals.onoff = 1;
121 optval = curlx_sltosi(data->set.tcp_keepidle);
122 KEEPALIVE_FACTOR(optval);
123 vals.keepalivetime = optval;
124 optval = curlx_sltosi(data->set.tcp_keepintvl);
125 KEEPALIVE_FACTOR(optval);
126 vals.keepaliveinterval = optval;
127 if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
128 NULL, 0, &dummy, NULL, NULL) != 0) {
129 infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
130 (int)sockfd, WSAGetLastError());
131 }
132#else
133#ifdef TCP_KEEPIDLE
134 optval = curlx_sltosi(data->set.tcp_keepidle);
135 KEEPALIVE_FACTOR(optval);
136 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
137 (void *)&optval, sizeof(optval)) < 0) {
138 infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd);
139 }
140#endif
141#ifdef TCP_KEEPINTVL
142 optval = curlx_sltosi(data->set.tcp_keepintvl);
143 KEEPALIVE_FACTOR(optval);
144 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
145 (void *)&optval, sizeof(optval)) < 0) {
146 infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd);
147 }
148#endif
149#ifdef TCP_KEEPALIVE
150 /* Mac OS X style */
151 optval = curlx_sltosi(data->set.tcp_keepidle);
152 KEEPALIVE_FACTOR(optval);
153 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
154 (void *)&optval, sizeof(optval)) < 0) {
155 infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd);
156 }
157#endif
158#endif
159 }
160}
161
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700162static CURLcode
Kristian Monsen5ab50182010-05-14 18:53:44 +0100163singleipconnect(struct connectdata *conn,
164 const Curl_addrinfo *ai, /* start connecting to this */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700165 curl_socket_t *sock);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100166
167/*
168 * Curl_timeleft() returns the amount of milliseconds left allowed for the
169 * transfer/connection. If the value is negative, the timeout time has already
170 * elapsed.
171 *
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700172 * The start time is stored in progress.t_startsingle - as set with
173 * Curl_pgrsTime(..., TIMER_STARTSINGLE);
174 *
Kristian Monsen5ab50182010-05-14 18:53:44 +0100175 * If 'nowp' is non-NULL, it points to the current time.
176 * 'duringconnect' is FALSE if not during a connect, as then of course the
177 * connect timeout is not taken into account!
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700178 *
179 * @unittest: 1303
Kristian Monsen5ab50182010-05-14 18:53:44 +0100180 */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700181long Curl_timeleft(struct SessionHandle *data,
Kristian Monsen5ab50182010-05-14 18:53:44 +0100182 struct timeval *nowp,
183 bool duringconnect)
184{
Kristian Monsen5ab50182010-05-14 18:53:44 +0100185 int timeout_set = 0;
186 long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
187 struct timeval now;
188
189 /* if a timeout is set, use the most restrictive one */
190
191 if(data->set.timeout > 0)
192 timeout_set |= 1;
193 if(duringconnect && (data->set.connecttimeout > 0))
194 timeout_set |= 2;
195
196 switch (timeout_set) {
197 case 1:
198 timeout_ms = data->set.timeout;
199 break;
200 case 2:
201 timeout_ms = data->set.connecttimeout;
202 break;
203 case 3:
204 if(data->set.timeout < data->set.connecttimeout)
205 timeout_ms = data->set.timeout;
206 else
207 timeout_ms = data->set.connecttimeout;
208 break;
209 default:
210 /* use the default */
211 if(!duringconnect)
212 /* if we're not during connect, there's no default timeout so if we're
213 at zero we better just return zero and not make it a negative number
214 by the math below */
215 return 0;
216 break;
217 }
218
219 if(!nowp) {
220 now = Curl_tvnow();
221 nowp = &now;
222 }
223
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700224 /* subtract elapsed time */
225 if(duringconnect)
226 /* since this most recent connect started */
227 timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
228 else
229 /* since the entire operation started */
230 timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700231 if(!timeout_ms)
232 /* avoid returning 0 as that means no timeout! */
233 return -1;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100234
235 return timeout_ms;
236}
237
Kristian Monsen5ab50182010-05-14 18:53:44 +0100238static CURLcode bindlocal(struct connectdata *conn,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700239 curl_socket_t sockfd, int af, unsigned int scope)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100240{
241 struct SessionHandle *data = conn->data;
242
243 struct Curl_sockaddr_storage sa;
244 struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
245 curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
246 struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
247#ifdef ENABLE_IPV6
248 struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
249#endif
250
251 struct Curl_dns_entry *h=NULL;
252 unsigned short port = data->set.localport; /* use this port number, 0 for
253 "random" */
254 /* how many port numbers to try to bind to, increasing one at a time */
255 int portnum = data->set.localportrange;
256 const char *dev = data->set.str[STRING_DEVICE];
257 int error;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100258
259 /*************************************************************
260 * Select device to bind socket to
261 *************************************************************/
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700262 if(!dev && !port)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100263 /* no local kind of binding was requested */
264 return CURLE_OK;
265
266 memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
267
268 if(dev && (strlen(dev)<255) ) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700269 char myhost[256] = "";
270 int done = 0; /* -1 for error, 1 for address found */
271 bool is_interface = FALSE;
272 bool is_host = FALSE;
273 static const char *if_prefix = "if!";
274 static const char *host_prefix = "host!";
275
276 if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
277 dev += strlen(if_prefix);
278 is_interface = TRUE;
279 }
280 else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
281 dev += strlen(host_prefix);
282 is_host = TRUE;
283 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100284
285 /* interface */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700286 if(!is_host) {
287 switch(Curl_if2ip(af, scope, conn->scope_id, dev,
288 myhost, sizeof(myhost))) {
289 case IF2IP_NOT_FOUND:
290 if(is_interface) {
291 /* Do not fall back to treating it as a host name */
292 failf(data, "Couldn't bind to interface '%s'", dev);
293 return CURLE_INTERFACE_FAILED;
294 }
295 break;
296 case IF2IP_AF_NOT_SUPPORTED:
297 /* Signal the caller to try another address family if available */
298 return CURLE_UNSUPPORTED_PROTOCOL;
299 case IF2IP_FOUND:
300 is_interface = TRUE;
301 /*
302 * We now have the numerical IP address in the 'myhost' buffer
303 */
304 infof(data, "Local Interface %s is ip %s using address family %i\n",
305 dev, myhost, af);
306 done = 1;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100307
308#ifdef SO_BINDTODEVICE
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700309 /* I am not sure any other OSs than Linux that provide this feature,
310 * and at the least I cannot test. --Ben
311 *
312 * This feature allows one to tightly bind the local socket to a
313 * particular interface. This will force even requests to other
314 * local interfaces to go out the external interface.
315 *
316 *
317 * Only bind to the interface when specified as interface, not just
318 * as a hostname or ip address.
319 */
320 if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
321 dev, (curl_socklen_t)strlen(dev)+1) != 0) {
322 error = SOCKERRNO;
323 infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
324 " will do regular bind\n",
325 dev, error, Curl_strerror(conn, error));
326 /* This is typically "errno 1, error: Operation not permitted" if
327 you're not running as root or another suitable privileged
328 user */
329 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100330#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700331 break;
332 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100333 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700334 if(!is_interface) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100335 /*
336 * This was not an interface, resolve the name as a host name
337 * or IP number
338 *
339 * Temporarily force name resolution to use only the address type
340 * of the connection. The resolve functions should really be changed
341 * to take a type parameter instead.
342 */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700343 long ipver = conn->ip_version;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100344 int rc;
345
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700346 if(af == AF_INET)
347 conn->ip_version = CURL_IPRESOLVE_V4;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100348#ifdef ENABLE_IPV6
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700349 else if(af == AF_INET6)
350 conn->ip_version = CURL_IPRESOLVE_V6;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100351#endif
352
353 rc = Curl_resolv(conn, dev, 0, &h);
354 if(rc == CURLRESOLV_PENDING)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700355 (void)Curl_resolver_wait_resolv(conn, &h);
356 conn->ip_version = ipver;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100357
358 if(h) {
359 /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
360 Curl_printable_address(h->addr, myhost, sizeof(myhost));
361 infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
362 dev, af, myhost, h->addr->ai_family);
363 Curl_resolv_unlock(data, h);
364 done = 1;
365 }
366 else {
367 /*
368 * provided dev was no interface (or interfaces are not supported
369 * e.g. solaris) no ip address and no domain we fail here
370 */
371 done = -1;
372 }
373 }
374
375 if(done > 0) {
376#ifdef ENABLE_IPV6
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700377 /* IPv6 address */
378 if(af == AF_INET6) {
379#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
380 char *scope_ptr = strchr(myhost, '%');
381 if(scope_ptr)
382 *(scope_ptr++) = 0;
383#endif
384 if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
385 si6->sin6_family = AF_INET6;
386 si6->sin6_port = htons(port);
387#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
388 if(scope_ptr)
389 /* The "myhost" string either comes from Curl_if2ip or from
390 Curl_printable_address. The latter returns only numeric scope
391 IDs and the former returns none at all. So the scope ID, if
392 present, is known to be numeric */
393 si6->sin6_scope_id = atoi(scope_ptr);
394#endif
395 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100396 sizeof_sa = sizeof(struct sockaddr_in6);
397 }
398 else
399#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700400 /* IPv4 address */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100401 if((af == AF_INET) &&
402 (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
403 si4->sin_family = AF_INET;
404 si4->sin_port = htons(port);
405 sizeof_sa = sizeof(struct sockaddr_in);
406 }
407 }
408
409 if(done < 1) {
410 failf(data, "Couldn't bind to '%s'", dev);
411 return CURLE_INTERFACE_FAILED;
412 }
413 }
414 else {
415 /* no device was given, prepare sa to match af's needs */
416#ifdef ENABLE_IPV6
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700417 if(af == AF_INET6) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100418 si6->sin6_family = AF_INET6;
419 si6->sin6_port = htons(port);
420 sizeof_sa = sizeof(struct sockaddr_in6);
421 }
422 else
423#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700424 if(af == AF_INET) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100425 si4->sin_family = AF_INET;
426 si4->sin_port = htons(port);
427 sizeof_sa = sizeof(struct sockaddr_in);
428 }
429 }
430
431 for(;;) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700432 if(bind(sockfd, sock, sizeof_sa) >= 0) {
433 /* we succeeded to bind */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100434 struct Curl_sockaddr_storage add;
435 curl_socklen_t size = sizeof(add);
436 memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
437 if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
438 data->state.os_errno = error = SOCKERRNO;
439 failf(data, "getsockname() failed with errno %d: %s",
440 error, Curl_strerror(conn, error));
441 return CURLE_INTERFACE_FAILED;
442 }
443 infof(data, "Local port: %hu\n", port);
444 conn->bits.bound = TRUE;
445 return CURLE_OK;
446 }
447
448 if(--portnum > 0) {
449 infof(data, "Bind to local port %hu failed, trying next\n", port);
450 port++; /* try next port */
451 /* We re-use/clobber the port variable here below */
452 if(sock->sa_family == AF_INET)
453 si4->sin_port = ntohs(port);
454#ifdef ENABLE_IPV6
455 else
456 si6->sin6_port = ntohs(port);
457#endif
458 }
459 else
460 break;
461 }
462
463 data->state.os_errno = error = SOCKERRNO;
464 failf(data, "bind failed with errno %d: %s",
465 error, Curl_strerror(conn, error));
466
467 return CURLE_INTERFACE_FAILED;
468}
469
470/*
471 * verifyconnect() returns TRUE if the connect really has happened.
472 */
473static bool verifyconnect(curl_socket_t sockfd, int *error)
474{
475 bool rc = TRUE;
476#ifdef SO_ERROR
477 int err = 0;
478 curl_socklen_t errSize = sizeof(err);
479
480#ifdef WIN32
481 /*
482 * In October 2003 we effectively nullified this function on Windows due to
483 * problems with it using all CPU in multi-threaded cases.
484 *
485 * In May 2004, we bring it back to offer more info back on connect failures.
486 * Gisle Vanem could reproduce the former problems with this function, but
487 * could avoid them by adding this SleepEx() call below:
488 *
489 * "I don't have Rational Quantify, but the hint from his post was
490 * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
491 * just Sleep(0) would be enough?) would release whatever
492 * mutex/critical-section the ntdll call is waiting on.
493 *
494 * Someone got to verify this on Win-NT 4.0, 2000."
495 */
496
497#ifdef _WIN32_WCE
498 Sleep(0);
499#else
500 SleepEx(0, FALSE);
501#endif
502
503#endif
504
505 if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
506 err = SOCKERRNO;
507#ifdef _WIN32_WCE
508 /* Old WinCE versions don't support SO_ERROR */
509 if(WSAENOPROTOOPT == err) {
510 SET_SOCKERRNO(0);
511 err = 0;
512 }
513#endif
514#ifdef __minix
515 /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
516 if(EBADIOCTL == err) {
517 SET_SOCKERRNO(0);
518 err = 0;
519 }
520#endif
521 if((0 == err) || (EISCONN == err))
522 /* we are connected, awesome! */
523 rc = TRUE;
524 else
525 /* This wasn't a successful connect */
526 rc = FALSE;
527 if(error)
528 *error = err;
529#else
530 (void)sockfd;
531 if(error)
532 *error = SOCKERRNO;
533#endif
534 return rc;
535}
536
537/* Used within the multi interface. Try next IP address, return TRUE if no
538 more address exists or error */
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700539static CURLcode trynextip(struct connectdata *conn,
540 int sockindex,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700541 int tempindex)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100542{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700543 const int other = tempindex ^ 1;
544 CURLcode result = CURLE_COULDNT_CONNECT;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100545
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700546 /* First clean up after the failed socket.
547 Don't close it yet to ensure that the next IP's socket gets a different
548 file descriptor, which can prevent bugs when the curl_multi_socket_action
549 interface is used with certain select() replacements such as kqueue. */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700550 curl_socket_t fd_to_close = conn->tempsock[tempindex];
551 conn->tempsock[tempindex] = CURL_SOCKET_BAD;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100552
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700553 if(sockindex == FIRSTSOCKET) {
554 Curl_addrinfo *ai = NULL;
555 int family = AF_UNSPEC;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100556
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700557 if(conn->tempaddr[tempindex]) {
558 /* find next address in the same protocol family */
559 family = conn->tempaddr[tempindex]->ai_family;
560 ai = conn->tempaddr[tempindex]->ai_next;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100561 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700562#ifdef ENABLE_IPV6
563 else if(conn->tempaddr[0]) {
564 /* happy eyeballs - try the other protocol family */
565 int firstfamily = conn->tempaddr[0]->ai_family;
566 family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
567 ai = conn->tempaddr[0]->ai_next;
568 }
569#endif
570
571 while(ai) {
572 if(conn->tempaddr[other]) {
573 /* we can safely skip addresses of the other protocol family */
574 while(ai && ai->ai_family != family)
575 ai = ai->ai_next;
576 }
577
578 if(ai) {
579 result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
580 if(result == CURLE_COULDNT_CONNECT) {
581 ai = ai->ai_next;
582 continue;
583 }
584
585 conn->tempaddr[tempindex] = ai;
586 }
587 break;
588 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100589 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700590
591 if(fd_to_close != CURL_SOCKET_BAD)
592 Curl_closesocket(conn, fd_to_close);
593
594 return result;
595}
596
597/* Copies connection info into the session handle to make it available
598 when the session handle is no longer associated with a connection. */
599void Curl_persistconninfo(struct connectdata *conn)
600{
601 memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
602 memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
603 conn->data->info.conn_primary_port = conn->primary_port;
604 conn->data->info.conn_local_port = conn->local_port;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700605}
606
607/* retrieves ip address and port from a sockaddr structure */
608static bool getaddressinfo(struct sockaddr* sa, char* addr,
609 long* port)
610{
611 unsigned short us_port;
612 struct sockaddr_in* si = NULL;
613#ifdef ENABLE_IPV6
614 struct sockaddr_in6* si6 = NULL;
615#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700616#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
617 struct sockaddr_un* su = NULL;
618#endif
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700619
620 switch (sa->sa_family) {
621 case AF_INET:
622 si = (struct sockaddr_in*) sa;
623 if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700624 addr, MAX_IPADR_LEN)) {
625 us_port = ntohs(si->sin_port);
626 *port = us_port;
627 return TRUE;
628 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700629 break;
630#ifdef ENABLE_IPV6
631 case AF_INET6:
632 si6 = (struct sockaddr_in6*)sa;
633 if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700634 addr, MAX_IPADR_LEN)) {
635 us_port = ntohs(si6->sin6_port);
636 *port = us_port;
637 return TRUE;
638 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700639 break;
640#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700641#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
642 case AF_UNIX:
643 su = (struct sockaddr_un*)sa;
644 snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700645 *port = 0;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700646 return TRUE;
647#endif
648 default:
649 break;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700650 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700651
652 addr[0] = '\0';
653 *port = 0;
654
655 return FALSE;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100656}
657
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700658/* retrieves the start/end point information of a socket of an established
659 connection */
660void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
661{
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700662 curl_socklen_t len;
663 struct Curl_sockaddr_storage ssrem;
664 struct Curl_sockaddr_storage ssloc;
665 struct SessionHandle *data = conn->data;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700666
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700667 if(conn->socktype == SOCK_DGRAM)
668 /* there's no connection! */
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700669 return;
670
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700671 if(!conn->bits.reuse) {
672 int error;
673
674 len = sizeof(struct Curl_sockaddr_storage);
675 if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
676 error = SOCKERRNO;
677 failf(data, "getpeername() failed with errno %d: %s",
678 error, Curl_strerror(conn, error));
679 return;
680 }
681
682 len = sizeof(struct Curl_sockaddr_storage);
683 memset(&ssloc, 0, sizeof(ssloc));
684 if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
685 error = SOCKERRNO;
686 failf(data, "getsockname() failed with errno %d: %s",
687 error, Curl_strerror(conn, error));
688 return;
689 }
690
691 if(!getaddressinfo((struct sockaddr*)&ssrem,
692 conn->primary_ip, &conn->primary_port)) {
693 error = ERRNO;
694 failf(data, "ssrem inet_ntop() failed with errno %d: %s",
695 error, Curl_strerror(conn, error));
696 return;
697 }
698 memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
699
700 if(!getaddressinfo((struct sockaddr*)&ssloc,
701 conn->local_ip, &conn->local_port)) {
702 error = ERRNO;
703 failf(data, "ssloc inet_ntop() failed with errno %d: %s",
704 error, Curl_strerror(conn, error));
705 return;
706 }
707
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700708 }
709
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700710 /* persist connection info in session handle */
711 Curl_persistconninfo(conn);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700712}
713
Kristian Monsen5ab50182010-05-14 18:53:44 +0100714/*
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700715 * Curl_is_connected() checks if the socket has connected.
Kristian Monsen5ab50182010-05-14 18:53:44 +0100716 */
717
718CURLcode Curl_is_connected(struct connectdata *conn,
719 int sockindex,
720 bool *connected)
721{
Kristian Monsen5ab50182010-05-14 18:53:44 +0100722 struct SessionHandle *data = conn->data;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700723 CURLcode result = CURLE_OK;
724 long allow;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700725 int error = 0;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700726 struct timeval now;
727 int rc;
728 int i;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100729
730 DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
731
732 *connected = FALSE; /* a very negative world view is best */
733
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700734 if(conn->bits.tcpconnect[sockindex]) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100735 /* we are connected already! */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100736 *connected = TRUE;
737 return CURLE_OK;
738 }
739
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700740 now = Curl_tvnow();
741
Kristian Monsen5ab50182010-05-14 18:53:44 +0100742 /* figure out how long time we have left to connect */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700743 allow = Curl_timeleft(data, &now, TRUE);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100744
745 if(allow < 0) {
746 /* time-out, bail out, go home */
747 failf(data, "Connection time-out");
748 return CURLE_OPERATION_TIMEDOUT;
749 }
750
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700751 for(i=0; i<2; i++) {
752 const int other = i ^ 1;
753 if(conn->tempsock[i] == CURL_SOCKET_BAD)
754 continue;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100755
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700756#ifdef mpeix
757 /* Call this function once now, and ignore the results. We do this to
758 "clear" the error state on the socket so that we can later read it
759 reliably. This is reported necessary on the MPE/iX operating system. */
760 (void)verifyconnect(conn->tempsock[i], NULL);
761#endif
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700762
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700763 /* check socket for connect */
764 rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
765
766 if(rc == 0) { /* no connection yet */
767 if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
768 infof(data, "After %ldms connect time, move on!\n",
769 conn->timeoutms_per_addr);
770 error = ETIMEDOUT;
771 }
772
773 /* should we try another protocol family? */
774 if(i == 0 && conn->tempaddr[1] == NULL &&
775 curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
776 trynextip(conn, sockindex, 1);
777 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100778 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700779 else if(rc == CURL_CSELECT_OUT) {
780 if(verifyconnect(conn->tempsock[i], &error)) {
781 /* we are connected with TCP, awesome! */
782
783 /* use this socket from now on */
784 conn->sock[sockindex] = conn->tempsock[i];
785 conn->ip_addr = conn->tempaddr[i];
786 conn->tempsock[i] = CURL_SOCKET_BAD;
787
788 /* close the other socket, if open */
789 if(conn->tempsock[other] != CURL_SOCKET_BAD) {
790 Curl_closesocket(conn, conn->tempsock[other]);
791 conn->tempsock[other] = CURL_SOCKET_BAD;
792 }
793
794 /* see if we need to do any proxy magic first once we connected */
795 result = Curl_connected_proxy(conn, sockindex);
796 if(result)
797 return result;
798
799 conn->bits.tcpconnect[sockindex] = TRUE;
800
801 *connected = TRUE;
802 if(sockindex == FIRSTSOCKET)
803 Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
804 Curl_updateconninfo(conn, conn->sock[sockindex]);
805 Curl_verboseconnect(conn);
806
807 return CURLE_OK;
808 }
809 else
810 infof(data, "Connection failed\n");
Kristian Monsen5ab50182010-05-14 18:53:44 +0100811 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700812 else if(rc & CURL_CSELECT_ERR)
813 (void)verifyconnect(conn->tempsock[i], &error);
814
815 /*
816 * The connection failed here, we should attempt to connect to the "next
817 * address" for the given host. But first remember the latest error.
818 */
819 if(error) {
820 data->state.os_errno = error;
821 SET_SOCKERRNO(error);
822 if(conn->tempaddr[i]) {
823 CURLcode status;
824 char ipaddress[MAX_IPADR_LEN];
825 Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
826 infof(data, "connect to %s port %ld failed: %s\n",
827 ipaddress, conn->port, Curl_strerror(conn, error));
828
829 conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
830 allow : allow / 2;
831
832 status = trynextip(conn, sockindex, i);
833 if(status != CURLE_COULDNT_CONNECT
834 || conn->tempsock[other] == CURL_SOCKET_BAD)
835 /* the last attempt failed and no other sockets remain open */
836 result = status;
837 }
838 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100839 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700840
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700841 if(result) {
842 /* no more addresses to try */
843
844 /* if the first address family runs out of addresses to try before
845 the happy eyeball timeout, go ahead and try the next family now */
846 if(conn->tempaddr[1] == NULL) {
847 result = trynextip(conn, sockindex, 1);
848 if(!result)
849 return result;
850 }
851
852 failf(data, "Failed to connect to %s port %ld: %s",
853 conn->bits.proxy?conn->proxy.name:conn->host.name,
854 conn->port, Curl_strerror(conn, error));
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700855 }
856
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700857 return result;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100858}
859
860static void tcpnodelay(struct connectdata *conn,
861 curl_socket_t sockfd)
862{
863#ifdef TCP_NODELAY
864 struct SessionHandle *data= conn->data;
865 curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700866 int level = IPPROTO_TCP;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100867
868#if 0
869 /* The use of getprotobyname() is disabled since it isn't thread-safe on
870 numerous systems. On these getprotobyname_r() should be used instead, but
871 that exists in at least one 4 arg version and one 5 arg version, and
872 since the proto number rarely changes anyway we now just use the hard
873 coded number. The "proper" fix would need a configure check for the
874 correct function much in the same style the gethostbyname_r versions are
875 detected. */
876 struct protoent *pe = getprotobyname("tcp");
877 if(pe)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700878 level = pe->p_proto;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100879#endif
880
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700881 if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
Kristian Monsen5ab50182010-05-14 18:53:44 +0100882 sizeof(onoff)) < 0)
883 infof(data, "Could not set TCP_NODELAY: %s\n",
884 Curl_strerror(conn, SOCKERRNO));
885 else
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700886 infof(data, "TCP_NODELAY set\n");
Kristian Monsen5ab50182010-05-14 18:53:44 +0100887#else
888 (void)conn;
889 (void)sockfd;
890#endif
891}
892
893#ifdef SO_NOSIGPIPE
894/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
895 sending data to a dead peer (instead of relying on the 4th argument to send
896 being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
897 systems? */
898static void nosigpipe(struct connectdata *conn,
899 curl_socket_t sockfd)
900{
901 struct SessionHandle *data= conn->data;
902 int onoff = 1;
903 if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
904 sizeof(onoff)) < 0)
905 infof(data, "Could not set SO_NOSIGPIPE: %s\n",
906 Curl_strerror(conn, SOCKERRNO));
907}
908#else
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700909#define nosigpipe(x,y) Curl_nop_stmt
Kristian Monsen5ab50182010-05-14 18:53:44 +0100910#endif
911
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700912#ifdef USE_WINSOCK
Kristian Monsen5ab50182010-05-14 18:53:44 +0100913/* When you run a program that uses the Windows Sockets API, you may
914 experience slow performance when you copy data to a TCP server.
915
916 http://support.microsoft.com/kb/823764
917
918 Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
919 Buffer Size
920
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700921 The problem described in this knowledge-base is applied only to pre-Vista
922 Windows. Following function trying to detect OS version and skips
923 SO_SNDBUF adjustment for Windows Vista and above.
Kristian Monsen5ab50182010-05-14 18:53:44 +0100924*/
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700925#define DETECT_OS_NONE 0
926#define DETECT_OS_PREVISTA 1
927#define DETECT_OS_VISTA_OR_LATER 2
928
Kristian Monsen5ab50182010-05-14 18:53:44 +0100929void Curl_sndbufset(curl_socket_t sockfd)
930{
931 int val = CURL_MAX_WRITE_SIZE + 32;
932 int curval = 0;
933 int curlen = sizeof(curval);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700934 DWORD majorVersion = 6;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100935
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700936 static int detectOsState = DETECT_OS_NONE;
937
938 if(detectOsState == DETECT_OS_NONE) {
939#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
940 (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
941 OSVERSIONINFO osver;
942
943 memset(&osver, 0, sizeof(osver));
944 osver.dwOSVersionInfoSize = sizeof(osver);
945
946 detectOsState = DETECT_OS_PREVISTA;
947 if(GetVersionEx(&osver)) {
948 if(osver.dwMajorVersion >= majorVersion)
949 detectOsState = DETECT_OS_VISTA_OR_LATER;
950 }
951#else
952 ULONGLONG majorVersionMask;
953 OSVERSIONINFOEX osver;
954
955 memset(&osver, 0, sizeof(osver));
956 osver.dwOSVersionInfoSize = sizeof(osver);
957 osver.dwMajorVersion = majorVersion;
958 majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION,
959 VER_GREATER_EQUAL);
960
961 if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask))
962 detectOsState = DETECT_OS_VISTA_OR_LATER;
963 else
964 detectOsState = DETECT_OS_PREVISTA;
965#endif
966 }
967
968 if(detectOsState == DETECT_OS_VISTA_OR_LATER)
969 return;
970
971 if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
972 if(curval > val)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100973 return;
974
975 setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
976}
977#endif
978
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700979/*
980 * singleipconnect()
981 *
982 * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
983 * CURL_SOCKET_BAD. Other errors will however return proper errors.
984 *
985 * singleipconnect() connects to the given IP only, and it may return without
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700986 * having connected.
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700987 */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700988static CURLcode singleipconnect(struct connectdata *conn,
989 const Curl_addrinfo *ai,
990 curl_socket_t *sockp)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100991{
992 struct Curl_sockaddr_ex addr;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100993 int rc;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700994 int error = 0;
995 bool isconnected = FALSE;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100996 struct SessionHandle *data = conn->data;
997 curl_socket_t sockfd;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700998 CURLcode result;
999 char ipaddress[MAX_IPADR_LEN];
1000 long port;
1001 bool is_tcp;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001002
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001003 *sockp = CURL_SOCKET_BAD;
1004
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001005 result = Curl_socket(conn, ai, &addr, &sockfd);
1006 if(result)
1007 /* Failed to create the socket, but still return OK since we signal the
1008 lack of socket as well. This allows the parent function to keep looping
1009 over alternative addresses/socket families etc. */
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001010 return CURLE_OK;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001011
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001012 /* store remote address and port used in this connection attempt */
1013 if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
1014 ipaddress, &port)) {
1015 /* malformed address or bug in inet_ntop, try next address */
1016 error = ERRNO;
1017 failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
1018 error, Curl_strerror(conn, error));
1019 Curl_closesocket(conn, sockfd);
1020 return CURLE_OK;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001021 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001022 infof(data, " Trying %s...\n", ipaddress);
1023
Kristian Monsen5ab50182010-05-14 18:53:44 +01001024#ifdef ENABLE_IPV6
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001025 is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
1026 addr.socktype == SOCK_STREAM;
1027#else
1028 is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001029#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001030 if(is_tcp && data->set.tcp_nodelay)
Kristian Monsen5ab50182010-05-14 18:53:44 +01001031 tcpnodelay(conn, sockfd);
1032
1033 nosigpipe(conn, sockfd);
1034
1035 Curl_sndbufset(sockfd);
1036
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001037 if(is_tcp && data->set.tcp_keepalive)
1038 tcpkeepalive(data, sockfd);
1039
Kristian Monsen5ab50182010-05-14 18:53:44 +01001040 if(data->set.fsockopt) {
1041 /* activate callback for setting socket options */
1042 error = data->set.fsockopt(data->set.sockopt_client,
1043 sockfd,
1044 CURLSOCKTYPE_IPCXN);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001045
1046 if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
1047 isconnected = TRUE;
1048 else if(error) {
1049 Curl_closesocket(conn, sockfd); /* close the socket and bail out */
1050 return CURLE_ABORTED_BY_CALLBACK;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001051 }
1052 }
1053
1054 /* possibly bind the local end to an IP, interface or port */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001055 if(addr.family == AF_INET
1056#ifdef ENABLE_IPV6
1057 || addr.family == AF_INET6
1058#endif
1059 ) {
1060 result = bindlocal(conn, sockfd, addr.family,
1061 Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
1062 if(result) {
1063 Curl_closesocket(conn, sockfd); /* close socket and bail out */
1064 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
1065 /* The address family is not supported on this interface.
1066 We can continue trying addresses */
1067 return CURLE_COULDNT_CONNECT;
1068 }
1069 return result;
1070 }
Kristian Monsen5ab50182010-05-14 18:53:44 +01001071 }
1072
1073 /* set socket non-blocking */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001074 (void)curlx_nonblock(sockfd, TRUE);
1075
1076 conn->connecttime = Curl_tvnow();
1077 if(conn->num_addr > 1)
1078 Curl_expire_latest(data, conn->timeoutms_per_addr);
Kristian Monsen5ab50182010-05-14 18:53:44 +01001079
1080 /* Connect TCP sockets, bind UDP */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001081 if(!isconnected && (conn->socktype == SOCK_STREAM)) {
Kristian Monsen5ab50182010-05-14 18:53:44 +01001082 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001083 if(-1 == rc)
1084 error = SOCKERRNO;
1085 }
1086 else {
1087 *sockp = sockfd;
1088 return CURLE_OK;
1089 }
1090
1091#ifdef ENABLE_IPV6
1092 conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
1093#endif
Kristian Monsen5ab50182010-05-14 18:53:44 +01001094
1095 if(-1 == rc) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001096 switch(error) {
Kristian Monsen5ab50182010-05-14 18:53:44 +01001097 case EINPROGRESS:
1098 case EWOULDBLOCK:
1099#if defined(EAGAIN)
1100#if (EAGAIN) != (EWOULDBLOCK)
1101 /* On some platforms EAGAIN and EWOULDBLOCK are the
1102 * same value, and on others they are different, hence
1103 * the odd #if
1104 */
1105 case EAGAIN:
1106#endif
1107#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001108 result = CURLE_OK;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001109 break;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001110
Kristian Monsen5ab50182010-05-14 18:53:44 +01001111 default:
1112 /* unknown error, fallthrough and try another address! */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001113 infof(data, "Immediate connect fail for %s: %s\n",
1114 ipaddress, Curl_strerror(conn, error));
Kristian Monsen5ab50182010-05-14 18:53:44 +01001115 data->state.os_errno = error;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001116
1117 /* connect failed */
1118 Curl_closesocket(conn, sockfd);
1119 result = CURLE_COULDNT_CONNECT;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001120 }
1121 }
1122
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001123 if(!result)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001124 *sockp = sockfd;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001125
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001126 return result;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001127}
1128
1129/*
1130 * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1131 * There might be more than one IP address to try out. Fill in the passed
1132 * pointer with the connected socket.
1133 */
1134
1135CURLcode Curl_connecthost(struct connectdata *conn, /* context */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001136 const struct Curl_dns_entry *remotehost)
Kristian Monsen5ab50182010-05-14 18:53:44 +01001137{
1138 struct SessionHandle *data = conn->data;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001139 struct timeval before = Curl_tvnow();
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001140 CURLcode result = CURLE_COULDNT_CONNECT;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001141
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001142 long timeout_ms = Curl_timeleft(data, &before, TRUE);
Kristian Monsen5ab50182010-05-14 18:53:44 +01001143
1144 if(timeout_ms < 0) {
1145 /* a precaution, no need to continue if time already is up */
1146 failf(data, "Connection time-out");
1147 return CURLE_OPERATION_TIMEDOUT;
1148 }
Kristian Monsen5ab50182010-05-14 18:53:44 +01001149
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001150 conn->num_addr = Curl_num_addresses(remotehost->addr);
1151 conn->tempaddr[0] = remotehost->addr;
1152 conn->tempaddr[1] = NULL;
1153 conn->tempsock[0] = CURL_SOCKET_BAD;
1154 conn->tempsock[1] = CURL_SOCKET_BAD;
1155 Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
Kristian Monsen5ab50182010-05-14 18:53:44 +01001156
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001157 /* Max time for the next connection attempt */
1158 conn->timeoutms_per_addr =
1159 conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001160
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001161 /* start connecting to first IP */
1162 while(conn->tempaddr[0]) {
1163 result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1164 if(!result)
Kristian Monsen5ab50182010-05-14 18:53:44 +01001165 break;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001166 conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001167 }
1168
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001169 if(conn->tempsock[0] == CURL_SOCKET_BAD) {
1170 if(!result)
1171 result = CURLE_COULDNT_CONNECT;
1172 return result;
1173 }
Kristian Monsen5ab50182010-05-14 18:53:44 +01001174
1175 data->info.numconnects++; /* to track the number of connections made */
1176
1177 return CURLE_OK;
1178}
1179
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001180struct connfind {
1181 struct connectdata *tofind;
1182 bool found;
1183};
1184
1185static int conn_is_conn(struct connectdata *conn, void *param)
1186{
1187 struct connfind *f = (struct connfind *)param;
1188 if(conn == f->tofind) {
1189 f->found = TRUE;
1190 return 1;
1191 }
1192 return 0;
1193}
1194
Kristian Monsen5ab50182010-05-14 18:53:44 +01001195/*
1196 * Used to extract socket and connectdata struct for the most recent
1197 * transfer on the given SessionHandle.
1198 *
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001199 * The returned socket will be CURL_SOCKET_BAD in case of failure!
Kristian Monsen5ab50182010-05-14 18:53:44 +01001200 */
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001201curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
1202 struct connectdata **connp)
Kristian Monsen5ab50182010-05-14 18:53:44 +01001203{
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001204 curl_socket_t sockfd;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001205
1206 DEBUGASSERT(data);
1207
1208 /* this works for an easy handle:
1209 * - that has been used for curl_easy_perform()
1210 * - that is associated with a multi handle, and whose connection
1211 * was detached with CURLOPT_CONNECT_ONLY
1212 */
1213 if(data->state.lastconnect && (data->multi_easy || data->multi)) {
1214 struct connectdata *c = data->state.lastconnect;
1215 struct connfind find;
1216 find.tofind = data->state.lastconnect;
1217 find.found = FALSE;
1218
1219 Curl_conncache_foreach(data->multi_easy?
1220 &data->multi_easy->conn_cache:
1221 &data->multi->conn_cache, &find, conn_is_conn);
1222
1223 if(!find.found) {
1224 data->state.lastconnect = NULL;
1225 return CURL_SOCKET_BAD;
1226 }
1227
Kristian Monsen5ab50182010-05-14 18:53:44 +01001228 if(connp)
1229 /* only store this if the caller cares for it */
1230 *connp = c;
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001231 sockfd = c->sock[FIRSTSOCKET];
Kristian Monsen5ab50182010-05-14 18:53:44 +01001232 /* we have a socket connected, let's determine if the server shut down */
1233 /* determine if ssl */
1234 if(c->ssl[FIRSTSOCKET].use) {
1235 /* use the SSL context */
1236 if(!Curl_ssl_check_cxn(c))
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001237 return CURL_SOCKET_BAD; /* FIN received */
Kristian Monsen5ab50182010-05-14 18:53:44 +01001238 }
1239/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1240#ifdef MSG_PEEK
1241 else {
1242 /* use the socket */
1243 char buf;
1244 if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1245 (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001246 return CURL_SOCKET_BAD; /* FIN received */
Kristian Monsen5ab50182010-05-14 18:53:44 +01001247 }
1248 }
1249#endif
1250 }
1251 else
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001252 return CURL_SOCKET_BAD;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001253
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001254 return sockfd;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001255}
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001256
1257/*
1258 * Close a socket.
1259 *
1260 * 'conn' can be NULL, beware!
1261 */
1262int Curl_closesocket(struct connectdata *conn,
1263 curl_socket_t sock)
1264{
1265 if(conn && conn->fclosesocket) {
1266 if((sock == conn->sock[SECONDARYSOCKET]) &&
1267 conn->sock_accepted[SECONDARYSOCKET])
1268 /* if this socket matches the second socket, and that was created with
1269 accept, then we MUST NOT call the callback but clear the accepted
1270 status */
1271 conn->sock_accepted[SECONDARYSOCKET] = FALSE;
1272 else {
1273 Curl_multi_closed(conn, sock);
1274 return conn->fclosesocket(conn->closesocket_client, sock);
1275 }
1276 }
1277
1278 if(conn)
1279 /* tell the multi-socket code about this */
1280 Curl_multi_closed(conn, sock);
1281
1282 sclose(sock);
1283
1284 return 0;
1285}
1286
1287/*
1288 * Create a socket based on info from 'conn' and 'ai'.
1289 *
1290 * 'addr' should be a pointer to the correct struct to get data back, or NULL.
1291 * 'sockfd' must be a pointer to a socket descriptor.
1292 *
1293 * If the open socket callback is set, used that!
1294 *
1295 */
1296CURLcode Curl_socket(struct connectdata *conn,
1297 const Curl_addrinfo *ai,
1298 struct Curl_sockaddr_ex *addr,
1299 curl_socket_t *sockfd)
1300{
1301 struct SessionHandle *data = conn->data;
1302 struct Curl_sockaddr_ex dummy;
1303
1304 if(!addr)
1305 /* if the caller doesn't want info back, use a local temp copy */
1306 addr = &dummy;
1307
1308 /*
1309 * The Curl_sockaddr_ex structure is basically libcurl's external API
1310 * curl_sockaddr structure with enough space available to directly hold
1311 * any protocol-specific address structures. The variable declared here
1312 * will be used to pass / receive data to/from the fopensocket callback
1313 * if this has been set, before that, it is initialized from parameters.
1314 */
1315
1316 addr->family = ai->ai_family;
1317 addr->socktype = conn->socktype;
1318 addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1319 addr->addrlen = ai->ai_addrlen;
1320
1321 if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
1322 addr->addrlen = sizeof(struct Curl_sockaddr_storage);
1323 memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
1324
1325 if(data->set.fopensocket)
1326 /*
1327 * If the opensocket callback is set, all the destination address
1328 * information is passed to the callback. Depending on this information the
1329 * callback may opt to abort the connection, this is indicated returning
1330 * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
1331 * the callback returns a valid socket the destination address information
1332 * might have been changed and this 'new' address will actually be used
1333 * here to connect.
1334 */
1335 *sockfd = data->set.fopensocket(data->set.opensocket_client,
1336 CURLSOCKTYPE_IPCXN,
1337 (struct curl_sockaddr *)addr);
1338 else
1339 /* opensocket callback not set, so simply create the socket now */
1340 *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1341
1342 if(*sockfd == CURL_SOCKET_BAD)
1343 /* no socket, no connection */
1344 return CURLE_COULDNT_CONNECT;
1345
1346#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
1347 if(conn->scope_id && (addr->family == AF_INET6)) {
1348 struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
1349 sa6->sin6_scope_id = conn->scope_id;
1350 }
1351#endif
1352
1353 return CURLE_OK;
1354
1355}
1356
1357#ifdef CURLDEBUG
1358/*
1359 * Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
1360 * MUST be called with the connclose() or connkeep() macros with a stated
1361 * reason. The reason is only shown in debug builds but helps to figure out
1362 * decision paths when connections are or aren't re-used as expected.
1363 */
1364void Curl_conncontrol(struct connectdata *conn, bool closeit,
1365 const char *reason)
1366{
1367#if defined(CURL_DISABLE_VERBOSE_STRINGS)
1368 (void) reason;
1369#endif
1370 if(closeit != conn->bits.close) {
1371 infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
1372 reason);
1373
1374 conn->bits.close = closeit; /* the only place in the source code that
1375 should assign this bit */
1376 }
1377}
1378#endif