1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.h> /* <netinet/tcp.h> may need it */
29 #include <sys/un.h> /* for sockaddr_un */
31 #ifdef HAVE_NETINET_TCP_H
32 #include <netinet/tcp.h> /* for TCP_NODELAY */
34 #ifdef HAVE_SYS_IOCTL_H
35 #include <sys/ioctl.h>
43 #ifdef HAVE_ARPA_INET_H
44 #include <arpa/inet.h>
47 #if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
48 #include <sys/filio.h>
52 #define in_addr_t unsigned long
59 #include "curl_printf.h"
66 #include "url.h" /* for Curl_safefree() */
68 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
69 #include "inet_ntop.h"
70 #include "inet_pton.h"
71 #include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
74 #include "conncache.h"
75 #include "multihandle.h"
77 /* The last #include files should be: */
78 #include "curl_memory.h"
82 /* This isn't actually supported under Symbian OS */
86 static bool verifyconnect(curl_socket_t sockfd, int *error);
88 #if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
89 /* DragonFlyBSD and Windows use millisecond units */
90 #define KEEPALIVE_FACTOR(x) (x *= 1000)
92 #define KEEPALIVE_FACTOR(x)
95 #if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
96 #define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
98 struct tcp_keepalive {
100 u_long keepalivetime;
101 u_long keepaliveinterval;
106 tcpkeepalive(struct SessionHandle *data,
107 curl_socket_t sockfd)
109 int optval = data->set.tcp_keepalive?1:0;
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);
117 #if defined(SIO_KEEPALIVE_VALS)
118 struct tcp_keepalive vals;
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());
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);
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);
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);
163 singleipconnect(struct connectdata *conn,
164 const Curl_addrinfo *ai, /* start connecting to this */
165 curl_socket_t *sock);
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
172 * The start time is stored in progress.t_startsingle - as set with
173 * Curl_pgrsTime(..., TIMER_STARTSINGLE);
175 * 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!
181 long Curl_timeleft(struct SessionHandle *data,
182 struct timeval *nowp,
186 long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
189 /* if a timeout is set, use the most restrictive one */
191 if(data->set.timeout > 0)
193 if(duringconnect && (data->set.connecttimeout > 0))
196 switch (timeout_set) {
198 timeout_ms = data->set.timeout;
201 timeout_ms = data->set.connecttimeout;
204 if(data->set.timeout < data->set.connecttimeout)
205 timeout_ms = data->set.timeout;
207 timeout_ms = data->set.connecttimeout;
210 /* use the default */
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
224 /* subtract elapsed time */
226 /* since this most recent connect started */
227 timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
229 /* since the entire operation started */
230 timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop);
232 /* avoid returning 0 as that means no timeout! */
238 static CURLcode bindlocal(struct connectdata *conn,
239 curl_socket_t sockfd, int af, unsigned int scope)
241 struct SessionHandle *data = conn->data;
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;
248 struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
251 struct Curl_dns_entry *h=NULL;
252 unsigned short port = data->set.localport; /* use this port number, 0 for
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];
259 /*************************************************************
260 * Select device to bind socket to
261 *************************************************************/
263 /* no local kind of binding was requested */
266 memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
268 if(dev && (strlen(dev)<255) ) {
269 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!";
276 if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
277 dev += strlen(if_prefix);
280 else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
281 dev += strlen(host_prefix);
287 switch(Curl_if2ip(af, scope, conn->scope_id, dev,
288 myhost, sizeof(myhost))) {
289 case IF2IP_NOT_FOUND:
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;
296 case IF2IP_AF_NOT_SUPPORTED:
297 /* Signal the caller to try another address family if available */
298 return CURLE_UNSUPPORTED_PROTOCOL;
302 * We now have the numerical IP address in the 'myhost' buffer
304 infof(data, "Local Interface %s is ip %s using address family %i\n",
308 #ifdef SO_BINDTODEVICE
309 /* I am not sure any other OSs than Linux that provide this feature,
310 * and at the least I cannot test. --Ben
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.
317 * Only bind to the interface when specified as interface, not just
318 * as a hostname or ip address.
320 if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
321 dev, (curl_socklen_t)strlen(dev)+1) != 0) {
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
336 * This was not an interface, resolve the name as a host name
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.
343 long ipver = conn->ip_version;
347 conn->ip_version = CURL_IPRESOLVE_V4;
349 else if(af == AF_INET6)
350 conn->ip_version = CURL_IPRESOLVE_V6;
353 rc = Curl_resolv(conn, dev, 0, &h);
354 if(rc == CURLRESOLV_PENDING)
355 (void)Curl_resolver_wait_resolv(conn, &h);
356 conn->ip_version = ipver;
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);
368 * provided dev was no interface (or interfaces are not supported
369 * e.g. solaris) no ip address and no domain we fail here
379 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
380 char *scope_ptr = strchr(myhost, '%');
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
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);
396 sizeof_sa = sizeof(struct sockaddr_in6);
401 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);
410 failf(data, "Couldn't bind to '%s'", dev);
411 return CURLE_INTERFACE_FAILED;
415 /* no device was given, prepare sa to match af's needs */
418 si6->sin6_family = AF_INET6;
419 si6->sin6_port = htons(port);
420 sizeof_sa = sizeof(struct sockaddr_in6);
425 si4->sin_family = AF_INET;
426 si4->sin_port = htons(port);
427 sizeof_sa = sizeof(struct sockaddr_in);
432 if(bind(sockfd, sock, sizeof_sa) >= 0) {
433 /* we succeeded to bind */
434 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;
443 infof(data, "Local port: %hu\n", port);
444 conn->bits.bound = TRUE;
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);
456 si6->sin6_port = ntohs(port);
463 data->state.os_errno = error = SOCKERRNO;
464 failf(data, "bind failed with errno %d: %s",
465 error, Curl_strerror(conn, error));
467 return CURLE_INTERFACE_FAILED;
471 * verifyconnect() returns TRUE if the connect really has happened.
473 static bool verifyconnect(curl_socket_t sockfd, int *error)
478 curl_socklen_t errSize = sizeof(err);
482 * In October 2003 we effectively nullified this function on Windows due to
483 * problems with it using all CPU in multi-threaded cases.
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:
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.
494 * Someone got to verify this on Win-NT 4.0, 2000."
505 if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
508 /* Old WinCE versions don't support SO_ERROR */
509 if(WSAENOPROTOOPT == err) {
515 /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
516 if(EBADIOCTL == err) {
521 if((0 == err) || (EISCONN == err))
522 /* we are connected, awesome! */
525 /* This wasn't a successful connect */
537 /* Used within the multi interface. Try next IP address, return TRUE if no
538 more address exists or error */
539 static CURLcode trynextip(struct connectdata *conn,
543 const int other = tempindex ^ 1;
544 CURLcode result = CURLE_COULDNT_CONNECT;
546 /* 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. */
550 curl_socket_t fd_to_close = conn->tempsock[tempindex];
551 conn->tempsock[tempindex] = CURL_SOCKET_BAD;
553 if(sockindex == FIRSTSOCKET) {
554 Curl_addrinfo *ai = NULL;
555 int family = AF_UNSPEC;
557 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;
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;
572 if(conn->tempaddr[other]) {
573 /* we can safely skip addresses of the other protocol family */
574 while(ai && ai->ai_family != family)
579 result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
580 if(result == CURLE_COULDNT_CONNECT) {
585 conn->tempaddr[tempindex] = ai;
591 if(fd_to_close != CURL_SOCKET_BAD)
592 Curl_closesocket(conn, fd_to_close);
597 /* Copies connection info into the session handle to make it available
598 when the session handle is no longer associated with a connection. */
599 void Curl_persistconninfo(struct connectdata *conn)
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;
607 /* retrieves ip address and port from a sockaddr structure */
608 static bool getaddressinfo(struct sockaddr* sa, char* addr,
611 unsigned short us_port;
612 struct sockaddr_in* si = NULL;
614 struct sockaddr_in6* si6 = NULL;
616 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
617 struct sockaddr_un* su = NULL;
620 switch (sa->sa_family) {
622 si = (struct sockaddr_in*) sa;
623 if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
624 addr, MAX_IPADR_LEN)) {
625 us_port = ntohs(si->sin_port);
632 si6 = (struct sockaddr_in6*)sa;
633 if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
634 addr, MAX_IPADR_LEN)) {
635 us_port = ntohs(si6->sin6_port);
641 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
643 su = (struct sockaddr_un*)sa;
644 snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
658 /* retrieves the start/end point information of a socket of an established
660 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
663 struct Curl_sockaddr_storage ssrem;
664 struct Curl_sockaddr_storage ssloc;
665 struct SessionHandle *data = conn->data;
667 if(conn->socktype == SOCK_DGRAM)
668 /* there's no connection! */
671 if(!conn->bits.reuse) {
674 len = sizeof(struct Curl_sockaddr_storage);
675 if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
677 failf(data, "getpeername() failed with errno %d: %s",
678 error, Curl_strerror(conn, error));
682 len = sizeof(struct Curl_sockaddr_storage);
683 memset(&ssloc, 0, sizeof(ssloc));
684 if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
686 failf(data, "getsockname() failed with errno %d: %s",
687 error, Curl_strerror(conn, error));
691 if(!getaddressinfo((struct sockaddr*)&ssrem,
692 conn->primary_ip, &conn->primary_port)) {
694 failf(data, "ssrem inet_ntop() failed with errno %d: %s",
695 error, Curl_strerror(conn, error));
698 memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
700 if(!getaddressinfo((struct sockaddr*)&ssloc,
701 conn->local_ip, &conn->local_port)) {
703 failf(data, "ssloc inet_ntop() failed with errno %d: %s",
704 error, Curl_strerror(conn, error));
710 /* persist connection info in session handle */
711 Curl_persistconninfo(conn);
715 * Curl_is_connected() checks if the socket has connected.
718 CURLcode Curl_is_connected(struct connectdata *conn,
722 struct SessionHandle *data = conn->data;
723 CURLcode result = CURLE_OK;
730 DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
732 *connected = FALSE; /* a very negative world view is best */
734 if(conn->bits.tcpconnect[sockindex]) {
735 /* we are connected already! */
742 /* figure out how long time we have left to connect */
743 allow = Curl_timeleft(data, &now, TRUE);
746 /* time-out, bail out, go home */
747 failf(data, "Connection time-out");
748 return CURLE_OPERATION_TIMEDOUT;
752 const int other = i ^ 1;
753 if(conn->tempsock[i] == CURL_SOCKET_BAD)
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);
763 /* check socket for connect */
764 rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
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);
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);
779 else if(rc == CURL_CSELECT_OUT) {
780 if(verifyconnect(conn->tempsock[i], &error)) {
781 /* we are connected with TCP, awesome! */
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;
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;
794 /* see if we need to do any proxy magic first once we connected */
795 result = Curl_connected_proxy(conn, sockindex);
799 conn->bits.tcpconnect[sockindex] = TRUE;
802 if(sockindex == FIRSTSOCKET)
803 Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
804 Curl_updateconninfo(conn, conn->sock[sockindex]);
805 Curl_verboseconnect(conn);
810 infof(data, "Connection failed\n");
812 else if(rc & CURL_CSELECT_ERR)
813 (void)verifyconnect(conn->tempsock[i], &error);
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.
820 data->state.os_errno = error;
821 SET_SOCKERRNO(error);
822 if(conn->tempaddr[i]) {
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));
829 conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
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 */
842 /* no more addresses to try */
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);
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));
860 static void tcpnodelay(struct connectdata *conn,
861 curl_socket_t sockfd)
864 struct SessionHandle *data= conn->data;
865 curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
866 int level = IPPROTO_TCP;
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
876 struct protoent *pe = getprotobyname("tcp");
881 if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
883 infof(data, "Could not set TCP_NODELAY: %s\n",
884 Curl_strerror(conn, SOCKERRNO));
886 infof(data, "TCP_NODELAY set\n");
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
898 static void nosigpipe(struct connectdata *conn,
899 curl_socket_t sockfd)
901 struct SessionHandle *data= conn->data;
903 if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
905 infof(data, "Could not set SO_NOSIGPIPE: %s\n",
906 Curl_strerror(conn, SOCKERRNO));
909 #define nosigpipe(x,y) Curl_nop_stmt
913 /* 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.
916 http://support.microsoft.com/kb/823764
918 Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
921 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.
925 #define DETECT_OS_NONE 0
926 #define DETECT_OS_PREVISTA 1
927 #define DETECT_OS_VISTA_OR_LATER 2
929 void Curl_sndbufset(curl_socket_t sockfd)
931 int val = CURL_MAX_WRITE_SIZE + 32;
933 int curlen = sizeof(curval);
934 DWORD majorVersion = 6;
936 static int detectOsState = DETECT_OS_NONE;
938 if(detectOsState == DETECT_OS_NONE) {
939 #if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
940 (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
943 memset(&osver, 0, sizeof(osver));
944 osver.dwOSVersionInfoSize = sizeof(osver);
946 detectOsState = DETECT_OS_PREVISTA;
947 if(GetVersionEx(&osver)) {
948 if(osver.dwMajorVersion >= majorVersion)
949 detectOsState = DETECT_OS_VISTA_OR_LATER;
953 OSVERSIONINFOEX osver;
955 memset(&osver, 0, sizeof(osver));
956 osver.dwOSVersionInfoSize = sizeof(osver);
957 osver.dwMajorVersion = majorVersion;
959 cm = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
960 cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_GREATER_EQUAL);
961 cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
962 cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
964 if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
965 VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
967 detectOsState = DETECT_OS_VISTA_OR_LATER;
969 detectOsState = DETECT_OS_PREVISTA;
973 if(detectOsState == DETECT_OS_VISTA_OR_LATER)
976 if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
980 setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
987 * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
988 * CURL_SOCKET_BAD. Other errors will however return proper errors.
990 * singleipconnect() connects to the given IP only, and it may return without
993 static CURLcode singleipconnect(struct connectdata *conn,
994 const Curl_addrinfo *ai,
995 curl_socket_t *sockp)
997 struct Curl_sockaddr_ex addr;
1000 bool isconnected = FALSE;
1001 struct SessionHandle *data = conn->data;
1002 curl_socket_t sockfd;
1004 char ipaddress[MAX_IPADR_LEN];
1008 *sockp = CURL_SOCKET_BAD;
1010 result = Curl_socket(conn, ai, &addr, &sockfd);
1012 /* Failed to create the socket, but still return OK since we signal the
1013 lack of socket as well. This allows the parent function to keep looping
1014 over alternative addresses/socket families etc. */
1017 /* store remote address and port used in this connection attempt */
1018 if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
1019 ipaddress, &port)) {
1020 /* malformed address or bug in inet_ntop, try next address */
1022 failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
1023 error, Curl_strerror(conn, error));
1024 Curl_closesocket(conn, sockfd);
1027 infof(data, " Trying %s...\n", ipaddress);
1030 is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
1031 addr.socktype == SOCK_STREAM;
1033 is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
1035 if(is_tcp && data->set.tcp_nodelay)
1036 tcpnodelay(conn, sockfd);
1038 nosigpipe(conn, sockfd);
1040 Curl_sndbufset(sockfd);
1042 if(is_tcp && data->set.tcp_keepalive)
1043 tcpkeepalive(data, sockfd);
1045 if(data->set.fsockopt) {
1046 /* activate callback for setting socket options */
1047 error = data->set.fsockopt(data->set.sockopt_client,
1049 CURLSOCKTYPE_IPCXN);
1051 if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
1054 Curl_closesocket(conn, sockfd); /* close the socket and bail out */
1055 return CURLE_ABORTED_BY_CALLBACK;
1059 /* possibly bind the local end to an IP, interface or port */
1060 if(addr.family == AF_INET
1062 || addr.family == AF_INET6
1065 result = bindlocal(conn, sockfd, addr.family,
1066 Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
1068 Curl_closesocket(conn, sockfd); /* close socket and bail out */
1069 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
1070 /* The address family is not supported on this interface.
1071 We can continue trying addresses */
1072 return CURLE_COULDNT_CONNECT;
1078 /* set socket non-blocking */
1079 (void)curlx_nonblock(sockfd, TRUE);
1081 conn->connecttime = Curl_tvnow();
1082 if(conn->num_addr > 1)
1083 Curl_expire_latest(data, conn->timeoutms_per_addr);
1085 /* Connect TCP sockets, bind UDP */
1086 if(!isconnected && (conn->socktype == SOCK_STREAM)) {
1087 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1097 conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
1105 #if (EAGAIN) != (EWOULDBLOCK)
1106 /* On some platforms EAGAIN and EWOULDBLOCK are the
1107 * same value, and on others they are different, hence
1117 /* unknown error, fallthrough and try another address! */
1118 infof(data, "Immediate connect fail for %s: %s\n",
1119 ipaddress, Curl_strerror(conn, error));
1120 data->state.os_errno = error;
1122 /* connect failed */
1123 Curl_closesocket(conn, sockfd);
1124 result = CURLE_COULDNT_CONNECT;
1135 * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1136 * There might be more than one IP address to try out. Fill in the passed
1137 * pointer with the connected socket.
1140 CURLcode Curl_connecthost(struct connectdata *conn, /* context */
1141 const struct Curl_dns_entry *remotehost)
1143 struct SessionHandle *data = conn->data;
1144 struct timeval before = Curl_tvnow();
1145 CURLcode result = CURLE_COULDNT_CONNECT;
1147 long timeout_ms = Curl_timeleft(data, &before, TRUE);
1149 if(timeout_ms < 0) {
1150 /* a precaution, no need to continue if time already is up */
1151 failf(data, "Connection time-out");
1152 return CURLE_OPERATION_TIMEDOUT;
1155 conn->num_addr = Curl_num_addresses(remotehost->addr);
1156 conn->tempaddr[0] = remotehost->addr;
1157 conn->tempaddr[1] = NULL;
1158 conn->tempsock[0] = CURL_SOCKET_BAD;
1159 conn->tempsock[1] = CURL_SOCKET_BAD;
1160 Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
1162 /* Max time for the next connection attempt */
1163 conn->timeoutms_per_addr =
1164 conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
1166 /* start connecting to first IP */
1167 while(conn->tempaddr[0]) {
1168 result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1171 conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
1174 if(conn->tempsock[0] == CURL_SOCKET_BAD) {
1176 result = CURLE_COULDNT_CONNECT;
1180 data->info.numconnects++; /* to track the number of connections made */
1186 struct connectdata *tofind;
1190 static int conn_is_conn(struct connectdata *conn, void *param)
1192 struct connfind *f = (struct connfind *)param;
1193 if(conn == f->tofind) {
1201 * Used to extract socket and connectdata struct for the most recent
1202 * transfer on the given SessionHandle.
1204 * The returned socket will be CURL_SOCKET_BAD in case of failure!
1206 curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
1207 struct connectdata **connp)
1209 curl_socket_t sockfd;
1213 /* this works for an easy handle:
1214 * - that has been used for curl_easy_perform()
1215 * - that is associated with a multi handle, and whose connection
1216 * was detached with CURLOPT_CONNECT_ONLY
1218 if(data->state.lastconnect && (data->multi_easy || data->multi)) {
1219 struct connectdata *c = data->state.lastconnect;
1220 struct connfind find;
1221 find.tofind = data->state.lastconnect;
1224 Curl_conncache_foreach(data->multi_easy?
1225 &data->multi_easy->conn_cache:
1226 &data->multi->conn_cache, &find, conn_is_conn);
1229 data->state.lastconnect = NULL;
1230 return CURL_SOCKET_BAD;
1234 /* only store this if the caller cares for it */
1236 sockfd = c->sock[FIRSTSOCKET];
1237 /* we have a socket connected, let's determine if the server shut down */
1238 /* determine if ssl */
1239 if(c->ssl[FIRSTSOCKET].use) {
1240 /* use the SSL context */
1241 if(!Curl_ssl_check_cxn(c))
1242 return CURL_SOCKET_BAD; /* FIN received */
1244 /* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1247 /* use the socket */
1249 if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1250 (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
1251 return CURL_SOCKET_BAD; /* FIN received */
1257 return CURL_SOCKET_BAD;
1265 * 'conn' can be NULL, beware!
1267 int Curl_closesocket(struct connectdata *conn,
1270 if(conn && conn->fclosesocket) {
1271 if((sock == conn->sock[SECONDARYSOCKET]) &&
1272 conn->sock_accepted[SECONDARYSOCKET])
1273 /* if this socket matches the second socket, and that was created with
1274 accept, then we MUST NOT call the callback but clear the accepted
1276 conn->sock_accepted[SECONDARYSOCKET] = FALSE;
1278 Curl_multi_closed(conn, sock);
1279 return conn->fclosesocket(conn->closesocket_client, sock);
1284 /* tell the multi-socket code about this */
1285 Curl_multi_closed(conn, sock);
1293 * Create a socket based on info from 'conn' and 'ai'.
1295 * 'addr' should be a pointer to the correct struct to get data back, or NULL.
1296 * 'sockfd' must be a pointer to a socket descriptor.
1298 * If the open socket callback is set, used that!
1301 CURLcode Curl_socket(struct connectdata *conn,
1302 const Curl_addrinfo *ai,
1303 struct Curl_sockaddr_ex *addr,
1304 curl_socket_t *sockfd)
1306 struct SessionHandle *data = conn->data;
1307 struct Curl_sockaddr_ex dummy;
1310 /* if the caller doesn't want info back, use a local temp copy */
1314 * The Curl_sockaddr_ex structure is basically libcurl's external API
1315 * curl_sockaddr structure with enough space available to directly hold
1316 * any protocol-specific address structures. The variable declared here
1317 * will be used to pass / receive data to/from the fopensocket callback
1318 * if this has been set, before that, it is initialized from parameters.
1321 addr->family = ai->ai_family;
1322 addr->socktype = conn->socktype;
1323 addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1324 addr->addrlen = ai->ai_addrlen;
1326 if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
1327 addr->addrlen = sizeof(struct Curl_sockaddr_storage);
1328 memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
1330 if(data->set.fopensocket)
1332 * If the opensocket callback is set, all the destination address
1333 * information is passed to the callback. Depending on this information the
1334 * callback may opt to abort the connection, this is indicated returning
1335 * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
1336 * the callback returns a valid socket the destination address information
1337 * might have been changed and this 'new' address will actually be used
1340 *sockfd = data->set.fopensocket(data->set.opensocket_client,
1342 (struct curl_sockaddr *)addr);
1344 /* opensocket callback not set, so simply create the socket now */
1345 *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1347 if(*sockfd == CURL_SOCKET_BAD)
1348 /* no socket, no connection */
1349 return CURLE_COULDNT_CONNECT;
1351 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
1352 if(conn->scope_id && (addr->family == AF_INET6)) {
1353 struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
1354 sa6->sin6_scope_id = conn->scope_id;
1364 * Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
1365 * MUST be called with the connclose() or connkeep() macros with a stated
1366 * reason. The reason is only shown in debug builds but helps to figure out
1367 * decision paths when connections are or aren't re-used as expected.
1369 void Curl_conncontrol(struct connectdata *conn, bool closeit,
1372 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
1375 if(closeit != conn->bits.close) {
1376 infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
1379 conn->bits.close = closeit; /* the only place in the source code that
1380 should assign this bit */