blob: 1a27ae1353e975b691ffa3f95d4503d62d619f47 [file] [log] [blame]
Kristian Monsen5ab50182010-05-14 18:53:44 +01001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
Elliott Hughes82be86d2017-09-20 17:00:17 -07008 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
Kristian Monsen5ab50182010-05-14 18:53:44 +01009 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
Alex Deymod15eaac2016-06-28 14:49:26 -070012 * are also available at https://curl.haxx.se/docs/copyright.html.
Kristian Monsen5ab50182010-05-14 18:53:44 +010013 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070023#include "curl_setup.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010024
Kristian Monsen5ab50182010-05-14 18:53:44 +010025#ifdef HAVE_NETINET_IN_H
26#include <netinet/in.h> /* <netinet/tcp.h> may need it */
27#endif
28#ifdef HAVE_SYS_UN_H
29#include <sys/un.h> /* for sockaddr_un */
30#endif
Alex Deymo486467e2017-12-19 19:04:07 +010031#ifdef HAVE_LINUX_TCP_H
32#include <linux/tcp.h>
33#elif defined(HAVE_NETINET_TCP_H)
34#include <netinet/tcp.h>
Kristian Monsen5ab50182010-05-14 18:53:44 +010035#endif
36#ifdef HAVE_SYS_IOCTL_H
37#include <sys/ioctl.h>
38#endif
Kristian Monsen5ab50182010-05-14 18:53:44 +010039#ifdef HAVE_NETDB_H
40#include <netdb.h>
41#endif
42#ifdef HAVE_FCNTL_H
43#include <fcntl.h>
44#endif
45#ifdef HAVE_ARPA_INET_H
46#include <arpa/inet.h>
47#endif
Kristian Monsen5ab50182010-05-14 18:53:44 +010048
49#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
50#include <sys/filio.h>
51#endif
52#ifdef NETWARE
53#undef in_addr_t
54#define in_addr_t unsigned long
55#endif
56#ifdef __VMS
57#include <in.h>
58#include <inet.h>
59#endif
60
Kristian Monsen5ab50182010-05-14 18:53:44 +010061#include "urldata.h"
62#include "sendf.h"
63#include "if2ip.h"
64#include "strerror.h"
65#include "connect.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010066#include "select.h"
67#include "url.h" /* for Curl_safefree() */
68#include "multiif.h"
69#include "sockaddr.h" /* required for Curl_sockaddr_storage */
70#include "inet_ntop.h"
71#include "inet_pton.h"
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070072#include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
Kristian Monsen5ab50182010-05-14 18:53:44 +010073#include "progress.h"
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070074#include "warnless.h"
75#include "conncache.h"
76#include "multihandle.h"
Alex Deymoe3149cc2016-10-05 11:18:42 -070077#include "system_win32.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010078
Alex Deymod15eaac2016-06-28 14:49:26 -070079/* The last 3 #include files should be in this order */
80#include "curl_printf.h"
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070081#include "curl_memory.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010082#include "memdebug.h"
83
84#ifdef __SYMBIAN32__
85/* This isn't actually supported under Symbian OS */
86#undef SO_NOSIGPIPE
87#endif
88
Kristian Monsen5ab50182010-05-14 18:53:44 +010089static bool verifyconnect(curl_socket_t sockfd, int *error);
90
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070091#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
92/* DragonFlyBSD and Windows use millisecond units */
93#define KEEPALIVE_FACTOR(x) (x *= 1000)
94#else
95#define KEEPALIVE_FACTOR(x)
96#endif
97
98#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
99#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
100
101struct tcp_keepalive {
102 u_long onoff;
103 u_long keepalivetime;
104 u_long keepaliveinterval;
105};
106#endif
107
108static void
Alex Deymoe3149cc2016-10-05 11:18:42 -0700109tcpkeepalive(struct Curl_easy *data,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700110 curl_socket_t sockfd)
111{
112 int optval = data->set.tcp_keepalive?1:0;
113
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);
118 }
119 else {
120#if defined(SIO_KEEPALIVE_VALS)
121 struct tcp_keepalive vals;
122 DWORD dummy;
123 vals.onoff = 1;
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());
134 }
135#else
136#ifdef TCP_KEEPIDLE
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);
142 }
143#endif
144#ifdef TCP_KEEPINTVL
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);
150 }
151#endif
152#ifdef TCP_KEEPALIVE
153 /* Mac OS X style */
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);
159 }
160#endif
161#endif
162 }
163}
164
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700165static CURLcode
Kristian Monsen5ab50182010-05-14 18:53:44 +0100166singleipconnect(struct connectdata *conn,
167 const Curl_addrinfo *ai, /* start connecting to this */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700168 curl_socket_t *sock);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100169
170/*
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
173 * elapsed.
174 *
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700175 * The start time is stored in progress.t_startsingle - as set with
176 * Curl_pgrsTime(..., TIMER_STARTSINGLE);
177 *
Kristian Monsen5ab50182010-05-14 18:53:44 +0100178 * 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!
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700181 *
182 * @unittest: 1303
Kristian Monsen5ab50182010-05-14 18:53:44 +0100183 */
Alex Deymo486467e2017-12-19 19:04:07 +0100184timediff_t Curl_timeleft(struct Curl_easy *data,
185 struct curltime *nowp,
186 bool duringconnect)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100187{
Kristian Monsen5ab50182010-05-14 18:53:44 +0100188 int timeout_set = 0;
Alex Deymo486467e2017-12-19 19:04:07 +0100189 timediff_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
Elliott Hughes82be86d2017-09-20 17:00:17 -0700190 struct curltime now;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100191
192 /* if a timeout is set, use the most restrictive one */
193
194 if(data->set.timeout > 0)
195 timeout_set |= 1;
196 if(duringconnect && (data->set.connecttimeout > 0))
197 timeout_set |= 2;
198
Elliott Hughes82be86d2017-09-20 17:00:17 -0700199 switch(timeout_set) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100200 case 1:
201 timeout_ms = data->set.timeout;
202 break;
203 case 2:
204 timeout_ms = data->set.connecttimeout;
205 break;
206 case 3:
207 if(data->set.timeout < data->set.connecttimeout)
208 timeout_ms = data->set.timeout;
209 else
210 timeout_ms = data->set.connecttimeout;
211 break;
212 default:
213 /* use the default */
214 if(!duringconnect)
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
217 by the math below */
218 return 0;
219 break;
220 }
221
222 if(!nowp) {
Alex Deymo486467e2017-12-19 19:04:07 +0100223 now = Curl_now();
Kristian Monsen5ab50182010-05-14 18:53:44 +0100224 nowp = &now;
225 }
226
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700227 /* subtract elapsed time */
228 if(duringconnect)
229 /* since this most recent connect started */
Alex Deymo486467e2017-12-19 19:04:07 +0100230 timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700231 else
232 /* since the entire operation started */
Alex Deymo486467e2017-12-19 19:04:07 +0100233 timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700234 if(!timeout_ms)
235 /* avoid returning 0 as that means no timeout! */
236 return -1;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100237
238 return timeout_ms;
239}
240
Kristian Monsen5ab50182010-05-14 18:53:44 +0100241static CURLcode bindlocal(struct connectdata *conn,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700242 curl_socket_t sockfd, int af, unsigned int scope)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100243{
Alex Deymoe3149cc2016-10-05 11:18:42 -0700244 struct Curl_easy *data = conn->data;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100245
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;
250#ifdef ENABLE_IPV6
251 struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
252#endif
253
Alex Deymo486467e2017-12-19 19:04:07 +0100254 struct Curl_dns_entry *h = NULL;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100255 unsigned short port = data->set.localport; /* use this port number, 0 for
256 "random" */
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];
260 int error;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100261
262 /*************************************************************
263 * Select device to bind socket to
264 *************************************************************/
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700265 if(!dev && !port)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100266 /* no local kind of binding was requested */
267 return CURLE_OK;
268
269 memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
270
271 if(dev && (strlen(dev)<255) ) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700272 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!";
278
279 if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
280 dev += strlen(if_prefix);
281 is_interface = TRUE;
282 }
283 else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
284 dev += strlen(host_prefix);
285 is_host = TRUE;
286 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100287
288 /* interface */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700289 if(!is_host) {
Alex Deymo486467e2017-12-19 19:04:07 +0100290#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
293 *
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.
297 *
298 *
299 * Only bind to the interface when specified as interface, not just
300 * as a hostname or ip address.
301 *
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.
305 */
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
310 * user.
311 * If it succeeds it means the parameter was a valid interface and
312 * not an IP address. Return immediately.
313 */
314 return CURLE_OK;
315 }
316#endif
317
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700318 switch(Curl_if2ip(af, scope, conn->scope_id, dev,
319 myhost, sizeof(myhost))) {
320 case IF2IP_NOT_FOUND:
321 if(is_interface) {
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;
325 }
326 break;
327 case IF2IP_AF_NOT_SUPPORTED:
328 /* Signal the caller to try another address family if available */
329 return CURLE_UNSUPPORTED_PROTOCOL;
330 case IF2IP_FOUND:
331 is_interface = TRUE;
332 /*
333 * We now have the numerical IP address in the 'myhost' buffer
334 */
335 infof(data, "Local Interface %s is ip %s using address family %i\n",
336 dev, myhost, af);
337 done = 1;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700338 break;
339 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100340 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700341 if(!is_interface) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100342 /*
343 * This was not an interface, resolve the name as a host name
344 * or IP number
345 *
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.
349 */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700350 long ipver = conn->ip_version;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100351 int rc;
352
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700353 if(af == AF_INET)
354 conn->ip_version = CURL_IPRESOLVE_V4;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100355#ifdef ENABLE_IPV6
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700356 else if(af == AF_INET6)
357 conn->ip_version = CURL_IPRESOLVE_V6;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100358#endif
359
360 rc = Curl_resolv(conn, dev, 0, &h);
361 if(rc == CURLRESOLV_PENDING)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700362 (void)Curl_resolver_wait_resolv(conn, &h);
363 conn->ip_version = ipver;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100364
365 if(h) {
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);
371 done = 1;
372 }
373 else {
374 /*
375 * provided dev was no interface (or interfaces are not supported
376 * e.g. solaris) no ip address and no domain we fail here
377 */
378 done = -1;
379 }
380 }
381
382 if(done > 0) {
383#ifdef ENABLE_IPV6
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700384 /* IPv6 address */
385 if(af == AF_INET6) {
386#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
387 char *scope_ptr = strchr(myhost, '%');
388 if(scope_ptr)
389 *(scope_ptr++) = 0;
390#endif
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
395 if(scope_ptr)
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);
401#endif
402 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100403 sizeof_sa = sizeof(struct sockaddr_in6);
404 }
405 else
406#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700407 /* IPv4 address */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100408 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);
413 }
414 }
415
416 if(done < 1) {
Alex Deymo486467e2017-12-19 19:04:07 +0100417 /* 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;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100421 failf(data, "Couldn't bind to '%s'", dev);
422 return CURLE_INTERFACE_FAILED;
423 }
424 }
425 else {
426 /* no device was given, prepare sa to match af's needs */
427#ifdef ENABLE_IPV6
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700428 if(af == AF_INET6) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100429 si6->sin6_family = AF_INET6;
430 si6->sin6_port = htons(port);
431 sizeof_sa = sizeof(struct sockaddr_in6);
432 }
433 else
434#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700435 if(af == AF_INET) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100436 si4->sin_family = AF_INET;
437 si4->sin_port = htons(port);
438 sizeof_sa = sizeof(struct sockaddr_in);
439 }
440 }
441
442 for(;;) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700443 if(bind(sockfd, sock, sizeof_sa) >= 0) {
444 /* we succeeded to bind */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100445 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;
453 }
454 infof(data, "Local port: %hu\n", port);
455 conn->bits.bound = TRUE;
456 return CURLE_OK;
457 }
458
459 if(--portnum > 0) {
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);
465#ifdef ENABLE_IPV6
466 else
467 si6->sin6_port = ntohs(port);
468#endif
469 }
470 else
471 break;
472 }
473
474 data->state.os_errno = error = SOCKERRNO;
475 failf(data, "bind failed with errno %d: %s",
476 error, Curl_strerror(conn, error));
477
478 return CURLE_INTERFACE_FAILED;
479}
480
481/*
482 * verifyconnect() returns TRUE if the connect really has happened.
483 */
484static bool verifyconnect(curl_socket_t sockfd, int *error)
485{
486 bool rc = TRUE;
487#ifdef SO_ERROR
488 int err = 0;
489 curl_socklen_t errSize = sizeof(err);
490
491#ifdef WIN32
492 /*
493 * In October 2003 we effectively nullified this function on Windows due to
494 * problems with it using all CPU in multi-threaded cases.
495 *
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:
499 *
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.
504 *
505 * Someone got to verify this on Win-NT 4.0, 2000."
506 */
507
508#ifdef _WIN32_WCE
509 Sleep(0);
510#else
511 SleepEx(0, FALSE);
512#endif
513
514#endif
515
516 if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
517 err = SOCKERRNO;
518#ifdef _WIN32_WCE
519 /* Old WinCE versions don't support SO_ERROR */
520 if(WSAENOPROTOOPT == err) {
521 SET_SOCKERRNO(0);
522 err = 0;
523 }
524#endif
525#ifdef __minix
526 /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
527 if(EBADIOCTL == err) {
528 SET_SOCKERRNO(0);
529 err = 0;
530 }
531#endif
532 if((0 == err) || (EISCONN == err))
533 /* we are connected, awesome! */
534 rc = TRUE;
535 else
536 /* This wasn't a successful connect */
537 rc = FALSE;
538 if(error)
539 *error = err;
540#else
541 (void)sockfd;
542 if(error)
543 *error = SOCKERRNO;
544#endif
545 return rc;
546}
547
548/* Used within the multi interface. Try next IP address, return TRUE if no
549 more address exists or error */
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700550static CURLcode trynextip(struct connectdata *conn,
551 int sockindex,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700552 int tempindex)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100553{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700554 const int other = tempindex ^ 1;
555 CURLcode result = CURLE_COULDNT_CONNECT;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100556
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700557 /* 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. */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700561 curl_socket_t fd_to_close = conn->tempsock[tempindex];
562 conn->tempsock[tempindex] = CURL_SOCKET_BAD;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100563
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700564 if(sockindex == FIRSTSOCKET) {
565 Curl_addrinfo *ai = NULL;
566 int family = AF_UNSPEC;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100567
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700568 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;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100572 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700573#ifdef ENABLE_IPV6
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;
579 }
580#endif
581
582 while(ai) {
583 if(conn->tempaddr[other]) {
584 /* we can safely skip addresses of the other protocol family */
585 while(ai && ai->ai_family != family)
586 ai = ai->ai_next;
587 }
588
589 if(ai) {
590 result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
591 if(result == CURLE_COULDNT_CONNECT) {
592 ai = ai->ai_next;
593 continue;
594 }
595
596 conn->tempaddr[tempindex] = ai;
597 }
598 break;
599 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100600 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700601
602 if(fd_to_close != CURL_SOCKET_BAD)
603 Curl_closesocket(conn, fd_to_close);
604
605 return result;
606}
607
608/* Copies connection info into the session handle to make it available
609 when the session handle is no longer associated with a connection. */
610void Curl_persistconninfo(struct connectdata *conn)
611{
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);
Elliott Hughescee03382017-06-23 12:17:18 -0700614 conn->data->info.conn_scheme = conn->handler->scheme;
615 conn->data->info.conn_protocol = conn->handler->protocol;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700616 conn->data->info.conn_primary_port = conn->primary_port;
617 conn->data->info.conn_local_port = conn->local_port;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700618}
619
Elliott Hughes82be86d2017-09-20 17:00:17 -0700620/* retrieves ip address and port from a sockaddr structure.
621 note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
Elliott Hughescac39802018-04-27 16:19:43 -0700622bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
623 long *port)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700624{
625 unsigned short us_port;
Elliott Hughescee03382017-06-23 12:17:18 -0700626 struct sockaddr_in *si = NULL;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700627#ifdef ENABLE_IPV6
Elliott Hughescee03382017-06-23 12:17:18 -0700628 struct sockaddr_in6 *si6 = NULL;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700629#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700630#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
Elliott Hughescee03382017-06-23 12:17:18 -0700631 struct sockaddr_un *su = NULL;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700632#endif
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700633
Elliott Hughes82be86d2017-09-20 17:00:17 -0700634 switch(sa->sa_family) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700635 case AF_INET:
Elliott Hughescee03382017-06-23 12:17:18 -0700636 si = (struct sockaddr_in *)(void *) sa;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700637 if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700638 addr, MAX_IPADR_LEN)) {
639 us_port = ntohs(si->sin_port);
640 *port = us_port;
641 return TRUE;
642 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700643 break;
644#ifdef ENABLE_IPV6
645 case AF_INET6:
Elliott Hughescee03382017-06-23 12:17:18 -0700646 si6 = (struct sockaddr_in6 *)(void *) sa;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700647 if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700648 addr, MAX_IPADR_LEN)) {
649 us_port = ntohs(si6->sin6_port);
650 *port = us_port;
651 return TRUE;
652 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700653 break;
654#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700655#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
656 case AF_UNIX:
657 su = (struct sockaddr_un*)sa;
658 snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700659 *port = 0;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700660 return TRUE;
661#endif
662 default:
663 break;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700664 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700665
666 addr[0] = '\0';
667 *port = 0;
Elliott Hughes82be86d2017-09-20 17:00:17 -0700668 errno = EAFNOSUPPORT;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700669 return FALSE;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100670}
671
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700672/* retrieves the start/end point information of a socket of an established
673 connection */
674void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
675{
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700676 curl_socklen_t len;
677 struct Curl_sockaddr_storage ssrem;
678 struct Curl_sockaddr_storage ssloc;
Alex Deymoe3149cc2016-10-05 11:18:42 -0700679 struct Curl_easy *data = conn->data;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700680
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700681 if(conn->socktype == SOCK_DGRAM)
682 /* there's no connection! */
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700683 return;
684
Alex Deymod15eaac2016-06-28 14:49:26 -0700685 if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700686 len = sizeof(struct Curl_sockaddr_storage);
687 if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
Elliott Hughes82be86d2017-09-20 17:00:17 -0700688 int error = SOCKERRNO;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700689 failf(data, "getpeername() failed with errno %d: %s",
690 error, Curl_strerror(conn, error));
691 return;
692 }
693
694 len = sizeof(struct Curl_sockaddr_storage);
695 memset(&ssloc, 0, sizeof(ssloc));
696 if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
Elliott Hughes82be86d2017-09-20 17:00:17 -0700697 int error = SOCKERRNO;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700698 failf(data, "getsockname() failed with errno %d: %s",
699 error, Curl_strerror(conn, error));
700 return;
701 }
702
Elliott Hughescac39802018-04-27 16:19:43 -0700703 if(!Curl_getaddressinfo((struct sockaddr*)&ssrem,
704 conn->primary_ip, &conn->primary_port)) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700705 failf(data, "ssrem inet_ntop() failed with errno %d: %s",
Elliott Hughes82be86d2017-09-20 17:00:17 -0700706 errno, Curl_strerror(conn, errno));
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700707 return;
708 }
709 memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
710
Elliott Hughescac39802018-04-27 16:19:43 -0700711 if(!Curl_getaddressinfo((struct sockaddr*)&ssloc,
712 conn->local_ip, &conn->local_port)) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700713 failf(data, "ssloc inet_ntop() failed with errno %d: %s",
Elliott Hughes82be86d2017-09-20 17:00:17 -0700714 errno, Curl_strerror(conn, errno));
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700715 return;
716 }
717
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700718 }
719
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700720 /* persist connection info in session handle */
721 Curl_persistconninfo(conn);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700722}
723
Kristian Monsen5ab50182010-05-14 18:53:44 +0100724/*
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700725 * Curl_is_connected() checks if the socket has connected.
Kristian Monsen5ab50182010-05-14 18:53:44 +0100726 */
727
728CURLcode Curl_is_connected(struct connectdata *conn,
729 int sockindex,
730 bool *connected)
731{
Alex Deymoe3149cc2016-10-05 11:18:42 -0700732 struct Curl_easy *data = conn->data;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700733 CURLcode result = CURLE_OK;
Alex Deymo486467e2017-12-19 19:04:07 +0100734 timediff_t allow;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700735 int error = 0;
Elliott Hughes82be86d2017-09-20 17:00:17 -0700736 struct curltime now;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700737 int rc;
738 int i;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100739
740 DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
741
742 *connected = FALSE; /* a very negative world view is best */
743
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700744 if(conn->bits.tcpconnect[sockindex]) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100745 /* we are connected already! */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100746 *connected = TRUE;
747 return CURLE_OK;
748 }
749
Alex Deymo486467e2017-12-19 19:04:07 +0100750 now = Curl_now();
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700751
Kristian Monsen5ab50182010-05-14 18:53:44 +0100752 /* figure out how long time we have left to connect */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700753 allow = Curl_timeleft(data, &now, TRUE);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100754
755 if(allow < 0) {
756 /* time-out, bail out, go home */
757 failf(data, "Connection time-out");
758 return CURLE_OPERATION_TIMEDOUT;
759 }
760
Alex Deymo486467e2017-12-19 19:04:07 +0100761 for(i = 0; i<2; i++) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700762 const int other = i ^ 1;
763 if(conn->tempsock[i] == CURL_SOCKET_BAD)
764 continue;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100765
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700766#ifdef mpeix
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);
771#endif
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700772
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700773 /* check socket for connect */
Elliott Hughescee03382017-06-23 12:17:18 -0700774 rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700775
776 if(rc == 0) { /* no connection yet */
Alex Deymod15eaac2016-06-28 14:49:26 -0700777 error = 0;
Alex Deymo486467e2017-12-19 19:04:07 +0100778 if(Curl_timediff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700779 infof(data, "After %ldms connect time, move on!\n",
780 conn->timeoutms_per_addr);
781 error = ETIMEDOUT;
782 }
783
784 /* should we try another protocol family? */
785 if(i == 0 && conn->tempaddr[1] == NULL &&
Elliott Hughescac39802018-04-27 16:19:43 -0700786 (Curl_timediff(now, conn->connecttime) >=
787 data->set.happy_eyeballs_timeout)) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700788 trynextip(conn, sockindex, 1);
789 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100790 }
Alex Deymod15eaac2016-06-28 14:49:26 -0700791 else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700792 if(verifyconnect(conn->tempsock[i], &error)) {
793 /* we are connected with TCP, awesome! */
794
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;
Alex Deymo486467e2017-12-19 19:04:07 +0100799#ifdef ENABLE_IPV6
800 conn->bits.ipv6 = (conn->ip_addr->ai_family == AF_INET6)?TRUE:FALSE;
801#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700802
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;
807 }
808
809 /* see if we need to do any proxy magic first once we connected */
810 result = Curl_connected_proxy(conn, sockindex);
811 if(result)
812 return result;
813
814 conn->bits.tcpconnect[sockindex] = TRUE;
815
816 *connected = TRUE;
817 if(sockindex == FIRSTSOCKET)
818 Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
819 Curl_updateconninfo(conn, conn->sock[sockindex]);
820 Curl_verboseconnect(conn);
821
822 return CURLE_OK;
823 }
Elliott Hughes82be86d2017-09-20 17:00:17 -0700824 infof(data, "Connection failed\n");
Kristian Monsen5ab50182010-05-14 18:53:44 +0100825 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700826 else if(rc & CURL_CSELECT_ERR)
827 (void)verifyconnect(conn->tempsock[i], &error);
828
829 /*
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.
832 */
833 if(error) {
834 data->state.os_errno = error;
835 SET_SOCKERRNO(error);
836 if(conn->tempaddr[i]) {
837 CURLcode status;
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));
842
843 conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
844 allow : allow / 2;
845
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 */
850 result = status;
851 }
852 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100853 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700854
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700855 if(result) {
856 /* no more addresses to try */
857
Elliott Hughescee03382017-06-23 12:17:18 -0700858 const char *hostname;
Alex Deymod15eaac2016-06-28 14:49:26 -0700859
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700860 /* 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);
864 if(!result)
865 return result;
866 }
867
Elliott Hughescee03382017-06-23 12:17:18 -0700868 if(conn->bits.socksproxy)
869 hostname = conn->socks_proxy.host.name;
870 else if(conn->bits.httpproxy)
871 hostname = conn->http_proxy.host.name;
Alex Deymod15eaac2016-06-28 14:49:26 -0700872 else if(conn->bits.conn_to_host)
873 hostname = conn->conn_to_host.name;
874 else
875 hostname = conn->host.name;
876
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700877 failf(data, "Failed to connect to %s port %ld: %s",
Alex Deymod15eaac2016-06-28 14:49:26 -0700878 hostname, conn->port, Curl_strerror(conn, error));
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700879 }
880
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700881 return result;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100882}
883
Alex Deymod15eaac2016-06-28 14:49:26 -0700884void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100885{
Alex Deymod15eaac2016-06-28 14:49:26 -0700886#if defined(TCP_NODELAY)
887#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
Alex Deymoe3149cc2016-10-05 11:18:42 -0700888 struct Curl_easy *data = conn->data;
Alex Deymod15eaac2016-06-28 14:49:26 -0700889#endif
890 curl_socklen_t onoff = (curl_socklen_t) 1;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700891 int level = IPPROTO_TCP;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100892
Alex Deymod15eaac2016-06-28 14:49:26 -0700893#if defined(CURL_DISABLE_VERBOSE_STRINGS)
894 (void) conn;
895#endif
896
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700897 if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
Kristian Monsen5ab50182010-05-14 18:53:44 +0100898 sizeof(onoff)) < 0)
899 infof(data, "Could not set TCP_NODELAY: %s\n",
900 Curl_strerror(conn, SOCKERRNO));
901 else
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700902 infof(data, "TCP_NODELAY set\n");
Kristian Monsen5ab50182010-05-14 18:53:44 +0100903#else
904 (void)conn;
905 (void)sockfd;
906#endif
907}
908
909#ifdef SO_NOSIGPIPE
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
913 systems? */
914static void nosigpipe(struct connectdata *conn,
915 curl_socket_t sockfd)
916{
Alex Deymo486467e2017-12-19 19:04:07 +0100917 struct Curl_easy *data = conn->data;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100918 int onoff = 1;
919 if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
920 sizeof(onoff)) < 0)
921 infof(data, "Could not set SO_NOSIGPIPE: %s\n",
922 Curl_strerror(conn, SOCKERRNO));
923}
924#else
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700925#define nosigpipe(x,y) Curl_nop_stmt
Kristian Monsen5ab50182010-05-14 18:53:44 +0100926#endif
927
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700928#ifdef USE_WINSOCK
Kristian Monsen5ab50182010-05-14 18:53:44 +0100929/* 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.
931
Alex Deymod15eaac2016-06-28 14:49:26 -0700932 https://support.microsoft.com/kb/823764
Kristian Monsen5ab50182010-05-14 18:53:44 +0100933
934 Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
935 Buffer Size
936
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700937 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.
Kristian Monsen5ab50182010-05-14 18:53:44 +0100940*/
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700941#define DETECT_OS_NONE 0
942#define DETECT_OS_PREVISTA 1
943#define DETECT_OS_VISTA_OR_LATER 2
944
Kristian Monsen5ab50182010-05-14 18:53:44 +0100945void Curl_sndbufset(curl_socket_t sockfd)
946{
947 int val = CURL_MAX_WRITE_SIZE + 32;
948 int curval = 0;
949 int curlen = sizeof(curval);
950
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700951 static int detectOsState = DETECT_OS_NONE;
952
953 if(detectOsState == DETECT_OS_NONE) {
Alex Deymoe3149cc2016-10-05 11:18:42 -0700954 if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
955 VERSION_GREATER_THAN_EQUAL))
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700956 detectOsState = DETECT_OS_VISTA_OR_LATER;
957 else
958 detectOsState = DETECT_OS_PREVISTA;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700959 }
960
961 if(detectOsState == DETECT_OS_VISTA_OR_LATER)
962 return;
963
964 if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
965 if(curval > val)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100966 return;
967
968 setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
969}
970#endif
971
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700972/*
973 * singleipconnect()
974 *
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.
977 *
978 * singleipconnect() connects to the given IP only, and it may return without
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700979 * having connected.
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700980 */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700981static CURLcode singleipconnect(struct connectdata *conn,
982 const Curl_addrinfo *ai,
983 curl_socket_t *sockp)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100984{
985 struct Curl_sockaddr_ex addr;
Alex Deymod15eaac2016-06-28 14:49:26 -0700986 int rc = -1;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700987 int error = 0;
988 bool isconnected = FALSE;
Alex Deymoe3149cc2016-10-05 11:18:42 -0700989 struct Curl_easy *data = conn->data;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100990 curl_socket_t sockfd;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700991 CURLcode result;
992 char ipaddress[MAX_IPADR_LEN];
993 long port;
994 bool is_tcp;
Alex Deymo486467e2017-12-19 19:04:07 +0100995#ifdef TCP_FASTOPEN_CONNECT
996 int optval = 1;
997#endif
Kristian Monsen5ab50182010-05-14 18:53:44 +0100998
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700999 *sockp = CURL_SOCKET_BAD;
1000
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001001 result = Curl_socket(conn, ai, &addr, &sockfd);
1002 if(result)
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. */
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001006 return CURLE_OK;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001007
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001008 /* store remote address and port used in this connection attempt */
Elliott Hughescac39802018-04-27 16:19:43 -07001009 if(!Curl_getaddressinfo((struct sockaddr*)&addr.sa_addr,
1010 ipaddress, &port)) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001011 /* malformed address or bug in inet_ntop, try next address */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001012 failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
Elliott Hughes82be86d2017-09-20 17:00:17 -07001013 errno, Curl_strerror(conn, errno));
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001014 Curl_closesocket(conn, sockfd);
1015 return CURLE_OK;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001016 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001017 infof(data, " Trying %s...\n", ipaddress);
1018
Kristian Monsen5ab50182010-05-14 18:53:44 +01001019#ifdef ENABLE_IPV6
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001020 is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
1021 addr.socktype == SOCK_STREAM;
1022#else
1023 is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001024#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001025 if(is_tcp && data->set.tcp_nodelay)
Alex Deymod15eaac2016-06-28 14:49:26 -07001026 Curl_tcpnodelay(conn, sockfd);
Kristian Monsen5ab50182010-05-14 18:53:44 +01001027
1028 nosigpipe(conn, sockfd);
1029
1030 Curl_sndbufset(sockfd);
1031
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001032 if(is_tcp && data->set.tcp_keepalive)
1033 tcpkeepalive(data, sockfd);
1034
Kristian Monsen5ab50182010-05-14 18:53:44 +01001035 if(data->set.fsockopt) {
1036 /* activate callback for setting socket options */
Elliott Hughescac39802018-04-27 16:19:43 -07001037 Curl_set_in_callback(data, true);
Kristian Monsen5ab50182010-05-14 18:53:44 +01001038 error = data->set.fsockopt(data->set.sockopt_client,
1039 sockfd,
1040 CURLSOCKTYPE_IPCXN);
Elliott Hughescac39802018-04-27 16:19:43 -07001041 Curl_set_in_callback(data, false);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001042
1043 if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
1044 isconnected = TRUE;
1045 else if(error) {
1046 Curl_closesocket(conn, sockfd); /* close the socket and bail out */
1047 return CURLE_ABORTED_BY_CALLBACK;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001048 }
1049 }
1050
1051 /* possibly bind the local end to an IP, interface or port */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001052 if(addr.family == AF_INET
1053#ifdef ENABLE_IPV6
1054 || addr.family == AF_INET6
1055#endif
1056 ) {
1057 result = bindlocal(conn, sockfd, addr.family,
1058 Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
1059 if(result) {
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;
1065 }
1066 return result;
1067 }
Kristian Monsen5ab50182010-05-14 18:53:44 +01001068 }
1069
1070 /* set socket non-blocking */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001071 (void)curlx_nonblock(sockfd, TRUE);
1072
Alex Deymo486467e2017-12-19 19:04:07 +01001073 conn->connecttime = Curl_now();
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001074 if(conn->num_addr > 1)
Elliott Hughes82be86d2017-09-20 17:00:17 -07001075 Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME);
Kristian Monsen5ab50182010-05-14 18:53:44 +01001076
1077 /* Connect TCP sockets, bind UDP */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001078 if(!isconnected && (conn->socktype == SOCK_STREAM)) {
Alex Deymod15eaac2016-06-28 14:49:26 -07001079 if(conn->bits.tcp_fastopen) {
Alex Deymo486467e2017-12-19 19:04:07 +01001080#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;
Alex Deymod15eaac2016-06-28 14:49:26 -07001092
Alex Deymo486467e2017-12-19 19:04:07 +01001093 rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
1094 CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
1095 NULL, 0, NULL, NULL);
1096 }
1097 else {
1098 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1099 }
1100# else
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);
1107 else
1108 infof(data, "TCP_FASTOPEN_CONNECT set\n");
1109
1110 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1111#elif defined(MSG_FASTOPEN) /* old Linux */
Alex Deymoe3149cc2016-10-05 11:18:42 -07001112 if(conn->given->flags & PROTOPT_SSL)
1113 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1114 else
1115 rc = 0; /* Do nothing */
Alex Deymod15eaac2016-06-28 14:49:26 -07001116#endif
1117 }
1118 else {
1119 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1120 }
1121
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001122 if(-1 == rc)
1123 error = SOCKERRNO;
1124 }
1125 else {
1126 *sockp = sockfd;
1127 return CURLE_OK;
1128 }
1129
Kristian Monsen5ab50182010-05-14 18:53:44 +01001130 if(-1 == rc) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001131 switch(error) {
Kristian Monsen5ab50182010-05-14 18:53:44 +01001132 case EINPROGRESS:
1133 case EWOULDBLOCK:
1134#if defined(EAGAIN)
1135#if (EAGAIN) != (EWOULDBLOCK)
1136 /* On some platforms EAGAIN and EWOULDBLOCK are the
1137 * same value, and on others they are different, hence
1138 * the odd #if
1139 */
1140 case EAGAIN:
1141#endif
1142#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001143 result = CURLE_OK;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001144 break;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001145
Kristian Monsen5ab50182010-05-14 18:53:44 +01001146 default:
1147 /* unknown error, fallthrough and try another address! */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001148 infof(data, "Immediate connect fail for %s: %s\n",
1149 ipaddress, Curl_strerror(conn, error));
Kristian Monsen5ab50182010-05-14 18:53:44 +01001150 data->state.os_errno = error;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001151
1152 /* connect failed */
1153 Curl_closesocket(conn, sockfd);
1154 result = CURLE_COULDNT_CONNECT;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001155 }
1156 }
1157
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001158 if(!result)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001159 *sockp = sockfd;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001160
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001161 return result;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001162}
1163
1164/*
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.
1168 */
1169
1170CURLcode Curl_connecthost(struct connectdata *conn, /* context */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001171 const struct Curl_dns_entry *remotehost)
Kristian Monsen5ab50182010-05-14 18:53:44 +01001172{
Alex Deymoe3149cc2016-10-05 11:18:42 -07001173 struct Curl_easy *data = conn->data;
Alex Deymo486467e2017-12-19 19:04:07 +01001174 struct curltime before = Curl_now();
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001175 CURLcode result = CURLE_COULDNT_CONNECT;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001176
Alex Deymo486467e2017-12-19 19:04:07 +01001177 timediff_t timeout_ms = Curl_timeleft(data, &before, TRUE);
Kristian Monsen5ab50182010-05-14 18:53:44 +01001178
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;
1183 }
Kristian Monsen5ab50182010-05-14 18:53:44 +01001184
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001185 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;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001190
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001191 /* Max time for the next connection attempt */
1192 conn->timeoutms_per_addr =
1193 conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001194
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001195 /* start connecting to first IP */
1196 while(conn->tempaddr[0]) {
1197 result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1198 if(!result)
Kristian Monsen5ab50182010-05-14 18:53:44 +01001199 break;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001200 conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001201 }
1202
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001203 if(conn->tempsock[0] == CURL_SOCKET_BAD) {
1204 if(!result)
1205 result = CURLE_COULDNT_CONNECT;
1206 return result;
1207 }
Kristian Monsen5ab50182010-05-14 18:53:44 +01001208
1209 data->info.numconnects++; /* to track the number of connections made */
Elliott Hughescac39802018-04-27 16:19:43 -07001210 Curl_expire(conn->data, data->set.happy_eyeballs_timeout,
1211 EXPIRE_HAPPY_EYEBALLS);
Kristian Monsen5ab50182010-05-14 18:53:44 +01001212
1213 return CURLE_OK;
1214}
1215
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001216struct connfind {
1217 struct connectdata *tofind;
1218 bool found;
1219};
1220
1221static int conn_is_conn(struct connectdata *conn, void *param)
1222{
1223 struct connfind *f = (struct connfind *)param;
1224 if(conn == f->tofind) {
1225 f->found = TRUE;
1226 return 1;
1227 }
1228 return 0;
1229}
1230
Kristian Monsen5ab50182010-05-14 18:53:44 +01001231/*
1232 * Used to extract socket and connectdata struct for the most recent
Alex Deymoe3149cc2016-10-05 11:18:42 -07001233 * transfer on the given Curl_easy.
Kristian Monsen5ab50182010-05-14 18:53:44 +01001234 *
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001235 * The returned socket will be CURL_SOCKET_BAD in case of failure!
Kristian Monsen5ab50182010-05-14 18:53:44 +01001236 */
Alex Deymoe3149cc2016-10-05 11:18:42 -07001237curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001238 struct connectdata **connp)
Kristian Monsen5ab50182010-05-14 18:53:44 +01001239{
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001240 curl_socket_t sockfd;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001241
1242 DEBUGASSERT(data);
1243
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
1248 */
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;
1253 find.found = FALSE;
1254
Alex Deymo486467e2017-12-19 19:04:07 +01001255 Curl_conncache_foreach(data, data->multi_easy?
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001256 &data->multi_easy->conn_cache:
1257 &data->multi->conn_cache, &find, conn_is_conn);
1258
1259 if(!find.found) {
1260 data->state.lastconnect = NULL;
1261 return CURL_SOCKET_BAD;
1262 }
1263
Kristian Monsen5ab50182010-05-14 18:53:44 +01001264 if(connp)
1265 /* only store this if the caller cares for it */
1266 *connp = c;
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001267 sockfd = c->sock[FIRSTSOCKET];
Kristian Monsen5ab50182010-05-14 18:53:44 +01001268 }
1269 else
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001270 return CURL_SOCKET_BAD;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001271
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001272 return sockfd;
Kristian Monsen5ab50182010-05-14 18:53:44 +01001273}
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001274
1275/*
Elliott Hughes82be86d2017-09-20 17:00:17 -07001276 * Check if a connection seems to be alive.
1277 */
1278bool Curl_connalive(struct connectdata *conn)
1279{
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 */
1285 }
1286/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1287#ifdef MSG_PEEK
1288 else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD)
1289 return false;
1290 else {
1291 /* use the socket */
1292 char buf;
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 */
1296 }
1297 }
1298#endif
1299 return true;
1300}
1301
1302/*
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001303 * Close a socket.
1304 *
1305 * 'conn' can be NULL, beware!
1306 */
1307int Curl_closesocket(struct connectdata *conn,
1308 curl_socket_t sock)
1309{
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
1315 status */
1316 conn->sock_accepted[SECONDARYSOCKET] = FALSE;
1317 else {
Elliott Hughescac39802018-04-27 16:19:43 -07001318 int rc;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001319 Curl_multi_closed(conn, sock);
Elliott Hughescac39802018-04-27 16:19:43 -07001320 Curl_set_in_callback(conn->data, true);
1321 rc = conn->fclosesocket(conn->closesocket_client, sock);
1322 Curl_set_in_callback(conn->data, false);
1323 return rc;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001324 }
1325 }
1326
1327 if(conn)
1328 /* tell the multi-socket code about this */
1329 Curl_multi_closed(conn, sock);
1330
1331 sclose(sock);
1332
1333 return 0;
1334}
1335
1336/*
1337 * Create a socket based on info from 'conn' and 'ai'.
1338 *
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.
1341 *
1342 * If the open socket callback is set, used that!
1343 *
1344 */
1345CURLcode Curl_socket(struct connectdata *conn,
1346 const Curl_addrinfo *ai,
1347 struct Curl_sockaddr_ex *addr,
1348 curl_socket_t *sockfd)
1349{
Alex Deymoe3149cc2016-10-05 11:18:42 -07001350 struct Curl_easy *data = conn->data;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001351 struct Curl_sockaddr_ex dummy;
1352
1353 if(!addr)
1354 /* if the caller doesn't want info back, use a local temp copy */
1355 addr = &dummy;
1356
1357 /*
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.
1363 */
1364
1365 addr->family = ai->ai_family;
1366 addr->socktype = conn->socktype;
Alex Deymo486467e2017-12-19 19:04:07 +01001367 addr->protocol = conn->socktype == SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001368 addr->addrlen = ai->ai_addrlen;
1369
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);
1373
Elliott Hughescac39802018-04-27 16:19:43 -07001374 if(data->set.fopensocket) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001375 /*
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
1382 * here to connect.
1383 */
Elliott Hughescac39802018-04-27 16:19:43 -07001384 Curl_set_in_callback(data, true);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001385 *sockfd = data->set.fopensocket(data->set.opensocket_client,
1386 CURLSOCKTYPE_IPCXN,
1387 (struct curl_sockaddr *)addr);
Elliott Hughescac39802018-04-27 16:19:43 -07001388 Curl_set_in_callback(data, false);
1389 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001390 else
1391 /* opensocket callback not set, so simply create the socket now */
1392 *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1393
1394 if(*sockfd == CURL_SOCKET_BAD)
1395 /* no socket, no connection */
1396 return CURLE_COULDNT_CONNECT;
1397
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;
1402 }
1403#endif
1404
1405 return CURLE_OK;
1406
1407}
1408
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001409/*
Elliott Hughescee03382017-06-23 12:17:18 -07001410 * Curl_conncontrol() marks streams or connection for closure.
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001411 */
Elliott Hughescee03382017-06-23 12:17:18 -07001412void Curl_conncontrol(struct connectdata *conn,
1413 int ctrl /* see defines in header */
Elliott Hughes82be86d2017-09-20 17:00:17 -07001414#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
Elliott Hughescee03382017-06-23 12:17:18 -07001415 , const char *reason
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001416#endif
Elliott Hughescee03382017-06-23 12:17:18 -07001417 )
1418{
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));
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001428 conn->bits.close = closeit; /* the only place in the source code that
1429 should assign this bit */
1430 }
1431}
Elliott Hughes82be86d2017-09-20 17:00:17 -07001432
1433/* Data received can be cached at various levels, so check them all here. */
1434bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
1435{
1436 int readable;
1437
1438 if(Curl_ssl_data_pending(conn, sockindex) ||
1439 Curl_recv_has_postponed_data(conn, sockindex))
1440 return true;
1441
1442 readable = SOCKET_READABLE(conn->sock[sockindex], 0);
1443 return (readable > 0 && (readable & CURL_CSELECT_IN));
1444}