Imported Upstream version 7.59.0
[platform/upstream/curl.git] / lib / connect.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
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.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22
23 #include "curl_setup.h"
24
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.h> /* <netinet/tcp.h> may need it */
27 #endif
28 #ifdef HAVE_SYS_UN_H
29 #include <sys/un.h> /* for sockaddr_un */
30 #endif
31 #ifdef HAVE_LINUX_TCP_H
32 #include <linux/tcp.h>
33 #elif defined(HAVE_NETINET_TCP_H)
34 #include <netinet/tcp.h>
35 #endif
36 #ifdef HAVE_SYS_IOCTL_H
37 #include <sys/ioctl.h>
38 #endif
39 #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
48
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
61 #include "urldata.h"
62 #include "sendf.h"
63 #include "if2ip.h"
64 #include "strerror.h"
65 #include "connect.h"
66 #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"
72 #include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
73 #include "progress.h"
74 #include "warnless.h"
75 #include "conncache.h"
76 #include "multihandle.h"
77 #include "system_win32.h"
78
79 /* The last 3 #include files should be in this order */
80 #include "curl_printf.h"
81 #include "curl_memory.h"
82 #include "memdebug.h"
83
84 #ifdef __SYMBIAN32__
85 /* This isn't actually supported under Symbian OS */
86 #undef SO_NOSIGPIPE
87 #endif
88
89 static bool verifyconnect(curl_socket_t sockfd, int *error);
90
91 #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
101 struct tcp_keepalive {
102   u_long onoff;
103   u_long keepalivetime;
104   u_long keepaliveinterval;
105 };
106 #endif
107
108 static void
109 tcpkeepalive(struct Curl_easy *data,
110              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
165 static CURLcode
166 singleipconnect(struct connectdata *conn,
167                 const Curl_addrinfo *ai, /* start connecting to this */
168                 curl_socket_t *sock);
169
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  *
175  * The start time is stored in progress.t_startsingle - as set with
176  * Curl_pgrsTime(..., TIMER_STARTSINGLE);
177  *
178  * If 'nowp' is non-NULL, it points to the current time.
179  * 'duringconnect' is FALSE if not during a connect, as then of course the
180  * connect timeout is not taken into account!
181  *
182  * @unittest: 1303
183  */
184 timediff_t Curl_timeleft(struct Curl_easy *data,
185                          struct curltime *nowp,
186                          bool duringconnect)
187 {
188   int timeout_set = 0;
189   timediff_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
190   struct curltime now;
191
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
199   switch(timeout_set) {
200   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) {
223     now = Curl_now();
224     nowp = &now;
225   }
226
227   /* subtract elapsed time */
228   if(duringconnect)
229     /* since this most recent connect started */
230     timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle);
231   else
232     /* since the entire operation started */
233     timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop);
234   if(!timeout_ms)
235     /* avoid returning 0 as that means no timeout! */
236     return -1;
237
238   return timeout_ms;
239 }
240
241 static CURLcode bindlocal(struct connectdata *conn,
242                           curl_socket_t sockfd, int af, unsigned int scope)
243 {
244   struct Curl_easy *data = conn->data;
245
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
254   struct Curl_dns_entry *h = NULL;
255   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;
261
262   /*************************************************************
263    * Select device to bind socket to
264    *************************************************************/
265   if(!dev && !port)
266     /* 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) ) {
272     char myhost[256] = "";
273     int done = 0; /* -1 for error, 1 for address found */
274     bool is_interface = FALSE;
275     bool is_host = FALSE;
276     static const char *if_prefix = "if!";
277     static const char *host_prefix = "host!";
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     }
287
288     /* interface */
289     if(!is_host) {
290 #ifdef SO_BINDTODEVICE
291       /* I am not sure any other OSs than Linux that provide this feature,
292        * and at the least I cannot test. --Ben
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
318       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;
338           break;
339       }
340     }
341     if(!is_interface) {
342       /*
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        */
350       long ipver = conn->ip_version;
351       int rc;
352
353       if(af == AF_INET)
354         conn->ip_version = CURL_IPRESOLVE_V4;
355 #ifdef ENABLE_IPV6
356       else if(af == AF_INET6)
357         conn->ip_version = CURL_IPRESOLVE_V6;
358 #endif
359
360       rc = Curl_resolv(conn, dev, 0, &h);
361       if(rc == CURLRESOLV_PENDING)
362         (void)Curl_resolver_wait_resolv(conn, &h);
363       conn->ip_version = ipver;
364
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
384       /* 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         }
403         sizeof_sa = sizeof(struct sockaddr_in6);
404       }
405       else
406 #endif
407       /* IPv4 address */
408       if((af == AF_INET) &&
409          (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
410         si4->sin_family = AF_INET;
411         si4->sin_port = htons(port);
412         sizeof_sa = sizeof(struct sockaddr_in);
413       }
414     }
415
416     if(done < 1) {
417       /* errorbuf is set false so failf will overwrite any message already in
418          the error buffer, so the user receives this error message instead of a
419          generic resolve error. */
420       data->state.errorbuf = FALSE;
421       failf(data, "Couldn't bind to '%s'", dev);
422       return CURLE_INTERFACE_FAILED;
423     }
424   }
425   else {
426     /* no device was given, prepare sa to match af's needs */
427 #ifdef ENABLE_IPV6
428     if(af == AF_INET6) {
429       si6->sin6_family = AF_INET6;
430       si6->sin6_port = htons(port);
431       sizeof_sa = sizeof(struct sockaddr_in6);
432     }
433     else
434 #endif
435     if(af == AF_INET) {
436       si4->sin_family = AF_INET;
437       si4->sin_port = htons(port);
438       sizeof_sa = sizeof(struct sockaddr_in);
439     }
440   }
441
442   for(;;) {
443     if(bind(sockfd, sock, sizeof_sa) >= 0) {
444       /* we succeeded to bind */
445       struct Curl_sockaddr_storage add;
446       curl_socklen_t size = sizeof(add);
447       memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
448       if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
449         data->state.os_errno = error = SOCKERRNO;
450         failf(data, "getsockname() failed with errno %d: %s",
451               error, Curl_strerror(conn, error));
452         return CURLE_INTERFACE_FAILED;
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  */
484 static 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 */
550 static CURLcode trynextip(struct connectdata *conn,
551                           int sockindex,
552                           int tempindex)
553 {
554   const int other = tempindex ^ 1;
555   CURLcode result = CURLE_COULDNT_CONNECT;
556
557   /* First clean up after the failed socket.
558      Don't close it yet to ensure that the next IP's socket gets a different
559      file descriptor, which can prevent bugs when the curl_multi_socket_action
560      interface is used with certain select() replacements such as kqueue. */
561   curl_socket_t fd_to_close = conn->tempsock[tempindex];
562   conn->tempsock[tempindex] = CURL_SOCKET_BAD;
563
564   if(sockindex == FIRSTSOCKET) {
565     Curl_addrinfo *ai = NULL;
566     int family = AF_UNSPEC;
567
568     if(conn->tempaddr[tempindex]) {
569       /* find next address in the same protocol family */
570       family = conn->tempaddr[tempindex]->ai_family;
571       ai = conn->tempaddr[tempindex]->ai_next;
572     }
573 #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     }
600   }
601
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. */
610 void 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);
614   conn->data->info.conn_scheme = conn->handler->scheme;
615   conn->data->info.conn_protocol = conn->handler->protocol;
616   conn->data->info.conn_primary_port = conn->primary_port;
617   conn->data->info.conn_local_port = conn->local_port;
618 }
619
620 /* retrieves ip address and port from a sockaddr structure.
621    note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
622 bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
623                          long *port)
624 {
625   unsigned short us_port;
626   struct sockaddr_in *si = NULL;
627 #ifdef ENABLE_IPV6
628   struct sockaddr_in6 *si6 = NULL;
629 #endif
630 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
631   struct sockaddr_un *su = NULL;
632 #endif
633
634   switch(sa->sa_family) {
635     case AF_INET:
636       si = (struct sockaddr_in *)(void *) sa;
637       if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
638                         addr, MAX_IPADR_LEN)) {
639         us_port = ntohs(si->sin_port);
640         *port = us_port;
641         return TRUE;
642       }
643       break;
644 #ifdef ENABLE_IPV6
645     case AF_INET6:
646       si6 = (struct sockaddr_in6 *)(void *) sa;
647       if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
648                         addr, MAX_IPADR_LEN)) {
649         us_port = ntohs(si6->sin6_port);
650         *port = us_port;
651         return TRUE;
652       }
653       break;
654 #endif
655 #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);
659       *port = 0;
660       return TRUE;
661 #endif
662     default:
663       break;
664   }
665
666   addr[0] = '\0';
667   *port = 0;
668   errno = EAFNOSUPPORT;
669   return FALSE;
670 }
671
672 /* retrieves the start/end point information of a socket of an established
673    connection */
674 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
675 {
676   curl_socklen_t len;
677   struct Curl_sockaddr_storage ssrem;
678   struct Curl_sockaddr_storage ssloc;
679   struct Curl_easy *data = conn->data;
680
681   if(conn->socktype == SOCK_DGRAM)
682     /* there's no connection! */
683     return;
684
685   if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
686     len = sizeof(struct Curl_sockaddr_storage);
687     if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
688       int error = SOCKERRNO;
689       failf(data, "getpeername() failed with errno %d: %s",
690             error, Curl_strerror(conn, error));
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)) {
697       int error = SOCKERRNO;
698       failf(data, "getsockname() failed with errno %d: %s",
699             error, Curl_strerror(conn, error));
700       return;
701     }
702
703     if(!Curl_getaddressinfo((struct sockaddr*)&ssrem,
704                             conn->primary_ip, &conn->primary_port)) {
705       failf(data, "ssrem inet_ntop() failed with errno %d: %s",
706             errno, Curl_strerror(conn, errno));
707       return;
708     }
709     memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
710
711     if(!Curl_getaddressinfo((struct sockaddr*)&ssloc,
712                             conn->local_ip, &conn->local_port)) {
713       failf(data, "ssloc inet_ntop() failed with errno %d: %s",
714             errno, Curl_strerror(conn, errno));
715       return;
716     }
717
718   }
719
720   /* persist connection info in session handle */
721   Curl_persistconninfo(conn);
722 }
723
724 /*
725  * Curl_is_connected() checks if the socket has connected.
726  */
727
728 CURLcode Curl_is_connected(struct connectdata *conn,
729                            int sockindex,
730                            bool *connected)
731 {
732   struct Curl_easy *data = conn->data;
733   CURLcode result = CURLE_OK;
734   timediff_t allow;
735   int error = 0;
736   struct curltime now;
737   int rc;
738   int i;
739
740   DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
741
742   *connected = FALSE; /* a very negative world view is best */
743
744   if(conn->bits.tcpconnect[sockindex]) {
745     /* we are connected already! */
746     *connected = TRUE;
747     return CURLE_OK;
748   }
749
750   now = Curl_now();
751
752   /* figure out how long time we have left to connect */
753   allow = Curl_timeleft(data, &now, TRUE);
754
755   if(allow < 0) {
756     /* time-out, bail out, go home */
757     failf(data, "Connection time-out");
758     return CURLE_OPERATION_TIMEDOUT;
759   }
760
761   for(i = 0; i<2; i++) {
762     const int other = i ^ 1;
763     if(conn->tempsock[i] == CURL_SOCKET_BAD)
764       continue;
765
766 #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
772
773     /* check socket for connect */
774     rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
775
776     if(rc == 0) { /* no connection yet */
777       error = 0;
778       if(Curl_timediff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
779         infof(data, "After %ldms connect time, move on!\n",
780               conn->timeoutms_per_addr);
781         error = ETIMEDOUT;
782       }
783
784       /* should we try another protocol family? */
785       if(i == 0 && conn->tempaddr[1] == NULL &&
786          (Curl_timediff(now, conn->connecttime) >=
787           data->set.happy_eyeballs_timeout)) {
788         trynextip(conn, sockindex, 1);
789       }
790     }
791     else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
792       if(verifyconnect(conn->tempsock[i], &error)) {
793         /* we are connected with TCP, awesome! */
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;
799 #ifdef ENABLE_IPV6
800         conn->bits.ipv6 = (conn->ip_addr->ai_family == AF_INET6)?TRUE:FALSE;
801 #endif
802
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       }
824       infof(data, "Connection failed\n");
825     }
826     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     }
853   }
854
855   if(result) {
856     /* no more addresses to try */
857
858     const char *hostname;
859
860     /* if the first address family runs out of addresses to try before
861        the happy eyeball timeout, go ahead and try the next family now */
862     if(conn->tempaddr[1] == NULL) {
863       result = trynextip(conn, sockindex, 1);
864       if(!result)
865         return result;
866     }
867
868     if(conn->bits.socksproxy)
869       hostname = conn->socks_proxy.host.name;
870     else if(conn->bits.httpproxy)
871       hostname = conn->http_proxy.host.name;
872     else if(conn->bits.conn_to_host)
873       hostname = conn->conn_to_host.name;
874     else
875       hostname = conn->host.name;
876
877     failf(data, "Failed to connect to %s port %ld: %s",
878         hostname, conn->port, Curl_strerror(conn, error));
879   }
880
881   return result;
882 }
883
884 void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
885 {
886 #if defined(TCP_NODELAY)
887 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
888   struct Curl_easy *data = conn->data;
889 #endif
890   curl_socklen_t onoff = (curl_socklen_t) 1;
891   int level = IPPROTO_TCP;
892
893 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
894   (void) conn;
895 #endif
896
897   if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
898                 sizeof(onoff)) < 0)
899     infof(data, "Could not set TCP_NODELAY: %s\n",
900           Curl_strerror(conn, SOCKERRNO));
901   else
902     infof(data, "TCP_NODELAY set\n");
903 #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? */
914 static void nosigpipe(struct connectdata *conn,
915                       curl_socket_t sockfd)
916 {
917   struct Curl_easy *data = conn->data;
918   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
925 #define nosigpipe(x,y) Curl_nop_stmt
926 #endif
927
928 #ifdef USE_WINSOCK
929 /* When you run a program that uses the Windows Sockets API, you may
930    experience slow performance when you copy data to a TCP server.
931
932    https://support.microsoft.com/kb/823764
933
934    Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
935    Buffer Size
936
937    The problem described in this knowledge-base is applied only to pre-Vista
938    Windows.  Following function trying to detect OS version and skips
939    SO_SNDBUF adjustment for Windows Vista and above.
940 */
941 #define DETECT_OS_NONE 0
942 #define DETECT_OS_PREVISTA 1
943 #define DETECT_OS_VISTA_OR_LATER 2
944
945 void 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
951   static int detectOsState = DETECT_OS_NONE;
952
953   if(detectOsState == DETECT_OS_NONE) {
954     if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
955                                    VERSION_GREATER_THAN_EQUAL))
956       detectOsState = DETECT_OS_VISTA_OR_LATER;
957     else
958       detectOsState = DETECT_OS_PREVISTA;
959   }
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)
966       return;
967
968   setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
969 }
970 #endif
971
972 /*
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
979  * having connected.
980  */
981 static CURLcode singleipconnect(struct connectdata *conn,
982                                 const Curl_addrinfo *ai,
983                                 curl_socket_t *sockp)
984 {
985   struct Curl_sockaddr_ex addr;
986   int rc = -1;
987   int error = 0;
988   bool isconnected = FALSE;
989   struct Curl_easy *data = conn->data;
990   curl_socket_t sockfd;
991   CURLcode result;
992   char ipaddress[MAX_IPADR_LEN];
993   long port;
994   bool is_tcp;
995 #ifdef TCP_FASTOPEN_CONNECT
996   int optval = 1;
997 #endif
998
999   *sockp = CURL_SOCKET_BAD;
1000
1001   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. */
1006     return CURLE_OK;
1007
1008   /* store remote address and port used in this connection attempt */
1009   if(!Curl_getaddressinfo((struct sockaddr*)&addr.sa_addr,
1010                           ipaddress, &port)) {
1011     /* malformed address or bug in inet_ntop, try next address */
1012     failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
1013           errno, Curl_strerror(conn, errno));
1014     Curl_closesocket(conn, sockfd);
1015     return CURLE_OK;
1016   }
1017   infof(data, "  Trying %s...\n", ipaddress);
1018
1019 #ifdef ENABLE_IPV6
1020   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;
1024 #endif
1025   if(is_tcp && data->set.tcp_nodelay)
1026     Curl_tcpnodelay(conn, sockfd);
1027
1028   nosigpipe(conn, sockfd);
1029
1030   Curl_sndbufset(sockfd);
1031
1032   if(is_tcp && data->set.tcp_keepalive)
1033     tcpkeepalive(data, sockfd);
1034
1035   if(data->set.fsockopt) {
1036     /* activate callback for setting socket options */
1037     Curl_set_in_callback(data, true);
1038     error = data->set.fsockopt(data->set.sockopt_client,
1039                                sockfd,
1040                                CURLSOCKTYPE_IPCXN);
1041     Curl_set_in_callback(data, false);
1042
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;
1048     }
1049   }
1050
1051   /* possibly bind the local end to an IP, interface or port */
1052   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     }
1068   }
1069
1070   /* set socket non-blocking */
1071   (void)curlx_nonblock(sockfd, TRUE);
1072
1073   conn->connecttime = Curl_now();
1074   if(conn->num_addr > 1)
1075     Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME);
1076
1077   /* Connect TCP sockets, bind UDP */
1078   if(!isconnected && (conn->socktype == SOCK_STREAM)) {
1079     if(conn->bits.tcp_fastopen) {
1080 #if defined(CONNECT_DATA_IDEMPOTENT) /* Darwin */
1081 #  if defined(HAVE_BUILTIN_AVAILABLE)
1082       /* while connectx function is available since macOS 10.11 / iOS 9,
1083          it did not have the interface declared correctly until
1084          Xcode 9 / macOS SDK 10.13 */
1085       if(__builtin_available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)) {
1086         sa_endpoints_t endpoints;
1087         endpoints.sae_srcif = 0;
1088         endpoints.sae_srcaddr = NULL;
1089         endpoints.sae_srcaddrlen = 0;
1090         endpoints.sae_dstaddr = &addr.sa_addr;
1091         endpoints.sae_dstaddrlen = addr.addrlen;
1092
1093         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 */
1112       if(conn->given->flags & PROTOPT_SSL)
1113         rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1114       else
1115         rc = 0; /* Do nothing */
1116 #endif
1117     }
1118     else {
1119       rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1120     }
1121
1122     if(-1 == rc)
1123       error = SOCKERRNO;
1124   }
1125   else {
1126     *sockp = sockfd;
1127     return CURLE_OK;
1128   }
1129
1130   if(-1 == rc) {
1131     switch(error) {
1132     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
1143       result = CURLE_OK;
1144       break;
1145
1146     default:
1147       /* unknown error, fallthrough and try another address! */
1148       infof(data, "Immediate connect fail for %s: %s\n",
1149             ipaddress, Curl_strerror(conn, error));
1150       data->state.os_errno = error;
1151
1152       /* connect failed */
1153       Curl_closesocket(conn, sockfd);
1154       result = CURLE_COULDNT_CONNECT;
1155     }
1156   }
1157
1158   if(!result)
1159     *sockp = sockfd;
1160
1161   return result;
1162 }
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
1170 CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
1171                           const struct Curl_dns_entry *remotehost)
1172 {
1173   struct Curl_easy *data = conn->data;
1174   struct curltime before = Curl_now();
1175   CURLcode result = CURLE_COULDNT_CONNECT;
1176
1177   timediff_t timeout_ms = Curl_timeleft(data, &before, TRUE);
1178
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   }
1184
1185   conn->num_addr = Curl_num_addresses(remotehost->addr);
1186   conn->tempaddr[0] = remotehost->addr;
1187   conn->tempaddr[1] = NULL;
1188   conn->tempsock[0] = CURL_SOCKET_BAD;
1189   conn->tempsock[1] = CURL_SOCKET_BAD;
1190
1191   /* Max time for the next connection attempt */
1192   conn->timeoutms_per_addr =
1193     conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
1194
1195   /* start connecting to first IP */
1196   while(conn->tempaddr[0]) {
1197     result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1198     if(!result)
1199       break;
1200     conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
1201   }
1202
1203   if(conn->tempsock[0] == CURL_SOCKET_BAD) {
1204     if(!result)
1205       result = CURLE_COULDNT_CONNECT;
1206     return result;
1207   }
1208
1209   data->info.numconnects++; /* to track the number of connections made */
1210   Curl_expire(conn->data, data->set.happy_eyeballs_timeout,
1211               EXPIRE_HAPPY_EYEBALLS);
1212
1213   return CURLE_OK;
1214 }
1215
1216 struct connfind {
1217   struct connectdata *tofind;
1218   bool found;
1219 };
1220
1221 static 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
1231 /*
1232  * Used to extract socket and connectdata struct for the most recent
1233  * transfer on the given Curl_easy.
1234  *
1235  * The returned socket will be CURL_SOCKET_BAD in case of failure!
1236  */
1237 curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
1238                                   struct connectdata **connp)
1239 {
1240   curl_socket_t sockfd;
1241
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
1255     Curl_conncache_foreach(data, data->multi_easy?
1256                            &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
1264     if(connp)
1265       /* only store this if the caller cares for it */
1266       *connp = c;
1267     sockfd = c->sock[FIRSTSOCKET];
1268   }
1269   else
1270     return CURL_SOCKET_BAD;
1271
1272   return sockfd;
1273 }
1274
1275 /*
1276  * Check if a connection seems to be alive.
1277  */
1278 bool 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 /*
1303  * Close a socket.
1304  *
1305  * 'conn' can be NULL, beware!
1306  */
1307 int 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 {
1318       int rc;
1319       Curl_multi_closed(conn, sock);
1320       Curl_set_in_callback(conn->data, true);
1321       rc = conn->fclosesocket(conn->closesocket_client, sock);
1322       Curl_set_in_callback(conn->data, false);
1323       return rc;
1324     }
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  */
1345 CURLcode Curl_socket(struct connectdata *conn,
1346                      const Curl_addrinfo *ai,
1347                      struct Curl_sockaddr_ex *addr,
1348                      curl_socket_t *sockfd)
1349 {
1350   struct Curl_easy *data = conn->data;
1351   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;
1367   addr->protocol = conn->socktype == SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1368   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
1374   if(data->set.fopensocket) {
1375    /*
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     */
1384     Curl_set_in_callback(data, true);
1385     *sockfd = data->set.fopensocket(data->set.opensocket_client,
1386                                     CURLSOCKTYPE_IPCXN,
1387                                     (struct curl_sockaddr *)addr);
1388     Curl_set_in_callback(data, false);
1389   }
1390   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
1409 /*
1410  * Curl_conncontrol() marks streams or connection for closure.
1411  */
1412 void Curl_conncontrol(struct connectdata *conn,
1413                       int ctrl /* see defines in header */
1414 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
1415                       , const char *reason
1416 #endif
1417   )
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));
1428     conn->bits.close = closeit; /* the only place in the source code that
1429                                    should assign this bit */
1430   }
1431 }
1432
1433 /* Data received can be cached at various levels, so check them all here. */
1434 bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
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 }