1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2017, 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 https://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_LINUX_TCP_H
32 #include <linux/tcp.h>
33 #elif defined(HAVE_NETINET_TCP_H)
34 #include <netinet/tcp.h>
36 #ifdef HAVE_SYS_IOCTL_H
37 #include <sys/ioctl.h>
45 #ifdef HAVE_ARPA_INET_H
46 #include <arpa/inet.h>
49 #if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
50 #include <sys/filio.h>
54 #define in_addr_t unsigned long
67 #include "url.h" /* for Curl_safefree() */
69 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
70 #include "inet_ntop.h"
71 #include "inet_pton.h"
72 #include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
75 #include "conncache.h"
76 #include "multihandle.h"
77 #include "system_win32.h"
79 /* The last 3 #include files should be in this order */
80 #include "curl_printf.h"
81 #include "curl_memory.h"
85 /* This isn't actually supported under Symbian OS */
89 static bool verifyconnect(curl_socket_t sockfd, int *error);
91 #if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
92 /* DragonFlyBSD and Windows use millisecond units */
93 #define KEEPALIVE_FACTOR(x) (x *= 1000)
95 #define KEEPALIVE_FACTOR(x)
98 #if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
99 #define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
101 struct tcp_keepalive {
103 u_long keepalivetime;
104 u_long keepaliveinterval;
109 tcpkeepalive(struct Curl_easy *data,
110 curl_socket_t sockfd)
112 int optval = data->set.tcp_keepalive?1:0;
114 /* only set IDLE and INTVL if setting KEEPALIVE is successful */
115 if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
116 (void *)&optval, sizeof(optval)) < 0) {
117 infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd);
120 #if defined(SIO_KEEPALIVE_VALS)
121 struct tcp_keepalive vals;
124 optval = curlx_sltosi(data->set.tcp_keepidle);
125 KEEPALIVE_FACTOR(optval);
126 vals.keepalivetime = optval;
127 optval = curlx_sltosi(data->set.tcp_keepintvl);
128 KEEPALIVE_FACTOR(optval);
129 vals.keepaliveinterval = optval;
130 if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
131 NULL, 0, &dummy, NULL, NULL) != 0) {
132 infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
133 (int)sockfd, WSAGetLastError());
137 optval = curlx_sltosi(data->set.tcp_keepidle);
138 KEEPALIVE_FACTOR(optval);
139 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
140 (void *)&optval, sizeof(optval)) < 0) {
141 infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd);
145 optval = curlx_sltosi(data->set.tcp_keepintvl);
146 KEEPALIVE_FACTOR(optval);
147 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
148 (void *)&optval, sizeof(optval)) < 0) {
149 infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd);
154 optval = curlx_sltosi(data->set.tcp_keepidle);
155 KEEPALIVE_FACTOR(optval);
156 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
157 (void *)&optval, sizeof(optval)) < 0) {
158 infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd);
166 singleipconnect(struct connectdata *conn,
167 const Curl_addrinfo *ai, /* start connecting to this */
168 curl_socket_t *sock);
171 * Curl_timeleft() returns the amount of milliseconds left allowed for the
172 * transfer/connection. If the value is negative, the timeout time has already
175 * The start time is stored in progress.t_startsingle - as set with
176 * Curl_pgrsTime(..., TIMER_STARTSINGLE);
178 * If 'nowp' is non-NULL, it points to the current time.
179 * 'duringconnect' is FALSE if not during a connect, as then of course the
180 * connect timeout is not taken into account!
184 timediff_t Curl_timeleft(struct Curl_easy *data,
185 struct curltime *nowp,
189 timediff_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
192 /* if a timeout is set, use the most restrictive one */
194 if(data->set.timeout > 0)
196 if(duringconnect && (data->set.connecttimeout > 0))
199 switch(timeout_set) {
201 timeout_ms = data->set.timeout;
204 timeout_ms = data->set.connecttimeout;
207 if(data->set.timeout < data->set.connecttimeout)
208 timeout_ms = data->set.timeout;
210 timeout_ms = data->set.connecttimeout;
213 /* use the default */
215 /* if we're not during connect, there's no default timeout so if we're
216 at zero we better just return zero and not make it a negative number
227 /* subtract elapsed time */
229 /* since this most recent connect started */
230 timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle);
232 /* since the entire operation started */
233 timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop);
235 /* avoid returning 0 as that means no timeout! */
241 static CURLcode bindlocal(struct connectdata *conn,
242 curl_socket_t sockfd, int af, unsigned int scope)
244 struct Curl_easy *data = conn->data;
246 struct Curl_sockaddr_storage sa;
247 struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
248 curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
249 struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
251 struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
254 struct Curl_dns_entry *h = NULL;
255 unsigned short port = data->set.localport; /* use this port number, 0 for
257 /* how many port numbers to try to bind to, increasing one at a time */
258 int portnum = data->set.localportrange;
259 const char *dev = data->set.str[STRING_DEVICE];
262 /*************************************************************
263 * Select device to bind socket to
264 *************************************************************/
266 /* no local kind of binding was requested */
269 memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
271 if(dev && (strlen(dev)<255) ) {
272 char myhost[256] = "";
273 int done = 0; /* -1 for error, 1 for address found */
274 bool is_interface = FALSE;
275 bool is_host = FALSE;
276 static const char *if_prefix = "if!";
277 static const char *host_prefix = "host!";
279 if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
280 dev += strlen(if_prefix);
283 else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
284 dev += strlen(host_prefix);
290 #ifdef SO_BINDTODEVICE
291 /* I am not sure any other OSs than Linux that provide this feature,
292 * and at the least I cannot test. --Ben
294 * This feature allows one to tightly bind the local socket to a
295 * particular interface. This will force even requests to other
296 * local interfaces to go out the external interface.
299 * Only bind to the interface when specified as interface, not just
300 * as a hostname or ip address.
302 * interface might be a VRF, eg: vrf-blue, which means it cannot be
303 * converted to an IP address and would fail Curl_if2ip. Simply try
304 * to use it straight away.
306 if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
307 dev, (curl_socklen_t)strlen(dev) + 1) == 0) {
308 /* This is typically "errno 1, error: Operation not permitted" if
309 * you're not running as root or another suitable privileged
311 * If it succeeds it means the parameter was a valid interface and
312 * not an IP address. Return immediately.
318 switch(Curl_if2ip(af, scope, conn->scope_id, dev,
319 myhost, sizeof(myhost))) {
320 case IF2IP_NOT_FOUND:
322 /* Do not fall back to treating it as a host name */
323 failf(data, "Couldn't bind to interface '%s'", dev);
324 return CURLE_INTERFACE_FAILED;
327 case IF2IP_AF_NOT_SUPPORTED:
328 /* Signal the caller to try another address family if available */
329 return CURLE_UNSUPPORTED_PROTOCOL;
333 * We now have the numerical IP address in the 'myhost' buffer
335 infof(data, "Local Interface %s is ip %s using address family %i\n",
343 * This was not an interface, resolve the name as a host name
346 * Temporarily force name resolution to use only the address type
347 * of the connection. The resolve functions should really be changed
348 * to take a type parameter instead.
350 long ipver = conn->ip_version;
354 conn->ip_version = CURL_IPRESOLVE_V4;
356 else if(af == AF_INET6)
357 conn->ip_version = CURL_IPRESOLVE_V6;
360 rc = Curl_resolv(conn, dev, 0, &h);
361 if(rc == CURLRESOLV_PENDING)
362 (void)Curl_resolver_wait_resolv(conn, &h);
363 conn->ip_version = ipver;
366 /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
367 Curl_printable_address(h->addr, myhost, sizeof(myhost));
368 infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
369 dev, af, myhost, h->addr->ai_family);
370 Curl_resolv_unlock(data, h);
375 * provided dev was no interface (or interfaces are not supported
376 * e.g. solaris) no ip address and no domain we fail here
386 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
387 char *scope_ptr = strchr(myhost, '%');
391 if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
392 si6->sin6_family = AF_INET6;
393 si6->sin6_port = htons(port);
394 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
396 /* The "myhost" string either comes from Curl_if2ip or from
397 Curl_printable_address. The latter returns only numeric scope
398 IDs and the former returns none at all. So the scope ID, if
399 present, is known to be numeric */
400 si6->sin6_scope_id = atoi(scope_ptr);
403 sizeof_sa = sizeof(struct sockaddr_in6);
408 if((af == AF_INET) &&
409 (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
410 si4->sin_family = AF_INET;
411 si4->sin_port = htons(port);
412 sizeof_sa = sizeof(struct sockaddr_in);
417 /* errorbuf is set false so failf will overwrite any message already in
418 the error buffer, so the user receives this error message instead of a
419 generic resolve error. */
420 data->state.errorbuf = FALSE;
421 failf(data, "Couldn't bind to '%s'", dev);
422 return CURLE_INTERFACE_FAILED;
426 /* no device was given, prepare sa to match af's needs */
429 si6->sin6_family = AF_INET6;
430 si6->sin6_port = htons(port);
431 sizeof_sa = sizeof(struct sockaddr_in6);
436 si4->sin_family = AF_INET;
437 si4->sin_port = htons(port);
438 sizeof_sa = sizeof(struct sockaddr_in);
443 if(bind(sockfd, sock, sizeof_sa) >= 0) {
444 /* we succeeded to bind */
445 struct Curl_sockaddr_storage add;
446 curl_socklen_t size = sizeof(add);
447 memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
448 if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
449 data->state.os_errno = error = SOCKERRNO;
450 failf(data, "getsockname() failed with errno %d: %s",
451 error, Curl_strerror(conn, error));
452 return CURLE_INTERFACE_FAILED;
454 infof(data, "Local port: %hu\n", port);
455 conn->bits.bound = TRUE;
460 infof(data, "Bind to local port %hu failed, trying next\n", port);
461 port++; /* try next port */
462 /* We re-use/clobber the port variable here below */
463 if(sock->sa_family == AF_INET)
464 si4->sin_port = ntohs(port);
467 si6->sin6_port = ntohs(port);
474 data->state.os_errno = error = SOCKERRNO;
475 failf(data, "bind failed with errno %d: %s",
476 error, Curl_strerror(conn, error));
478 return CURLE_INTERFACE_FAILED;
482 * verifyconnect() returns TRUE if the connect really has happened.
484 static bool verifyconnect(curl_socket_t sockfd, int *error)
489 curl_socklen_t errSize = sizeof(err);
493 * In October 2003 we effectively nullified this function on Windows due to
494 * problems with it using all CPU in multi-threaded cases.
496 * In May 2004, we bring it back to offer more info back on connect failures.
497 * Gisle Vanem could reproduce the former problems with this function, but
498 * could avoid them by adding this SleepEx() call below:
500 * "I don't have Rational Quantify, but the hint from his post was
501 * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
502 * just Sleep(0) would be enough?) would release whatever
503 * mutex/critical-section the ntdll call is waiting on.
505 * Someone got to verify this on Win-NT 4.0, 2000."
516 if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
519 /* Old WinCE versions don't support SO_ERROR */
520 if(WSAENOPROTOOPT == err) {
526 /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
527 if(EBADIOCTL == err) {
532 if((0 == err) || (EISCONN == err))
533 /* we are connected, awesome! */
536 /* This wasn't a successful connect */
548 /* Used within the multi interface. Try next IP address, return TRUE if no
549 more address exists or error */
550 static CURLcode trynextip(struct connectdata *conn,
554 const int other = tempindex ^ 1;
555 CURLcode result = CURLE_COULDNT_CONNECT;
557 /* First clean up after the failed socket.
558 Don't close it yet to ensure that the next IP's socket gets a different
559 file descriptor, which can prevent bugs when the curl_multi_socket_action
560 interface is used with certain select() replacements such as kqueue. */
561 curl_socket_t fd_to_close = conn->tempsock[tempindex];
562 conn->tempsock[tempindex] = CURL_SOCKET_BAD;
564 if(sockindex == FIRSTSOCKET) {
565 Curl_addrinfo *ai = NULL;
566 int family = AF_UNSPEC;
568 if(conn->tempaddr[tempindex]) {
569 /* find next address in the same protocol family */
570 family = conn->tempaddr[tempindex]->ai_family;
571 ai = conn->tempaddr[tempindex]->ai_next;
574 else if(conn->tempaddr[0]) {
575 /* happy eyeballs - try the other protocol family */
576 int firstfamily = conn->tempaddr[0]->ai_family;
577 family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
578 ai = conn->tempaddr[0]->ai_next;
583 if(conn->tempaddr[other]) {
584 /* we can safely skip addresses of the other protocol family */
585 while(ai && ai->ai_family != family)
590 result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
591 if(result == CURLE_COULDNT_CONNECT) {
596 conn->tempaddr[tempindex] = ai;
602 if(fd_to_close != CURL_SOCKET_BAD)
603 Curl_closesocket(conn, fd_to_close);
608 /* Copies connection info into the session handle to make it available
609 when the session handle is no longer associated with a connection. */
610 void Curl_persistconninfo(struct connectdata *conn)
612 memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
613 memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
614 conn->data->info.conn_scheme = conn->handler->scheme;
615 conn->data->info.conn_protocol = conn->handler->protocol;
616 conn->data->info.conn_primary_port = conn->primary_port;
617 conn->data->info.conn_local_port = conn->local_port;
620 /* retrieves ip address and port from a sockaddr structure.
621 note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
622 bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
625 unsigned short us_port;
626 struct sockaddr_in *si = NULL;
628 struct sockaddr_in6 *si6 = NULL;
630 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
631 struct sockaddr_un *su = NULL;
634 switch(sa->sa_family) {
636 si = (struct sockaddr_in *)(void *) sa;
637 if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
638 addr, MAX_IPADR_LEN)) {
639 us_port = ntohs(si->sin_port);
646 si6 = (struct sockaddr_in6 *)(void *) sa;
647 if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
648 addr, MAX_IPADR_LEN)) {
649 us_port = ntohs(si6->sin6_port);
655 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
657 su = (struct sockaddr_un*)sa;
658 snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
668 errno = EAFNOSUPPORT;
672 /* retrieves the start/end point information of a socket of an established
674 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
677 struct Curl_sockaddr_storage ssrem;
678 struct Curl_sockaddr_storage ssloc;
679 struct Curl_easy *data = conn->data;
681 if(conn->socktype == SOCK_DGRAM)
682 /* there's no connection! */
685 if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
686 len = sizeof(struct Curl_sockaddr_storage);
687 if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
688 int error = SOCKERRNO;
689 failf(data, "getpeername() failed with errno %d: %s",
690 error, Curl_strerror(conn, error));
694 len = sizeof(struct Curl_sockaddr_storage);
695 memset(&ssloc, 0, sizeof(ssloc));
696 if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
697 int error = SOCKERRNO;
698 failf(data, "getsockname() failed with errno %d: %s",
699 error, Curl_strerror(conn, error));
703 if(!Curl_getaddressinfo((struct sockaddr*)&ssrem,
704 conn->primary_ip, &conn->primary_port)) {
705 failf(data, "ssrem inet_ntop() failed with errno %d: %s",
706 errno, Curl_strerror(conn, errno));
709 memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
711 if(!Curl_getaddressinfo((struct sockaddr*)&ssloc,
712 conn->local_ip, &conn->local_port)) {
713 failf(data, "ssloc inet_ntop() failed with errno %d: %s",
714 errno, Curl_strerror(conn, errno));
720 /* persist connection info in session handle */
721 Curl_persistconninfo(conn);
725 * Curl_is_connected() checks if the socket has connected.
728 CURLcode Curl_is_connected(struct connectdata *conn,
732 struct Curl_easy *data = conn->data;
733 CURLcode result = CURLE_OK;
740 DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
742 *connected = FALSE; /* a very negative world view is best */
744 if(conn->bits.tcpconnect[sockindex]) {
745 /* we are connected already! */
752 /* figure out how long time we have left to connect */
753 allow = Curl_timeleft(data, &now, TRUE);
756 /* time-out, bail out, go home */
757 failf(data, "Connection time-out");
758 return CURLE_OPERATION_TIMEDOUT;
761 for(i = 0; i<2; i++) {
762 const int other = i ^ 1;
763 if(conn->tempsock[i] == CURL_SOCKET_BAD)
767 /* Call this function once now, and ignore the results. We do this to
768 "clear" the error state on the socket so that we can later read it
769 reliably. This is reported necessary on the MPE/iX operating system. */
770 (void)verifyconnect(conn->tempsock[i], NULL);
773 /* check socket for connect */
774 rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
776 if(rc == 0) { /* no connection yet */
778 if(Curl_timediff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
779 infof(data, "After %ldms connect time, move on!\n",
780 conn->timeoutms_per_addr);
784 /* should we try another protocol family? */
785 if(i == 0 && conn->tempaddr[1] == NULL &&
786 (Curl_timediff(now, conn->connecttime) >=
787 data->set.happy_eyeballs_timeout)) {
788 trynextip(conn, sockindex, 1);
791 else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
792 if(verifyconnect(conn->tempsock[i], &error)) {
793 /* we are connected with TCP, awesome! */
795 /* use this socket from now on */
796 conn->sock[sockindex] = conn->tempsock[i];
797 conn->ip_addr = conn->tempaddr[i];
798 conn->tempsock[i] = CURL_SOCKET_BAD;
800 conn->bits.ipv6 = (conn->ip_addr->ai_family == AF_INET6)?TRUE:FALSE;
803 /* close the other socket, if open */
804 if(conn->tempsock[other] != CURL_SOCKET_BAD) {
805 Curl_closesocket(conn, conn->tempsock[other]);
806 conn->tempsock[other] = CURL_SOCKET_BAD;
809 /* see if we need to do any proxy magic first once we connected */
810 result = Curl_connected_proxy(conn, sockindex);
814 conn->bits.tcpconnect[sockindex] = TRUE;
817 if(sockindex == FIRSTSOCKET)
818 Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
819 Curl_updateconninfo(conn, conn->sock[sockindex]);
820 Curl_verboseconnect(conn);
824 infof(data, "Connection failed\n");
826 else if(rc & CURL_CSELECT_ERR)
827 (void)verifyconnect(conn->tempsock[i], &error);
830 * The connection failed here, we should attempt to connect to the "next
831 * address" for the given host. But first remember the latest error.
834 data->state.os_errno = error;
835 SET_SOCKERRNO(error);
836 if(conn->tempaddr[i]) {
838 char ipaddress[MAX_IPADR_LEN];
839 Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
840 infof(data, "connect to %s port %ld failed: %s\n",
841 ipaddress, conn->port, Curl_strerror(conn, error));
843 conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
846 status = trynextip(conn, sockindex, i);
847 if(status != CURLE_COULDNT_CONNECT
848 || conn->tempsock[other] == CURL_SOCKET_BAD)
849 /* the last attempt failed and no other sockets remain open */
856 /* no more addresses to try */
858 const char *hostname;
860 /* if the first address family runs out of addresses to try before
861 the happy eyeball timeout, go ahead and try the next family now */
862 if(conn->tempaddr[1] == NULL) {
863 result = trynextip(conn, sockindex, 1);
868 if(conn->bits.socksproxy)
869 hostname = conn->socks_proxy.host.name;
870 else if(conn->bits.httpproxy)
871 hostname = conn->http_proxy.host.name;
872 else if(conn->bits.conn_to_host)
873 hostname = conn->conn_to_host.name;
875 hostname = conn->host.name;
877 failf(data, "Failed to connect to %s port %ld: %s",
878 hostname, conn->port, Curl_strerror(conn, error));
884 void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
886 #if defined(TCP_NODELAY)
887 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
888 struct Curl_easy *data = conn->data;
890 curl_socklen_t onoff = (curl_socklen_t) 1;
891 int level = IPPROTO_TCP;
893 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
897 if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
899 infof(data, "Could not set TCP_NODELAY: %s\n",
900 Curl_strerror(conn, SOCKERRNO));
902 infof(data, "TCP_NODELAY set\n");
910 /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
911 sending data to a dead peer (instead of relying on the 4th argument to send
912 being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
914 static void nosigpipe(struct connectdata *conn,
915 curl_socket_t sockfd)
917 struct Curl_easy *data = conn->data;
919 if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
921 infof(data, "Could not set SO_NOSIGPIPE: %s\n",
922 Curl_strerror(conn, SOCKERRNO));
925 #define nosigpipe(x,y) Curl_nop_stmt
929 /* When you run a program that uses the Windows Sockets API, you may
930 experience slow performance when you copy data to a TCP server.
932 https://support.microsoft.com/kb/823764
934 Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
937 The problem described in this knowledge-base is applied only to pre-Vista
938 Windows. Following function trying to detect OS version and skips
939 SO_SNDBUF adjustment for Windows Vista and above.
941 #define DETECT_OS_NONE 0
942 #define DETECT_OS_PREVISTA 1
943 #define DETECT_OS_VISTA_OR_LATER 2
945 void Curl_sndbufset(curl_socket_t sockfd)
947 int val = CURL_MAX_WRITE_SIZE + 32;
949 int curlen = sizeof(curval);
951 static int detectOsState = DETECT_OS_NONE;
953 if(detectOsState == DETECT_OS_NONE) {
954 if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
955 VERSION_GREATER_THAN_EQUAL))
956 detectOsState = DETECT_OS_VISTA_OR_LATER;
958 detectOsState = DETECT_OS_PREVISTA;
961 if(detectOsState == DETECT_OS_VISTA_OR_LATER)
964 if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
968 setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
975 * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
976 * CURL_SOCKET_BAD. Other errors will however return proper errors.
978 * singleipconnect() connects to the given IP only, and it may return without
981 static CURLcode singleipconnect(struct connectdata *conn,
982 const Curl_addrinfo *ai,
983 curl_socket_t *sockp)
985 struct Curl_sockaddr_ex addr;
988 bool isconnected = FALSE;
989 struct Curl_easy *data = conn->data;
990 curl_socket_t sockfd;
992 char ipaddress[MAX_IPADR_LEN];
995 #ifdef TCP_FASTOPEN_CONNECT
999 *sockp = CURL_SOCKET_BAD;
1001 result = Curl_socket(conn, ai, &addr, &sockfd);
1003 /* Failed to create the socket, but still return OK since we signal the
1004 lack of socket as well. This allows the parent function to keep looping
1005 over alternative addresses/socket families etc. */
1008 /* store remote address and port used in this connection attempt */
1009 if(!Curl_getaddressinfo((struct sockaddr*)&addr.sa_addr,
1010 ipaddress, &port)) {
1011 /* malformed address or bug in inet_ntop, try next address */
1012 failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
1013 errno, Curl_strerror(conn, errno));
1014 Curl_closesocket(conn, sockfd);
1017 infof(data, " Trying %s...\n", ipaddress);
1020 is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
1021 addr.socktype == SOCK_STREAM;
1023 is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
1025 if(is_tcp && data->set.tcp_nodelay)
1026 Curl_tcpnodelay(conn, sockfd);
1028 nosigpipe(conn, sockfd);
1030 Curl_sndbufset(sockfd);
1032 if(is_tcp && data->set.tcp_keepalive)
1033 tcpkeepalive(data, sockfd);
1035 if(data->set.fsockopt) {
1036 /* activate callback for setting socket options */
1037 Curl_set_in_callback(data, true);
1038 error = data->set.fsockopt(data->set.sockopt_client,
1040 CURLSOCKTYPE_IPCXN);
1041 Curl_set_in_callback(data, false);
1043 if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
1046 Curl_closesocket(conn, sockfd); /* close the socket and bail out */
1047 return CURLE_ABORTED_BY_CALLBACK;
1051 /* possibly bind the local end to an IP, interface or port */
1052 if(addr.family == AF_INET
1054 || addr.family == AF_INET6
1057 result = bindlocal(conn, sockfd, addr.family,
1058 Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
1060 Curl_closesocket(conn, sockfd); /* close socket and bail out */
1061 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
1062 /* The address family is not supported on this interface.
1063 We can continue trying addresses */
1064 return CURLE_COULDNT_CONNECT;
1070 /* set socket non-blocking */
1071 (void)curlx_nonblock(sockfd, TRUE);
1073 conn->connecttime = Curl_now();
1074 if(conn->num_addr > 1)
1075 Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME);
1077 /* Connect TCP sockets, bind UDP */
1078 if(!isconnected && (conn->socktype == SOCK_STREAM)) {
1079 if(conn->bits.tcp_fastopen) {
1080 #if defined(CONNECT_DATA_IDEMPOTENT) /* Darwin */
1081 # if defined(HAVE_BUILTIN_AVAILABLE)
1082 /* while connectx function is available since macOS 10.11 / iOS 9,
1083 it did not have the interface declared correctly until
1084 Xcode 9 / macOS SDK 10.13 */
1085 if(__builtin_available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)) {
1086 sa_endpoints_t endpoints;
1087 endpoints.sae_srcif = 0;
1088 endpoints.sae_srcaddr = NULL;
1089 endpoints.sae_srcaddrlen = 0;
1090 endpoints.sae_dstaddr = &addr.sa_addr;
1091 endpoints.sae_dstaddrlen = addr.addrlen;
1093 rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
1094 CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
1095 NULL, 0, NULL, NULL);
1098 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1101 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1102 # endif /* HAVE_BUILTIN_AVAILABLE */
1103 #elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */
1104 if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
1105 (void *)&optval, sizeof(optval)) < 0)
1106 infof(data, "Failed to enable TCP Fast Open on fd %d\n", sockfd);
1108 infof(data, "TCP_FASTOPEN_CONNECT set\n");
1110 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1111 #elif defined(MSG_FASTOPEN) /* old Linux */
1112 if(conn->given->flags & PROTOPT_SSL)
1113 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1115 rc = 0; /* Do nothing */
1119 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1135 #if (EAGAIN) != (EWOULDBLOCK)
1136 /* On some platforms EAGAIN and EWOULDBLOCK are the
1137 * same value, and on others they are different, hence
1147 /* unknown error, fallthrough and try another address! */
1148 infof(data, "Immediate connect fail for %s: %s\n",
1149 ipaddress, Curl_strerror(conn, error));
1150 data->state.os_errno = error;
1152 /* connect failed */
1153 Curl_closesocket(conn, sockfd);
1154 result = CURLE_COULDNT_CONNECT;
1165 * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1166 * There might be more than one IP address to try out. Fill in the passed
1167 * pointer with the connected socket.
1170 CURLcode Curl_connecthost(struct connectdata *conn, /* context */
1171 const struct Curl_dns_entry *remotehost)
1173 struct Curl_easy *data = conn->data;
1174 struct curltime before = Curl_now();
1175 CURLcode result = CURLE_COULDNT_CONNECT;
1177 timediff_t timeout_ms = Curl_timeleft(data, &before, TRUE);
1179 if(timeout_ms < 0) {
1180 /* a precaution, no need to continue if time already is up */
1181 failf(data, "Connection time-out");
1182 return CURLE_OPERATION_TIMEDOUT;
1185 conn->num_addr = Curl_num_addresses(remotehost->addr);
1186 conn->tempaddr[0] = remotehost->addr;
1187 conn->tempaddr[1] = NULL;
1188 conn->tempsock[0] = CURL_SOCKET_BAD;
1189 conn->tempsock[1] = CURL_SOCKET_BAD;
1191 /* Max time for the next connection attempt */
1192 conn->timeoutms_per_addr =
1193 conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
1195 /* start connecting to first IP */
1196 while(conn->tempaddr[0]) {
1197 result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1200 conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
1203 if(conn->tempsock[0] == CURL_SOCKET_BAD) {
1205 result = CURLE_COULDNT_CONNECT;
1209 data->info.numconnects++; /* to track the number of connections made */
1210 Curl_expire(conn->data, data->set.happy_eyeballs_timeout,
1211 EXPIRE_HAPPY_EYEBALLS);
1217 struct connectdata *tofind;
1221 static int conn_is_conn(struct connectdata *conn, void *param)
1223 struct connfind *f = (struct connfind *)param;
1224 if(conn == f->tofind) {
1232 * Used to extract socket and connectdata struct for the most recent
1233 * transfer on the given Curl_easy.
1235 * The returned socket will be CURL_SOCKET_BAD in case of failure!
1237 curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
1238 struct connectdata **connp)
1240 curl_socket_t sockfd;
1244 /* this works for an easy handle:
1245 * - that has been used for curl_easy_perform()
1246 * - that is associated with a multi handle, and whose connection
1247 * was detached with CURLOPT_CONNECT_ONLY
1249 if(data->state.lastconnect && (data->multi_easy || data->multi)) {
1250 struct connectdata *c = data->state.lastconnect;
1251 struct connfind find;
1252 find.tofind = data->state.lastconnect;
1255 Curl_conncache_foreach(data, data->multi_easy?
1256 &data->multi_easy->conn_cache:
1257 &data->multi->conn_cache, &find, conn_is_conn);
1260 data->state.lastconnect = NULL;
1261 return CURL_SOCKET_BAD;
1265 /* only store this if the caller cares for it */
1267 sockfd = c->sock[FIRSTSOCKET];
1270 return CURL_SOCKET_BAD;
1276 * Check if a connection seems to be alive.
1278 bool Curl_connalive(struct connectdata *conn)
1280 /* First determine if ssl */
1281 if(conn->ssl[FIRSTSOCKET].use) {
1282 /* use the SSL context */
1283 if(!Curl_ssl_check_cxn(conn))
1284 return false; /* FIN received */
1286 /* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1288 else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD)
1291 /* use the socket */
1293 if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1294 (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
1295 return false; /* FIN received */
1305 * 'conn' can be NULL, beware!
1307 int Curl_closesocket(struct connectdata *conn,
1310 if(conn && conn->fclosesocket) {
1311 if((sock == conn->sock[SECONDARYSOCKET]) &&
1312 conn->sock_accepted[SECONDARYSOCKET])
1313 /* if this socket matches the second socket, and that was created with
1314 accept, then we MUST NOT call the callback but clear the accepted
1316 conn->sock_accepted[SECONDARYSOCKET] = FALSE;
1319 Curl_multi_closed(conn, sock);
1320 Curl_set_in_callback(conn->data, true);
1321 rc = conn->fclosesocket(conn->closesocket_client, sock);
1322 Curl_set_in_callback(conn->data, false);
1328 /* tell the multi-socket code about this */
1329 Curl_multi_closed(conn, sock);
1337 * Create a socket based on info from 'conn' and 'ai'.
1339 * 'addr' should be a pointer to the correct struct to get data back, or NULL.
1340 * 'sockfd' must be a pointer to a socket descriptor.
1342 * If the open socket callback is set, used that!
1345 CURLcode Curl_socket(struct connectdata *conn,
1346 const Curl_addrinfo *ai,
1347 struct Curl_sockaddr_ex *addr,
1348 curl_socket_t *sockfd)
1350 struct Curl_easy *data = conn->data;
1351 struct Curl_sockaddr_ex dummy;
1354 /* if the caller doesn't want info back, use a local temp copy */
1358 * The Curl_sockaddr_ex structure is basically libcurl's external API
1359 * curl_sockaddr structure with enough space available to directly hold
1360 * any protocol-specific address structures. The variable declared here
1361 * will be used to pass / receive data to/from the fopensocket callback
1362 * if this has been set, before that, it is initialized from parameters.
1365 addr->family = ai->ai_family;
1366 addr->socktype = conn->socktype;
1367 addr->protocol = conn->socktype == SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1368 addr->addrlen = ai->ai_addrlen;
1370 if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
1371 addr->addrlen = sizeof(struct Curl_sockaddr_storage);
1372 memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
1374 if(data->set.fopensocket) {
1376 * If the opensocket callback is set, all the destination address
1377 * information is passed to the callback. Depending on this information the
1378 * callback may opt to abort the connection, this is indicated returning
1379 * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
1380 * the callback returns a valid socket the destination address information
1381 * might have been changed and this 'new' address will actually be used
1384 Curl_set_in_callback(data, true);
1385 *sockfd = data->set.fopensocket(data->set.opensocket_client,
1387 (struct curl_sockaddr *)addr);
1388 Curl_set_in_callback(data, false);
1391 /* opensocket callback not set, so simply create the socket now */
1392 *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1394 if(*sockfd == CURL_SOCKET_BAD)
1395 /* no socket, no connection */
1396 return CURLE_COULDNT_CONNECT;
1398 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
1399 if(conn->scope_id && (addr->family == AF_INET6)) {
1400 struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
1401 sa6->sin6_scope_id = conn->scope_id;
1410 * Curl_conncontrol() marks streams or connection for closure.
1412 void Curl_conncontrol(struct connectdata *conn,
1413 int ctrl /* see defines in header */
1414 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
1415 , const char *reason
1419 /* close if a connection, or a stream that isn't multiplexed */
1420 bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
1421 ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
1422 if((ctrl == CONNCTRL_STREAM) &&
1423 (conn->handler->flags & PROTOPT_STREAM))
1424 DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
1425 else if(closeit != conn->bits.close) {
1426 DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
1427 closeit?"closure":"keep alive", reason));
1428 conn->bits.close = closeit; /* the only place in the source code that
1429 should assign this bit */
1433 /* Data received can be cached at various levels, so check them all here. */
1434 bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
1438 if(Curl_ssl_data_pending(conn, sockindex) ||
1439 Curl_recv_has_postponed_data(conn, sockindex))
1442 readable = SOCKET_READABLE(conn->sock[sockindex], 0);
1443 return (readable > 0 && (readable & CURL_CSELECT_IN));