1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2016, 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_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
65 #include "url.h" /* for Curl_safefree() */
67 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
68 #include "inet_ntop.h"
69 #include "inet_pton.h"
70 #include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
73 #include "conncache.h"
74 #include "multihandle.h"
75 #include "system_win32.h"
77 /* The last 3 #include files should be in this order */
78 #include "curl_printf.h"
79 #include "curl_memory.h"
83 /* This isn't actually supported under Symbian OS */
87 static bool verifyconnect(curl_socket_t sockfd, int *error);
89 #if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
90 /* DragonFlyBSD and Windows use millisecond units */
91 #define KEEPALIVE_FACTOR(x) (x *= 1000)
93 #define KEEPALIVE_FACTOR(x)
96 #if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
97 #define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
99 struct tcp_keepalive {
101 u_long keepalivetime;
102 u_long keepaliveinterval;
107 tcpkeepalive(struct Curl_easy *data,
108 curl_socket_t sockfd)
110 int optval = data->set.tcp_keepalive?1:0;
112 /* only set IDLE and INTVL if setting KEEPALIVE is successful */
113 if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
114 (void *)&optval, sizeof(optval)) < 0) {
115 infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd);
118 #if defined(SIO_KEEPALIVE_VALS)
119 struct tcp_keepalive vals;
122 optval = curlx_sltosi(data->set.tcp_keepidle);
123 KEEPALIVE_FACTOR(optval);
124 vals.keepalivetime = optval;
125 optval = curlx_sltosi(data->set.tcp_keepintvl);
126 KEEPALIVE_FACTOR(optval);
127 vals.keepaliveinterval = optval;
128 if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
129 NULL, 0, &dummy, NULL, NULL) != 0) {
130 infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
131 (int)sockfd, WSAGetLastError());
135 optval = curlx_sltosi(data->set.tcp_keepidle);
136 KEEPALIVE_FACTOR(optval);
137 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
138 (void *)&optval, sizeof(optval)) < 0) {
139 infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd);
143 optval = curlx_sltosi(data->set.tcp_keepintvl);
144 KEEPALIVE_FACTOR(optval);
145 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
146 (void *)&optval, sizeof(optval)) < 0) {
147 infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd);
152 optval = curlx_sltosi(data->set.tcp_keepidle);
153 KEEPALIVE_FACTOR(optval);
154 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
155 (void *)&optval, sizeof(optval)) < 0) {
156 infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd);
164 singleipconnect(struct connectdata *conn,
165 const Curl_addrinfo *ai, /* start connecting to this */
166 curl_socket_t *sock);
169 * Curl_timeleft() returns the amount of milliseconds left allowed for the
170 * transfer/connection. If the value is negative, the timeout time has already
173 * The start time is stored in progress.t_startsingle - as set with
174 * Curl_pgrsTime(..., TIMER_STARTSINGLE);
176 * If 'nowp' is non-NULL, it points to the current time.
177 * 'duringconnect' is FALSE if not during a connect, as then of course the
178 * connect timeout is not taken into account!
182 time_t Curl_timeleft(struct Curl_easy *data,
183 struct timeval *nowp,
187 time_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
190 /* if a timeout is set, use the most restrictive one */
192 if(data->set.timeout > 0)
194 if(duringconnect && (data->set.connecttimeout > 0))
197 switch(timeout_set) {
199 timeout_ms = data->set.timeout;
202 timeout_ms = data->set.connecttimeout;
205 if(data->set.timeout < data->set.connecttimeout)
206 timeout_ms = data->set.timeout;
208 timeout_ms = data->set.connecttimeout;
211 /* use the default */
213 /* if we're not during connect, there's no default timeout so if we're
214 at zero we better just return zero and not make it a negative number
225 /* subtract elapsed time */
227 /* since this most recent connect started */
228 timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
230 /* since the entire operation started */
231 timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop);
233 /* avoid returning 0 as that means no timeout! */
239 static CURLcode bindlocal(struct connectdata *conn,
240 curl_socket_t sockfd, int af, unsigned int scope)
242 struct Curl_easy *data = conn->data;
244 struct Curl_sockaddr_storage sa;
245 struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
246 curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
247 struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
249 struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
252 struct Curl_dns_entry *h=NULL;
253 unsigned short port = data->set.localport; /* use this port number, 0 for
255 /* how many port numbers to try to bind to, increasing one at a time */
256 int portnum = data->set.localportrange;
257 const char *dev = data->set.str[STRING_DEVICE];
260 /*************************************************************
261 * Select device to bind socket to
262 *************************************************************/
264 /* no local kind of binding was requested */
267 memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
269 if(dev && (strlen(dev)<255) ) {
270 char myhost[256] = "";
271 int done = 0; /* -1 for error, 1 for address found */
272 bool is_interface = FALSE;
273 bool is_host = FALSE;
274 static const char *if_prefix = "if!";
275 static const char *host_prefix = "host!";
277 if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
278 dev += strlen(if_prefix);
281 else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
282 dev += strlen(host_prefix);
288 switch(Curl_if2ip(af, scope, conn->scope_id, dev,
289 myhost, sizeof(myhost))) {
290 case IF2IP_NOT_FOUND:
292 /* Do not fall back to treating it as a host name */
293 failf(data, "Couldn't bind to interface '%s'", dev);
294 return CURLE_INTERFACE_FAILED;
297 case IF2IP_AF_NOT_SUPPORTED:
298 /* Signal the caller to try another address family if available */
299 return CURLE_UNSUPPORTED_PROTOCOL;
303 * We now have the numerical IP address in the 'myhost' buffer
305 infof(data, "Local Interface %s is ip %s using address family %i\n",
309 #ifdef SO_BINDTODEVICE
310 /* I am not sure any other OSs than Linux that provide this feature,
311 * and at the least I cannot test. --Ben
313 * This feature allows one to tightly bind the local socket to a
314 * particular interface. This will force even requests to other
315 * local interfaces to go out the external interface.
318 * Only bind to the interface when specified as interface, not just
319 * as a hostname or ip address.
321 if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
322 dev, (curl_socklen_t)strlen(dev)+1) != 0) {
324 infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
325 " will do regular bind\n",
326 dev, error, Curl_strerror(conn, error));
327 /* This is typically "errno 1, error: Operation not permitted" if
328 you're not running as root or another suitable privileged
337 * This was not an interface, resolve the name as a host name
340 * Temporarily force name resolution to use only the address type
341 * of the connection. The resolve functions should really be changed
342 * to take a type parameter instead.
344 long ipver = conn->ip_version;
348 conn->ip_version = CURL_IPRESOLVE_V4;
350 else if(af == AF_INET6)
351 conn->ip_version = CURL_IPRESOLVE_V6;
354 rc = Curl_resolv(conn, dev, 0, &h);
355 if(rc == CURLRESOLV_PENDING)
356 (void)Curl_resolver_wait_resolv(conn, &h);
357 conn->ip_version = ipver;
360 /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
361 Curl_printable_address(h->addr, myhost, sizeof(myhost));
362 infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
363 dev, af, myhost, h->addr->ai_family);
364 Curl_resolv_unlock(data, h);
369 * provided dev was no interface (or interfaces are not supported
370 * e.g. solaris) no ip address and no domain we fail here
380 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
381 char *scope_ptr = strchr(myhost, '%');
385 if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
386 si6->sin6_family = AF_INET6;
387 si6->sin6_port = htons(port);
388 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
390 /* The "myhost" string either comes from Curl_if2ip or from
391 Curl_printable_address. The latter returns only numeric scope
392 IDs and the former returns none at all. So the scope ID, if
393 present, is known to be numeric */
394 si6->sin6_scope_id = atoi(scope_ptr);
397 sizeof_sa = sizeof(struct sockaddr_in6);
402 if((af == AF_INET) &&
403 (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
404 si4->sin_family = AF_INET;
405 si4->sin_port = htons(port);
406 sizeof_sa = sizeof(struct sockaddr_in);
411 failf(data, "Couldn't bind to '%s'", dev);
412 return CURLE_INTERFACE_FAILED;
416 /* no device was given, prepare sa to match af's needs */
419 si6->sin6_family = AF_INET6;
420 si6->sin6_port = htons(port);
421 sizeof_sa = sizeof(struct sockaddr_in6);
426 si4->sin_family = AF_INET;
427 si4->sin_port = htons(port);
428 sizeof_sa = sizeof(struct sockaddr_in);
433 if(bind(sockfd, sock, sizeof_sa) >= 0) {
434 /* we succeeded to bind */
435 struct Curl_sockaddr_storage add;
436 curl_socklen_t size = sizeof(add);
437 memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
438 if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
439 data->state.os_errno = error = SOCKERRNO;
440 failf(data, "getsockname() failed with errno %d: %s",
441 error, Curl_strerror(conn, error));
442 return CURLE_INTERFACE_FAILED;
444 infof(data, "Local port: %hu\n", port);
445 conn->bits.bound = TRUE;
450 infof(data, "Bind to local port %hu failed, trying next\n", port);
451 port++; /* try next port */
452 /* We re-use/clobber the port variable here below */
453 if(sock->sa_family == AF_INET)
454 si4->sin_port = ntohs(port);
457 si6->sin6_port = ntohs(port);
464 data->state.os_errno = error = SOCKERRNO;
465 failf(data, "bind failed with errno %d: %s",
466 error, Curl_strerror(conn, error));
468 return CURLE_INTERFACE_FAILED;
472 * verifyconnect() returns TRUE if the connect really has happened.
474 static bool verifyconnect(curl_socket_t sockfd, int *error)
479 curl_socklen_t errSize = sizeof(err);
483 * In October 2003 we effectively nullified this function on Windows due to
484 * problems with it using all CPU in multi-threaded cases.
486 * In May 2004, we bring it back to offer more info back on connect failures.
487 * Gisle Vanem could reproduce the former problems with this function, but
488 * could avoid them by adding this SleepEx() call below:
490 * "I don't have Rational Quantify, but the hint from his post was
491 * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
492 * just Sleep(0) would be enough?) would release whatever
493 * mutex/critical-section the ntdll call is waiting on.
495 * Someone got to verify this on Win-NT 4.0, 2000."
506 if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
509 /* Old WinCE versions don't support SO_ERROR */
510 if(WSAENOPROTOOPT == err) {
516 /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
517 if(EBADIOCTL == err) {
522 if((0 == err) || (EISCONN == err))
523 /* we are connected, awesome! */
526 /* This wasn't a successful connect */
538 /* Used within the multi interface. Try next IP address, return TRUE if no
539 more address exists or error */
540 static CURLcode trynextip(struct connectdata *conn,
544 const int other = tempindex ^ 1;
545 CURLcode result = CURLE_COULDNT_CONNECT;
547 /* First clean up after the failed socket.
548 Don't close it yet to ensure that the next IP's socket gets a different
549 file descriptor, which can prevent bugs when the curl_multi_socket_action
550 interface is used with certain select() replacements such as kqueue. */
551 curl_socket_t fd_to_close = conn->tempsock[tempindex];
552 conn->tempsock[tempindex] = CURL_SOCKET_BAD;
554 if(sockindex == FIRSTSOCKET) {
555 Curl_addrinfo *ai = NULL;
556 int family = AF_UNSPEC;
558 if(conn->tempaddr[tempindex]) {
559 /* find next address in the same protocol family */
560 family = conn->tempaddr[tempindex]->ai_family;
561 ai = conn->tempaddr[tempindex]->ai_next;
564 else if(conn->tempaddr[0]) {
565 /* happy eyeballs - try the other protocol family */
566 int firstfamily = conn->tempaddr[0]->ai_family;
567 family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
568 ai = conn->tempaddr[0]->ai_next;
573 if(conn->tempaddr[other]) {
574 /* we can safely skip addresses of the other protocol family */
575 while(ai && ai->ai_family != family)
580 result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
581 if(result == CURLE_COULDNT_CONNECT) {
586 conn->tempaddr[tempindex] = ai;
592 if(fd_to_close != CURL_SOCKET_BAD)
593 Curl_closesocket(conn, fd_to_close);
598 /* Copies connection info into the session handle to make it available
599 when the session handle is no longer associated with a connection. */
600 void Curl_persistconninfo(struct connectdata *conn)
602 memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
603 memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
604 conn->data->info.conn_scheme = conn->handler->scheme;
605 conn->data->info.conn_protocol = conn->handler->protocol;
606 conn->data->info.conn_primary_port = conn->primary_port;
607 conn->data->info.conn_local_port = conn->local_port;
610 /* retrieves ip address and port from a sockaddr structure */
611 static bool getaddressinfo(struct sockaddr *sa, char *addr,
614 unsigned short us_port;
615 struct sockaddr_in *si = NULL;
617 struct sockaddr_in6 *si6 = NULL;
619 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
620 struct sockaddr_un *su = NULL;
623 switch(sa->sa_family) {
625 si = (struct sockaddr_in *)(void *) sa;
626 if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
627 addr, MAX_IPADR_LEN)) {
628 us_port = ntohs(si->sin_port);
635 si6 = (struct sockaddr_in6 *)(void *) sa;
636 if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
637 addr, MAX_IPADR_LEN)) {
638 us_port = ntohs(si6->sin6_port);
644 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
646 su = (struct sockaddr_un*)sa;
647 snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
661 /* retrieves the start/end point information of a socket of an established
663 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
666 struct Curl_sockaddr_storage ssrem;
667 struct Curl_sockaddr_storage ssloc;
668 struct Curl_easy *data = conn->data;
670 if(conn->socktype == SOCK_DGRAM)
671 /* there's no connection! */
674 if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
677 len = sizeof(struct Curl_sockaddr_storage);
678 if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
680 failf(data, "getpeername() failed with errno %d: %s",
681 error, Curl_strerror(conn, error));
685 len = sizeof(struct Curl_sockaddr_storage);
686 memset(&ssloc, 0, sizeof(ssloc));
687 if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
689 failf(data, "getsockname() failed with errno %d: %s",
690 error, Curl_strerror(conn, error));
694 if(!getaddressinfo((struct sockaddr*)&ssrem,
695 conn->primary_ip, &conn->primary_port)) {
697 failf(data, "ssrem inet_ntop() failed with errno %d: %s",
698 error, Curl_strerror(conn, error));
701 memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
703 if(!getaddressinfo((struct sockaddr*)&ssloc,
704 conn->local_ip, &conn->local_port)) {
706 failf(data, "ssloc inet_ntop() failed with errno %d: %s",
707 error, Curl_strerror(conn, error));
713 /* persist connection info in session handle */
714 Curl_persistconninfo(conn);
718 * Curl_is_connected() checks if the socket has connected.
721 CURLcode Curl_is_connected(struct connectdata *conn,
725 struct Curl_easy *data = conn->data;
726 CURLcode result = CURLE_OK;
733 DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
735 *connected = FALSE; /* a very negative world view is best */
737 if(conn->bits.tcpconnect[sockindex]) {
738 /* we are connected already! */
745 /* figure out how long time we have left to connect */
746 allow = Curl_timeleft(data, &now, TRUE);
749 /* time-out, bail out, go home */
750 failf(data, "Connection time-out");
751 return CURLE_OPERATION_TIMEDOUT;
755 const int other = i ^ 1;
756 if(conn->tempsock[i] == CURL_SOCKET_BAD)
760 /* Call this function once now, and ignore the results. We do this to
761 "clear" the error state on the socket so that we can later read it
762 reliably. This is reported necessary on the MPE/iX operating system. */
763 (void)verifyconnect(conn->tempsock[i], NULL);
766 /* check socket for connect */
767 rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
769 if(rc == 0) { /* no connection yet */
771 if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
772 infof(data, "After %ldms connect time, move on!\n",
773 conn->timeoutms_per_addr);
777 /* should we try another protocol family? */
778 if(i == 0 && conn->tempaddr[1] == NULL &&
779 curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
780 trynextip(conn, sockindex, 1);
783 else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
784 if(verifyconnect(conn->tempsock[i], &error)) {
785 /* we are connected with TCP, awesome! */
787 /* use this socket from now on */
788 conn->sock[sockindex] = conn->tempsock[i];
789 conn->ip_addr = conn->tempaddr[i];
790 conn->tempsock[i] = CURL_SOCKET_BAD;
792 /* close the other socket, if open */
793 if(conn->tempsock[other] != CURL_SOCKET_BAD) {
794 Curl_closesocket(conn, conn->tempsock[other]);
795 conn->tempsock[other] = CURL_SOCKET_BAD;
798 /* see if we need to do any proxy magic first once we connected */
799 result = Curl_connected_proxy(conn, sockindex);
803 conn->bits.tcpconnect[sockindex] = TRUE;
806 if(sockindex == FIRSTSOCKET)
807 Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
808 Curl_updateconninfo(conn, conn->sock[sockindex]);
809 Curl_verboseconnect(conn);
814 infof(data, "Connection failed\n");
816 else if(rc & CURL_CSELECT_ERR)
817 (void)verifyconnect(conn->tempsock[i], &error);
820 * The connection failed here, we should attempt to connect to the "next
821 * address" for the given host. But first remember the latest error.
824 data->state.os_errno = error;
825 SET_SOCKERRNO(error);
826 if(conn->tempaddr[i]) {
828 char ipaddress[MAX_IPADR_LEN];
829 Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
830 infof(data, "connect to %s port %ld failed: %s\n",
831 ipaddress, conn->port, Curl_strerror(conn, error));
833 conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
836 status = trynextip(conn, sockindex, i);
837 if(status != CURLE_COULDNT_CONNECT
838 || conn->tempsock[other] == CURL_SOCKET_BAD)
839 /* the last attempt failed and no other sockets remain open */
846 /* no more addresses to try */
848 const char *hostname;
850 /* if the first address family runs out of addresses to try before
851 the happy eyeball timeout, go ahead and try the next family now */
852 if(conn->tempaddr[1] == NULL) {
853 result = trynextip(conn, sockindex, 1);
858 if(conn->bits.socksproxy)
859 hostname = conn->socks_proxy.host.name;
860 else if(conn->bits.httpproxy)
861 hostname = conn->http_proxy.host.name;
862 else if(conn->bits.conn_to_host)
863 hostname = conn->conn_to_host.name;
865 hostname = conn->host.name;
867 failf(data, "Failed to connect to %s port %ld: %s",
868 hostname, conn->port, Curl_strerror(conn, error));
874 void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
876 #if defined(TCP_NODELAY)
877 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
878 struct Curl_easy *data = conn->data;
880 curl_socklen_t onoff = (curl_socklen_t) 1;
881 int level = IPPROTO_TCP;
884 /* The use of getprotobyname() is disabled since it isn't thread-safe on
885 numerous systems. On these getprotobyname_r() should be used instead, but
886 that exists in at least one 4 arg version and one 5 arg version, and
887 since the proto number rarely changes anyway we now just use the hard
888 coded number. The "proper" fix would need a configure check for the
889 correct function much in the same style the gethostbyname_r versions are
891 struct protoent *pe = getprotobyname("tcp");
896 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
900 if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
902 infof(data, "Could not set TCP_NODELAY: %s\n",
903 Curl_strerror(conn, SOCKERRNO));
905 infof(data, "TCP_NODELAY set\n");
913 /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
914 sending data to a dead peer (instead of relying on the 4th argument to send
915 being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
917 static void nosigpipe(struct connectdata *conn,
918 curl_socket_t sockfd)
920 struct Curl_easy *data= conn->data;
922 if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
924 infof(data, "Could not set SO_NOSIGPIPE: %s\n",
925 Curl_strerror(conn, SOCKERRNO));
928 #define nosigpipe(x,y) Curl_nop_stmt
932 /* When you run a program that uses the Windows Sockets API, you may
933 experience slow performance when you copy data to a TCP server.
935 https://support.microsoft.com/kb/823764
937 Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
940 The problem described in this knowledge-base is applied only to pre-Vista
941 Windows. Following function trying to detect OS version and skips
942 SO_SNDBUF adjustment for Windows Vista and above.
944 #define DETECT_OS_NONE 0
945 #define DETECT_OS_PREVISTA 1
946 #define DETECT_OS_VISTA_OR_LATER 2
948 void Curl_sndbufset(curl_socket_t sockfd)
950 int val = CURL_MAX_WRITE_SIZE + 32;
952 int curlen = sizeof(curval);
954 static int detectOsState = DETECT_OS_NONE;
956 if(detectOsState == DETECT_OS_NONE) {
957 if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
958 VERSION_GREATER_THAN_EQUAL))
959 detectOsState = DETECT_OS_VISTA_OR_LATER;
961 detectOsState = DETECT_OS_PREVISTA;
964 if(detectOsState == DETECT_OS_VISTA_OR_LATER)
967 if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
971 setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
978 * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
979 * CURL_SOCKET_BAD. Other errors will however return proper errors.
981 * singleipconnect() connects to the given IP only, and it may return without
984 static CURLcode singleipconnect(struct connectdata *conn,
985 const Curl_addrinfo *ai,
986 curl_socket_t *sockp)
988 struct Curl_sockaddr_ex addr;
991 bool isconnected = FALSE;
992 struct Curl_easy *data = conn->data;
993 curl_socket_t sockfd;
995 char ipaddress[MAX_IPADR_LEN];
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(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
1010 ipaddress, &port)) {
1011 /* malformed address or bug in inet_ntop, try next address */
1013 failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
1014 error, Curl_strerror(conn, error));
1015 Curl_closesocket(conn, sockfd);
1018 infof(data, " Trying %s...\n", ipaddress);
1021 is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
1022 addr.socktype == SOCK_STREAM;
1024 is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
1026 if(is_tcp && data->set.tcp_nodelay)
1027 Curl_tcpnodelay(conn, sockfd);
1029 nosigpipe(conn, sockfd);
1031 Curl_sndbufset(sockfd);
1033 if(is_tcp && data->set.tcp_keepalive)
1034 tcpkeepalive(data, sockfd);
1036 if(data->set.fsockopt) {
1037 /* activate callback for setting socket options */
1038 error = data->set.fsockopt(data->set.sockopt_client,
1040 CURLSOCKTYPE_IPCXN);
1042 if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
1045 Curl_closesocket(conn, sockfd); /* close the socket and bail out */
1046 return CURLE_ABORTED_BY_CALLBACK;
1050 /* possibly bind the local end to an IP, interface or port */
1051 if(addr.family == AF_INET
1053 || addr.family == AF_INET6
1056 result = bindlocal(conn, sockfd, addr.family,
1057 Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
1059 Curl_closesocket(conn, sockfd); /* close socket and bail out */
1060 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
1061 /* The address family is not supported on this interface.
1062 We can continue trying addresses */
1063 return CURLE_COULDNT_CONNECT;
1069 /* set socket non-blocking */
1070 (void)curlx_nonblock(sockfd, TRUE);
1072 conn->connecttime = Curl_tvnow();
1073 if(conn->num_addr > 1)
1074 Curl_expire_latest(data, conn->timeoutms_per_addr);
1076 /* Connect TCP sockets, bind UDP */
1077 if(!isconnected && (conn->socktype == SOCK_STREAM)) {
1078 if(conn->bits.tcp_fastopen) {
1079 #if defined(CONNECT_DATA_IDEMPOTENT) /* OS X */
1080 sa_endpoints_t endpoints;
1081 endpoints.sae_srcif = 0;
1082 endpoints.sae_srcaddr = NULL;
1083 endpoints.sae_srcaddrlen = 0;
1084 endpoints.sae_dstaddr = &addr.sa_addr;
1085 endpoints.sae_dstaddrlen = addr.addrlen;
1087 rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
1088 CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
1089 NULL, 0, NULL, NULL);
1090 #elif defined(MSG_FASTOPEN) /* Linux */
1091 if(conn->given->flags & PROTOPT_SSL)
1092 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1094 rc = 0; /* Do nothing */
1098 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1110 conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
1118 #if (EAGAIN) != (EWOULDBLOCK)
1119 /* On some platforms EAGAIN and EWOULDBLOCK are the
1120 * same value, and on others they are different, hence
1130 /* unknown error, fallthrough and try another address! */
1131 infof(data, "Immediate connect fail for %s: %s\n",
1132 ipaddress, Curl_strerror(conn, error));
1133 data->state.os_errno = error;
1135 /* connect failed */
1136 Curl_closesocket(conn, sockfd);
1137 result = CURLE_COULDNT_CONNECT;
1148 * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1149 * There might be more than one IP address to try out. Fill in the passed
1150 * pointer with the connected socket.
1153 CURLcode Curl_connecthost(struct connectdata *conn, /* context */
1154 const struct Curl_dns_entry *remotehost)
1156 struct Curl_easy *data = conn->data;
1157 struct timeval before = Curl_tvnow();
1158 CURLcode result = CURLE_COULDNT_CONNECT;
1160 time_t timeout_ms = Curl_timeleft(data, &before, TRUE);
1162 if(timeout_ms < 0) {
1163 /* a precaution, no need to continue if time already is up */
1164 failf(data, "Connection time-out");
1165 return CURLE_OPERATION_TIMEDOUT;
1168 conn->num_addr = Curl_num_addresses(remotehost->addr);
1169 conn->tempaddr[0] = remotehost->addr;
1170 conn->tempaddr[1] = NULL;
1171 conn->tempsock[0] = CURL_SOCKET_BAD;
1172 conn->tempsock[1] = CURL_SOCKET_BAD;
1173 Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
1175 /* Max time for the next connection attempt */
1176 conn->timeoutms_per_addr =
1177 conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
1179 /* start connecting to first IP */
1180 while(conn->tempaddr[0]) {
1181 result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1184 conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
1187 if(conn->tempsock[0] == CURL_SOCKET_BAD) {
1189 result = CURLE_COULDNT_CONNECT;
1193 data->info.numconnects++; /* to track the number of connections made */
1199 struct connectdata *tofind;
1203 static int conn_is_conn(struct connectdata *conn, void *param)
1205 struct connfind *f = (struct connfind *)param;
1206 if(conn == f->tofind) {
1214 * Used to extract socket and connectdata struct for the most recent
1215 * transfer on the given Curl_easy.
1217 * The returned socket will be CURL_SOCKET_BAD in case of failure!
1219 curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
1220 struct connectdata **connp)
1222 curl_socket_t sockfd;
1226 /* this works for an easy handle:
1227 * - that has been used for curl_easy_perform()
1228 * - that is associated with a multi handle, and whose connection
1229 * was detached with CURLOPT_CONNECT_ONLY
1231 if(data->state.lastconnect && (data->multi_easy || data->multi)) {
1232 struct connectdata *c = data->state.lastconnect;
1233 struct connfind find;
1234 find.tofind = data->state.lastconnect;
1237 Curl_conncache_foreach(data->multi_easy?
1238 &data->multi_easy->conn_cache:
1239 &data->multi->conn_cache, &find, conn_is_conn);
1242 data->state.lastconnect = NULL;
1243 return CURL_SOCKET_BAD;
1247 /* only store this if the caller cares for it */
1249 sockfd = c->sock[FIRSTSOCKET];
1252 return CURL_SOCKET_BAD;
1258 * Check if a connection seems to be alive.
1260 bool Curl_connalive(struct connectdata *conn)
1262 /* First determine if ssl */
1263 if(conn->ssl[FIRSTSOCKET].use) {
1264 /* use the SSL context */
1265 if(!Curl_ssl_check_cxn(conn))
1266 return false; /* FIN received */
1268 /* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1270 else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD)
1273 /* use the socket */
1275 if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1276 (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
1277 return false; /* FIN received */
1287 * 'conn' can be NULL, beware!
1289 int Curl_closesocket(struct connectdata *conn,
1292 if(conn && conn->fclosesocket) {
1293 if((sock == conn->sock[SECONDARYSOCKET]) &&
1294 conn->sock_accepted[SECONDARYSOCKET])
1295 /* if this socket matches the second socket, and that was created with
1296 accept, then we MUST NOT call the callback but clear the accepted
1298 conn->sock_accepted[SECONDARYSOCKET] = FALSE;
1300 Curl_multi_closed(conn, sock);
1301 return conn->fclosesocket(conn->closesocket_client, sock);
1306 /* tell the multi-socket code about this */
1307 Curl_multi_closed(conn, sock);
1315 * Create a socket based on info from 'conn' and 'ai'.
1317 * 'addr' should be a pointer to the correct struct to get data back, or NULL.
1318 * 'sockfd' must be a pointer to a socket descriptor.
1320 * If the open socket callback is set, used that!
1323 CURLcode Curl_socket(struct connectdata *conn,
1324 const Curl_addrinfo *ai,
1325 struct Curl_sockaddr_ex *addr,
1326 curl_socket_t *sockfd)
1328 struct Curl_easy *data = conn->data;
1329 struct Curl_sockaddr_ex dummy;
1332 /* if the caller doesn't want info back, use a local temp copy */
1336 * The Curl_sockaddr_ex structure is basically libcurl's external API
1337 * curl_sockaddr structure with enough space available to directly hold
1338 * any protocol-specific address structures. The variable declared here
1339 * will be used to pass / receive data to/from the fopensocket callback
1340 * if this has been set, before that, it is initialized from parameters.
1343 addr->family = ai->ai_family;
1344 addr->socktype = conn->socktype;
1345 addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1346 addr->addrlen = ai->ai_addrlen;
1348 if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
1349 addr->addrlen = sizeof(struct Curl_sockaddr_storage);
1350 memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
1352 if(data->set.fopensocket)
1354 * If the opensocket callback is set, all the destination address
1355 * information is passed to the callback. Depending on this information the
1356 * callback may opt to abort the connection, this is indicated returning
1357 * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
1358 * the callback returns a valid socket the destination address information
1359 * might have been changed and this 'new' address will actually be used
1362 *sockfd = data->set.fopensocket(data->set.opensocket_client,
1364 (struct curl_sockaddr *)addr);
1366 /* opensocket callback not set, so simply create the socket now */
1367 *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1369 if(*sockfd == CURL_SOCKET_BAD)
1370 /* no socket, no connection */
1371 return CURLE_COULDNT_CONNECT;
1373 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
1374 if(conn->scope_id && (addr->family == AF_INET6)) {
1375 struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
1376 sa6->sin6_scope_id = conn->scope_id;
1385 * Curl_conncontrol() marks streams or connection for closure.
1387 void Curl_conncontrol(struct connectdata *conn,
1388 int ctrl /* see defines in header */
1390 , const char *reason
1394 /* close if a connection, or a stream that isn't multiplexed */
1395 bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
1396 ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
1397 if((ctrl == CONNCTRL_STREAM) &&
1398 (conn->handler->flags & PROTOPT_STREAM))
1399 DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
1400 else if(closeit != conn->bits.close) {
1401 DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
1402 closeit?"closure":"keep alive", reason));
1403 conn->bits.close = closeit; /* the only place in the source code that
1404 should assign this bit */
1408 /* Data received can be cached at various levels, so check them all here. */
1409 bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
1413 if(Curl_ssl_data_pending(conn, sockindex) ||
1414 Curl_recv_has_postponed_data(conn, sockindex))
1417 readable = SOCKET_READABLE(conn->sock[sockindex], 0);
1418 return (readable > 0 && (readable & CURL_CSELECT_IN));