3225d70cf864354c927ac273b21ca4da6b62c76f
[platform/upstream/curl.git] / lib / connect.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2016, 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_NETINET_TCP_H
32 #include <netinet/tcp.h> /* for TCP_NODELAY */
33 #endif
34 #ifdef HAVE_SYS_IOCTL_H
35 #include <sys/ioctl.h>
36 #endif
37 #ifdef HAVE_NETDB_H
38 #include <netdb.h>
39 #endif
40 #ifdef HAVE_FCNTL_H
41 #include <fcntl.h>
42 #endif
43 #ifdef HAVE_ARPA_INET_H
44 #include <arpa/inet.h>
45 #endif
46
47 #if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
48 #include <sys/filio.h>
49 #endif
50 #ifdef NETWARE
51 #undef in_addr_t
52 #define in_addr_t unsigned long
53 #endif
54 #ifdef __VMS
55 #include <in.h>
56 #include <inet.h>
57 #endif
58
59 #include "urldata.h"
60 #include "sendf.h"
61 #include "if2ip.h"
62 #include "strerror.h"
63 #include "connect.h"
64 #include "select.h"
65 #include "url.h" /* for Curl_safefree() */
66 #include "multiif.h"
67 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
68 #include "inet_ntop.h"
69 #include "inet_pton.h"
70 #include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
71 #include "progress.h"
72 #include "warnless.h"
73 #include "conncache.h"
74 #include "multihandle.h"
75 #include "system_win32.h"
76
77 /* The last 3 #include files should be in this order */
78 #include "curl_printf.h"
79 #include "curl_memory.h"
80 #include "memdebug.h"
81
82 #ifdef __SYMBIAN32__
83 /* This isn't actually supported under Symbian OS */
84 #undef SO_NOSIGPIPE
85 #endif
86
87 static bool verifyconnect(curl_socket_t sockfd, int *error);
88
89 #if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
90 /* DragonFlyBSD and Windows use millisecond units */
91 #define KEEPALIVE_FACTOR(x) (x *= 1000)
92 #else
93 #define KEEPALIVE_FACTOR(x)
94 #endif
95
96 #if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
97 #define SIO_KEEPALIVE_VALS    _WSAIOW(IOC_VENDOR,4)
98
99 struct tcp_keepalive {
100   u_long onoff;
101   u_long keepalivetime;
102   u_long keepaliveinterval;
103 };
104 #endif
105
106 static void
107 tcpkeepalive(struct Curl_easy *data,
108              curl_socket_t sockfd)
109 {
110   int optval = data->set.tcp_keepalive?1:0;
111
112   /* only set IDLE and INTVL if setting KEEPALIVE is successful */
113   if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
114         (void *)&optval, sizeof(optval)) < 0) {
115     infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd);
116   }
117   else {
118 #if defined(SIO_KEEPALIVE_VALS)
119     struct tcp_keepalive vals;
120     DWORD dummy;
121     vals.onoff = 1;
122     optval = curlx_sltosi(data->set.tcp_keepidle);
123     KEEPALIVE_FACTOR(optval);
124     vals.keepalivetime = optval;
125     optval = curlx_sltosi(data->set.tcp_keepintvl);
126     KEEPALIVE_FACTOR(optval);
127     vals.keepaliveinterval = optval;
128     if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
129                 NULL, 0, &dummy, NULL, NULL) != 0) {
130       infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
131             (int)sockfd, WSAGetLastError());
132     }
133 #elif defined(CURL_WINDOWS_APP)
134     (void)majorVersion;
135     detectOsState = DETECT_OS_VISTA_OR_LATER;
136 #else
137 #ifdef TCP_KEEPIDLE
138     optval = curlx_sltosi(data->set.tcp_keepidle);
139     KEEPALIVE_FACTOR(optval);
140     if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
141           (void *)&optval, sizeof(optval)) < 0) {
142       infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd);
143     }
144 #endif
145 #ifdef TCP_KEEPINTVL
146     optval = curlx_sltosi(data->set.tcp_keepintvl);
147     KEEPALIVE_FACTOR(optval);
148     if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
149           (void *)&optval, sizeof(optval)) < 0) {
150       infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd);
151     }
152 #endif
153 #ifdef TCP_KEEPALIVE
154     /* Mac OS X style */
155     optval = curlx_sltosi(data->set.tcp_keepidle);
156     KEEPALIVE_FACTOR(optval);
157     if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
158           (void *)&optval, sizeof(optval)) < 0) {
159       infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd);
160     }
161 #endif
162 #endif
163   }
164 }
165
166 static CURLcode
167 singleipconnect(struct connectdata *conn,
168                 const Curl_addrinfo *ai, /* start connecting to this */
169                 curl_socket_t *sock);
170
171 /*
172  * Curl_timeleft() returns the amount of milliseconds left allowed for the
173  * transfer/connection. If the value is negative, the timeout time has already
174  * elapsed.
175  *
176  * The start time is stored in progress.t_startsingle - as set with
177  * Curl_pgrsTime(..., TIMER_STARTSINGLE);
178  *
179  * If 'nowp' is non-NULL, it points to the current time.
180  * 'duringconnect' is FALSE if not during a connect, as then of course the
181  * connect timeout is not taken into account!
182  *
183  * @unittest: 1303
184  */
185 long Curl_timeleft(struct Curl_easy *data,
186                    struct timeval *nowp,
187                    bool duringconnect)
188 {
189   int timeout_set = 0;
190   long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
191   struct timeval now;
192
193   /* if a timeout is set, use the most restrictive one */
194
195   if(data->set.timeout > 0)
196     timeout_set |= 1;
197   if(duringconnect && (data->set.connecttimeout > 0))
198     timeout_set |= 2;
199
200   switch (timeout_set) {
201   case 1:
202     timeout_ms = data->set.timeout;
203     break;
204   case 2:
205     timeout_ms = data->set.connecttimeout;
206     break;
207   case 3:
208     if(data->set.timeout < data->set.connecttimeout)
209       timeout_ms = data->set.timeout;
210     else
211       timeout_ms = data->set.connecttimeout;
212     break;
213   default:
214     /* use the default */
215     if(!duringconnect)
216       /* if we're not during connect, there's no default timeout so if we're
217          at zero we better just return zero and not make it a negative number
218          by the math below */
219       return 0;
220     break;
221   }
222
223   if(!nowp) {
224     now = Curl_tvnow();
225     nowp = &now;
226   }
227
228   /* subtract elapsed time */
229   if(duringconnect)
230     /* since this most recent connect started */
231     timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
232   else
233     /* since the entire operation started */
234     timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop);
235   if(!timeout_ms)
236     /* avoid returning 0 as that means no timeout! */
237     return -1;
238
239   return timeout_ms;
240 }
241
242 static CURLcode bindlocal(struct connectdata *conn,
243                           curl_socket_t sockfd, int af, unsigned int scope)
244 {
245   struct Curl_easy *data = conn->data;
246
247   struct Curl_sockaddr_storage sa;
248   struct sockaddr *sock = (struct sockaddr *)&sa;  /* bind to this address */
249   curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
250   struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
251 #ifdef ENABLE_IPV6
252   struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
253 #endif
254
255   struct Curl_dns_entry *h=NULL;
256   unsigned short port = data->set.localport; /* use this port number, 0 for
257                                                 "random" */
258   /* how many port numbers to try to bind to, increasing one at a time */
259   int portnum = data->set.localportrange;
260   const char *dev = data->set.str[STRING_DEVICE];
261   int error;
262
263   /*************************************************************
264    * Select device to bind socket to
265    *************************************************************/
266   if(!dev && !port)
267     /* no local kind of binding was requested */
268     return CURLE_OK;
269
270   memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
271
272   if(dev && (strlen(dev)<255) ) {
273     char myhost[256] = "";
274     int done = 0; /* -1 for error, 1 for address found */
275     bool is_interface = FALSE;
276     bool is_host = FALSE;
277     static const char *if_prefix = "if!";
278     static const char *host_prefix = "host!";
279
280     if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
281       dev += strlen(if_prefix);
282       is_interface = TRUE;
283     }
284     else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
285       dev += strlen(host_prefix);
286       is_host = TRUE;
287     }
288
289     /* interface */
290     if(!is_host) {
291       switch(Curl_if2ip(af, scope, conn->scope_id, dev,
292                         myhost, sizeof(myhost))) {
293         case IF2IP_NOT_FOUND:
294           if(is_interface) {
295             /* Do not fall back to treating it as a host name */
296             failf(data, "Couldn't bind to interface '%s'", dev);
297             return CURLE_INTERFACE_FAILED;
298           }
299           break;
300         case IF2IP_AF_NOT_SUPPORTED:
301           /* Signal the caller to try another address family if available */
302           return CURLE_UNSUPPORTED_PROTOCOL;
303         case IF2IP_FOUND:
304           is_interface = TRUE;
305           /*
306            * We now have the numerical IP address in the 'myhost' buffer
307            */
308           infof(data, "Local Interface %s is ip %s using address family %i\n",
309                 dev, myhost, af);
310           done = 1;
311
312 #ifdef SO_BINDTODEVICE
313           /* I am not sure any other OSs than Linux that provide this feature,
314            * and at the least I cannot test. --Ben
315            *
316            * This feature allows one to tightly bind the local socket to a
317            * particular interface.  This will force even requests to other
318            * local interfaces to go out the external interface.
319            *
320            *
321            * Only bind to the interface when specified as interface, not just
322            * as a hostname or ip address.
323            */
324           if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
325                         dev, (curl_socklen_t)strlen(dev)+1) != 0) {
326             error = SOCKERRNO;
327             infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
328                   " will do regular bind\n",
329                   dev, error, Curl_strerror(conn, error));
330             /* This is typically "errno 1, error: Operation not permitted" if
331                you're not running as root or another suitable privileged
332                user */
333           }
334 #endif
335           break;
336       }
337     }
338     if(!is_interface) {
339       /*
340        * This was not an interface, resolve the name as a host name
341        * or IP number
342        *
343        * Temporarily force name resolution to use only the address type
344        * of the connection. The resolve functions should really be changed
345        * to take a type parameter instead.
346        */
347       long ipver = conn->ip_version;
348       int rc;
349
350       if(af == AF_INET)
351         conn->ip_version = CURL_IPRESOLVE_V4;
352 #ifdef ENABLE_IPV6
353       else if(af == AF_INET6)
354         conn->ip_version = CURL_IPRESOLVE_V6;
355 #endif
356
357       rc = Curl_resolv(conn, dev, 0, &h);
358       if(rc == CURLRESOLV_PENDING)
359         (void)Curl_resolver_wait_resolv(conn, &h);
360       conn->ip_version = ipver;
361
362       if(h) {
363         /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
364         Curl_printable_address(h->addr, myhost, sizeof(myhost));
365         infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
366               dev, af, myhost, h->addr->ai_family);
367         Curl_resolv_unlock(data, h);
368         done = 1;
369       }
370       else {
371         /*
372          * provided dev was no interface (or interfaces are not supported
373          * e.g. solaris) no ip address and no domain we fail here
374          */
375         done = -1;
376       }
377     }
378
379     if(done > 0) {
380 #ifdef ENABLE_IPV6
381       /* IPv6 address */
382       if(af == AF_INET6) {
383 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
384         char *scope_ptr = strchr(myhost, '%');
385         if(scope_ptr)
386           *(scope_ptr++) = 0;
387 #endif
388         if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
389           si6->sin6_family = AF_INET6;
390           si6->sin6_port = htons(port);
391 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
392           if(scope_ptr)
393             /* The "myhost" string either comes from Curl_if2ip or from
394                Curl_printable_address. The latter returns only numeric scope
395                IDs and the former returns none at all.  So the scope ID, if
396                present, is known to be numeric */
397             si6->sin6_scope_id = atoi(scope_ptr);
398 #endif
399         }
400         sizeof_sa = sizeof(struct sockaddr_in6);
401       }
402       else
403 #endif
404       /* IPv4 address */
405       if((af == AF_INET) &&
406          (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
407         si4->sin_family = AF_INET;
408         si4->sin_port = htons(port);
409         sizeof_sa = sizeof(struct sockaddr_in);
410       }
411     }
412
413     if(done < 1) {
414       failf(data, "Couldn't bind to '%s'", dev);
415       return CURLE_INTERFACE_FAILED;
416     }
417   }
418   else {
419     /* no device was given, prepare sa to match af's needs */
420 #ifdef ENABLE_IPV6
421     if(af == AF_INET6) {
422       si6->sin6_family = AF_INET6;
423       si6->sin6_port = htons(port);
424       sizeof_sa = sizeof(struct sockaddr_in6);
425     }
426     else
427 #endif
428     if(af == AF_INET) {
429       si4->sin_family = AF_INET;
430       si4->sin_port = htons(port);
431       sizeof_sa = sizeof(struct sockaddr_in);
432     }
433   }
434
435   for(;;) {
436     if(bind(sockfd, sock, sizeof_sa) >= 0) {
437       /* we succeeded to bind */
438       struct Curl_sockaddr_storage add;
439       curl_socklen_t size = sizeof(add);
440       memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
441       if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
442         data->state.os_errno = error = SOCKERRNO;
443         failf(data, "getsockname() failed with errno %d: %s",
444               error, Curl_strerror(conn, error));
445         return CURLE_INTERFACE_FAILED;
446       }
447       infof(data, "Local port: %hu\n", port);
448       conn->bits.bound = TRUE;
449       return CURLE_OK;
450     }
451
452     if(--portnum > 0) {
453       infof(data, "Bind to local port %hu failed, trying next\n", port);
454       port++; /* try next port */
455       /* We re-use/clobber the port variable here below */
456       if(sock->sa_family == AF_INET)
457         si4->sin_port = ntohs(port);
458 #ifdef ENABLE_IPV6
459       else
460         si6->sin6_port = ntohs(port);
461 #endif
462     }
463     else
464       break;
465   }
466
467   data->state.os_errno = error = SOCKERRNO;
468   failf(data, "bind failed with errno %d: %s",
469         error, Curl_strerror(conn, error));
470
471   return CURLE_INTERFACE_FAILED;
472 }
473
474 /*
475  * verifyconnect() returns TRUE if the connect really has happened.
476  */
477 static bool verifyconnect(curl_socket_t sockfd, int *error)
478 {
479   bool rc = TRUE;
480 #ifdef SO_ERROR
481   int err = 0;
482   curl_socklen_t errSize = sizeof(err);
483
484 #ifdef WIN32
485   /*
486    * In October 2003 we effectively nullified this function on Windows due to
487    * problems with it using all CPU in multi-threaded cases.
488    *
489    * In May 2004, we bring it back to offer more info back on connect failures.
490    * Gisle Vanem could reproduce the former problems with this function, but
491    * could avoid them by adding this SleepEx() call below:
492    *
493    *    "I don't have Rational Quantify, but the hint from his post was
494    *    ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
495    *    just Sleep(0) would be enough?) would release whatever
496    *    mutex/critical-section the ntdll call is waiting on.
497    *
498    *    Someone got to verify this on Win-NT 4.0, 2000."
499    */
500
501 #ifdef _WIN32_WCE
502   Sleep(0);
503 #else
504   SleepEx(0, FALSE);
505 #endif
506
507 #endif
508
509   if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
510     err = SOCKERRNO;
511 #ifdef _WIN32_WCE
512   /* Old WinCE versions don't support SO_ERROR */
513   if(WSAENOPROTOOPT == err) {
514     SET_SOCKERRNO(0);
515     err = 0;
516   }
517 #endif
518 #ifdef __minix
519   /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
520   if(EBADIOCTL == err) {
521     SET_SOCKERRNO(0);
522     err = 0;
523   }
524 #endif
525   if((0 == err) || (EISCONN == err))
526     /* we are connected, awesome! */
527     rc = TRUE;
528   else
529     /* This wasn't a successful connect */
530     rc = FALSE;
531   if(error)
532     *error = err;
533 #else
534   (void)sockfd;
535   if(error)
536     *error = SOCKERRNO;
537 #endif
538   return rc;
539 }
540
541 /* Used within the multi interface. Try next IP address, return TRUE if no
542    more address exists or error */
543 static CURLcode trynextip(struct connectdata *conn,
544                           int sockindex,
545                           int tempindex)
546 {
547   const int other = tempindex ^ 1;
548   CURLcode result = CURLE_COULDNT_CONNECT;
549
550   /* First clean up after the failed socket.
551      Don't close it yet to ensure that the next IP's socket gets a different
552      file descriptor, which can prevent bugs when the curl_multi_socket_action
553      interface is used with certain select() replacements such as kqueue. */
554   curl_socket_t fd_to_close = conn->tempsock[tempindex];
555   conn->tempsock[tempindex] = CURL_SOCKET_BAD;
556
557   if(sockindex == FIRSTSOCKET) {
558     Curl_addrinfo *ai = NULL;
559     int family = AF_UNSPEC;
560
561     if(conn->tempaddr[tempindex]) {
562       /* find next address in the same protocol family */
563       family = conn->tempaddr[tempindex]->ai_family;
564       ai = conn->tempaddr[tempindex]->ai_next;
565     }
566 #ifdef ENABLE_IPV6
567     else if(conn->tempaddr[0]) {
568       /* happy eyeballs - try the other protocol family */
569       int firstfamily = conn->tempaddr[0]->ai_family;
570       family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
571       ai = conn->tempaddr[0]->ai_next;
572     }
573 #endif
574
575     while(ai) {
576       if(conn->tempaddr[other]) {
577         /* we can safely skip addresses of the other protocol family */
578         while(ai && ai->ai_family != family)
579           ai = ai->ai_next;
580       }
581
582       if(ai) {
583         result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
584         if(result == CURLE_COULDNT_CONNECT) {
585           ai = ai->ai_next;
586           continue;
587         }
588
589         conn->tempaddr[tempindex] = ai;
590       }
591       break;
592     }
593   }
594
595   if(fd_to_close != CURL_SOCKET_BAD)
596     Curl_closesocket(conn, fd_to_close);
597
598   return result;
599 }
600
601 /* Copies connection info into the session handle to make it available
602    when the session handle is no longer associated with a connection. */
603 void Curl_persistconninfo(struct connectdata *conn)
604 {
605   memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
606   memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
607   conn->data->info.conn_primary_port = conn->primary_port;
608   conn->data->info.conn_local_port = conn->local_port;
609 }
610
611 /* retrieves ip address and port from a sockaddr structure */
612 static bool getaddressinfo(struct sockaddr* sa, char* addr,
613                            long* port)
614 {
615   unsigned short us_port;
616   struct sockaddr_in* si = NULL;
617 #ifdef ENABLE_IPV6
618   struct sockaddr_in6* si6 = NULL;
619 #endif
620 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
621   struct sockaddr_un* su = NULL;
622 #endif
623
624   switch (sa->sa_family) {
625     case AF_INET:
626       si = (struct sockaddr_in*)(void*) sa;
627       if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
628                         addr, MAX_IPADR_LEN)) {
629         us_port = ntohs(si->sin_port);
630         *port = us_port;
631         return TRUE;
632       }
633       break;
634 #ifdef ENABLE_IPV6
635     case AF_INET6:
636       si6 = (struct sockaddr_in6*)(void*) sa;
637       if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
638                         addr, MAX_IPADR_LEN)) {
639         us_port = ntohs(si6->sin6_port);
640         *port = us_port;
641         return TRUE;
642       }
643       break;
644 #endif
645 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
646     case AF_UNIX:
647       su = (struct sockaddr_un*)sa;
648       snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
649       *port = 0;
650       return TRUE;
651 #endif
652     default:
653       break;
654   }
655
656   addr[0] = '\0';
657   *port = 0;
658
659   return FALSE;
660 }
661
662 /* retrieves the start/end point information of a socket of an established
663    connection */
664 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
665 {
666   curl_socklen_t len;
667   struct Curl_sockaddr_storage ssrem;
668   struct Curl_sockaddr_storage ssloc;
669   struct Curl_easy *data = conn->data;
670
671   if(conn->socktype == SOCK_DGRAM)
672     /* there's no connection! */
673     return;
674
675   if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
676     int error;
677
678     len = sizeof(struct Curl_sockaddr_storage);
679     if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
680       error = SOCKERRNO;
681       failf(data, "getpeername() failed with errno %d: %s",
682             error, Curl_strerror(conn, error));
683       return;
684     }
685
686     len = sizeof(struct Curl_sockaddr_storage);
687     memset(&ssloc, 0, sizeof(ssloc));
688     if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
689       error = SOCKERRNO;
690       failf(data, "getsockname() failed with errno %d: %s",
691             error, Curl_strerror(conn, error));
692       return;
693     }
694
695     if(!getaddressinfo((struct sockaddr*)&ssrem,
696                         conn->primary_ip, &conn->primary_port)) {
697       error = ERRNO;
698       failf(data, "ssrem inet_ntop() failed with errno %d: %s",
699             error, Curl_strerror(conn, error));
700       return;
701     }
702     memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
703
704     if(!getaddressinfo((struct sockaddr*)&ssloc,
705                        conn->local_ip, &conn->local_port)) {
706       error = ERRNO;
707       failf(data, "ssloc inet_ntop() failed with errno %d: %s",
708             error, Curl_strerror(conn, error));
709       return;
710     }
711
712   }
713
714   /* persist connection info in session handle */
715   Curl_persistconninfo(conn);
716 }
717
718 /*
719  * Curl_is_connected() checks if the socket has connected.
720  */
721
722 CURLcode Curl_is_connected(struct connectdata *conn,
723                            int sockindex,
724                            bool *connected)
725 {
726   struct Curl_easy *data = conn->data;
727   CURLcode result = CURLE_OK;
728   long allow;
729   int error = 0;
730   struct timeval now;
731   int rc;
732   int i;
733
734   DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
735
736   *connected = FALSE; /* a very negative world view is best */
737
738   if(conn->bits.tcpconnect[sockindex]) {
739     /* we are connected already! */
740     *connected = TRUE;
741     return CURLE_OK;
742   }
743
744   now = Curl_tvnow();
745
746   /* figure out how long time we have left to connect */
747   allow = Curl_timeleft(data, &now, TRUE);
748
749   if(allow < 0) {
750     /* time-out, bail out, go home */
751     failf(data, "Connection time-out");
752     return CURLE_OPERATION_TIMEDOUT;
753   }
754
755   for(i=0; i<2; i++) {
756     const int other = i ^ 1;
757     if(conn->tempsock[i] == CURL_SOCKET_BAD)
758       continue;
759
760 #ifdef mpeix
761     /* Call this function once now, and ignore the results. We do this to
762        "clear" the error state on the socket so that we can later read it
763        reliably. This is reported necessary on the MPE/iX operating system. */
764     (void)verifyconnect(conn->tempsock[i], NULL);
765 #endif
766
767     /* check socket for connect */
768     rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
769
770     if(rc == 0) { /* no connection yet */
771       error = 0;
772       if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
773         infof(data, "After %ldms connect time, move on!\n",
774               conn->timeoutms_per_addr);
775         error = ETIMEDOUT;
776       }
777
778       /* should we try another protocol family? */
779       if(i == 0 && conn->tempaddr[1] == NULL &&
780          curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
781         trynextip(conn, sockindex, 1);
782       }
783     }
784     else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
785       if(verifyconnect(conn->tempsock[i], &error)) {
786         /* we are connected with TCP, awesome! */
787
788         /* use this socket from now on */
789         conn->sock[sockindex] = conn->tempsock[i];
790         conn->ip_addr = conn->tempaddr[i];
791         conn->tempsock[i] = CURL_SOCKET_BAD;
792
793         /* close the other socket, if open */
794         if(conn->tempsock[other] != CURL_SOCKET_BAD) {
795           Curl_closesocket(conn, conn->tempsock[other]);
796           conn->tempsock[other] = CURL_SOCKET_BAD;
797         }
798
799         /* see if we need to do any proxy magic first once we connected */
800         result = Curl_connected_proxy(conn, sockindex);
801         if(result)
802           return result;
803
804         conn->bits.tcpconnect[sockindex] = TRUE;
805
806         *connected = TRUE;
807         if(sockindex == FIRSTSOCKET)
808           Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
809         Curl_updateconninfo(conn, conn->sock[sockindex]);
810         Curl_verboseconnect(conn);
811
812         return CURLE_OK;
813       }
814       else
815         infof(data, "Connection failed\n");
816     }
817     else if(rc & CURL_CSELECT_ERR)
818       (void)verifyconnect(conn->tempsock[i], &error);
819
820     /*
821      * The connection failed here, we should attempt to connect to the "next
822      * address" for the given host. But first remember the latest error.
823      */
824     if(error) {
825       data->state.os_errno = error;
826       SET_SOCKERRNO(error);
827       if(conn->tempaddr[i]) {
828         CURLcode status;
829         char ipaddress[MAX_IPADR_LEN];
830         Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
831         infof(data, "connect to %s port %ld failed: %s\n",
832               ipaddress, conn->port, Curl_strerror(conn, error));
833
834         conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
835                                    allow : allow / 2;
836
837         status = trynextip(conn, sockindex, i);
838         if(status != CURLE_COULDNT_CONNECT
839             || conn->tempsock[other] == CURL_SOCKET_BAD)
840           /* the last attempt failed and no other sockets remain open */
841           result = status;
842       }
843     }
844   }
845
846   if(result) {
847     /* no more addresses to try */
848
849     const char* hostname;
850
851     /* if the first address family runs out of addresses to try before
852        the happy eyeball timeout, go ahead and try the next family now */
853     if(conn->tempaddr[1] == NULL) {
854       result = trynextip(conn, sockindex, 1);
855       if(!result)
856         return result;
857     }
858
859     if(conn->bits.proxy)
860       hostname = conn->proxy.name;
861     else if(conn->bits.conn_to_host)
862       hostname = conn->conn_to_host.name;
863     else
864       hostname = conn->host.name;
865
866     failf(data, "Failed to connect to %s port %ld: %s",
867         hostname, conn->port, Curl_strerror(conn, error));
868   }
869
870   return result;
871 }
872
873 void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
874 {
875 #if defined(TCP_NODELAY)
876 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
877   struct Curl_easy *data = conn->data;
878 #endif
879   curl_socklen_t onoff = (curl_socklen_t) 1;
880   int level = IPPROTO_TCP;
881
882 #if 0
883   /* The use of getprotobyname() is disabled since it isn't thread-safe on
884      numerous systems. On these getprotobyname_r() should be used instead, but
885      that exists in at least one 4 arg version and one 5 arg version, and
886      since the proto number rarely changes anyway we now just use the hard
887      coded number. The "proper" fix would need a configure check for the
888      correct function much in the same style the gethostbyname_r versions are
889      detected. */
890   struct protoent *pe = getprotobyname("tcp");
891   if(pe)
892     level = pe->p_proto;
893 #endif
894
895 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
896   (void) conn;
897 #endif
898
899   if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
900                 sizeof(onoff)) < 0)
901     infof(data, "Could not set TCP_NODELAY: %s\n",
902           Curl_strerror(conn, SOCKERRNO));
903   else
904     infof(data, "TCP_NODELAY set\n");
905 #else
906   (void)conn;
907   (void)sockfd;
908 #endif
909 }
910
911 #ifdef SO_NOSIGPIPE
912 /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
913    sending data to a dead peer (instead of relying on the 4th argument to send
914    being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
915    systems? */
916 static void nosigpipe(struct connectdata *conn,
917                       curl_socket_t sockfd)
918 {
919   struct Curl_easy *data= conn->data;
920   int onoff = 1;
921   if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
922                 sizeof(onoff)) < 0)
923     infof(data, "Could not set SO_NOSIGPIPE: %s\n",
924           Curl_strerror(conn, SOCKERRNO));
925 }
926 #else
927 #define nosigpipe(x,y) Curl_nop_stmt
928 #endif
929
930 #ifdef USE_WINSOCK
931 /* When you run a program that uses the Windows Sockets API, you may
932    experience slow performance when you copy data to a TCP server.
933
934    https://support.microsoft.com/kb/823764
935
936    Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
937    Buffer Size
938
939    The problem described in this knowledge-base is applied only to pre-Vista
940    Windows.  Following function trying to detect OS version and skips
941    SO_SNDBUF adjustment for Windows Vista and above.
942 */
943 #define DETECT_OS_NONE 0
944 #define DETECT_OS_PREVISTA 1
945 #define DETECT_OS_VISTA_OR_LATER 2
946
947 void Curl_sndbufset(curl_socket_t sockfd)
948 {
949   int val = CURL_MAX_WRITE_SIZE + 32;
950   int curval = 0;
951   int curlen = sizeof(curval);
952
953   static int detectOsState = DETECT_OS_NONE;
954
955   if(detectOsState == DETECT_OS_NONE) {
956     if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
957                                    VERSION_GREATER_THAN_EQUAL))
958       detectOsState = DETECT_OS_VISTA_OR_LATER;
959     else
960       detectOsState = DETECT_OS_PREVISTA;
961   }
962
963   if(detectOsState == DETECT_OS_VISTA_OR_LATER)
964     return;
965
966   if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
967     if(curval > val)
968       return;
969
970   setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
971 }
972 #endif
973
974 /*
975  * singleipconnect()
976  *
977  * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
978  * CURL_SOCKET_BAD. Other errors will however return proper errors.
979  *
980  * singleipconnect() connects to the given IP only, and it may return without
981  * having connected.
982  */
983 static CURLcode singleipconnect(struct connectdata *conn,
984                                 const Curl_addrinfo *ai,
985                                 curl_socket_t *sockp)
986 {
987   struct Curl_sockaddr_ex addr;
988   int rc = -1;
989   int error = 0;
990   bool isconnected = FALSE;
991   struct Curl_easy *data = conn->data;
992   curl_socket_t sockfd;
993   CURLcode result;
994   char ipaddress[MAX_IPADR_LEN];
995   long port;
996   bool is_tcp;
997
998   *sockp = CURL_SOCKET_BAD;
999
1000   result = Curl_socket(conn, ai, &addr, &sockfd);
1001   if(result)
1002     /* Failed to create the socket, but still return OK since we signal the
1003        lack of socket as well. This allows the parent function to keep looping
1004        over alternative addresses/socket families etc. */
1005     return CURLE_OK;
1006
1007   /* store remote address and port used in this connection attempt */
1008   if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
1009                      ipaddress, &port)) {
1010     /* malformed address or bug in inet_ntop, try next address */
1011     error = ERRNO;
1012     failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
1013           error, Curl_strerror(conn, error));
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     error = data->set.fsockopt(data->set.sockopt_client,
1038                                sockfd,
1039                                CURLSOCKTYPE_IPCXN);
1040
1041     if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
1042       isconnected = TRUE;
1043     else if(error) {
1044       Curl_closesocket(conn, sockfd); /* close the socket and bail out */
1045       return CURLE_ABORTED_BY_CALLBACK;
1046     }
1047   }
1048
1049   /* possibly bind the local end to an IP, interface or port */
1050   if(addr.family == AF_INET
1051 #ifdef ENABLE_IPV6
1052      || addr.family == AF_INET6
1053 #endif
1054     ) {
1055     result = bindlocal(conn, sockfd, addr.family,
1056                        Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
1057     if(result) {
1058       Curl_closesocket(conn, sockfd); /* close socket and bail out */
1059       if(result == CURLE_UNSUPPORTED_PROTOCOL) {
1060         /* The address family is not supported on this interface.
1061            We can continue trying addresses */
1062         return CURLE_COULDNT_CONNECT;
1063       }
1064       return result;
1065     }
1066   }
1067
1068   /* set socket non-blocking */
1069   (void)curlx_nonblock(sockfd, TRUE);
1070
1071   conn->connecttime = Curl_tvnow();
1072   if(conn->num_addr > 1)
1073     Curl_expire_latest(data, conn->timeoutms_per_addr);
1074
1075   /* Connect TCP sockets, bind UDP */
1076   if(!isconnected && (conn->socktype == SOCK_STREAM)) {
1077     if(conn->bits.tcp_fastopen) {
1078 #if defined(CONNECT_DATA_IDEMPOTENT) /* OS X */
1079       sa_endpoints_t endpoints;
1080       endpoints.sae_srcif = 0;
1081       endpoints.sae_srcaddr = NULL;
1082       endpoints.sae_srcaddrlen = 0;
1083       endpoints.sae_dstaddr = &addr.sa_addr;
1084       endpoints.sae_dstaddrlen = addr.addrlen;
1085
1086       rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
1087                     CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
1088                     NULL, 0, NULL, NULL);
1089 #elif defined(MSG_FASTOPEN) /* Linux */
1090       if(conn->given->flags & PROTOPT_SSL)
1091         rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1092       else
1093         rc = 0; /* Do nothing */
1094 #endif
1095     }
1096     else {
1097       rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1098     }
1099
1100     if(-1 == rc)
1101       error = SOCKERRNO;
1102   }
1103   else {
1104     *sockp = sockfd;
1105     return CURLE_OK;
1106   }
1107
1108 #ifdef ENABLE_IPV6
1109   conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
1110 #endif
1111
1112   if(-1 == rc) {
1113     switch(error) {
1114     case EINPROGRESS:
1115     case EWOULDBLOCK:
1116 #if defined(EAGAIN)
1117 #if (EAGAIN) != (EWOULDBLOCK)
1118       /* On some platforms EAGAIN and EWOULDBLOCK are the
1119        * same value, and on others they are different, hence
1120        * the odd #if
1121        */
1122     case EAGAIN:
1123 #endif
1124 #endif
1125       result = CURLE_OK;
1126       break;
1127
1128     default:
1129       /* unknown error, fallthrough and try another address! */
1130       infof(data, "Immediate connect fail for %s: %s\n",
1131             ipaddress, Curl_strerror(conn, error));
1132       data->state.os_errno = error;
1133
1134       /* connect failed */
1135       Curl_closesocket(conn, sockfd);
1136       result = CURLE_COULDNT_CONNECT;
1137     }
1138   }
1139
1140   if(!result)
1141     *sockp = sockfd;
1142
1143   return result;
1144 }
1145
1146 /*
1147  * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1148  * There might be more than one IP address to try out. Fill in the passed
1149  * pointer with the connected socket.
1150  */
1151
1152 CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
1153                           const struct Curl_dns_entry *remotehost)
1154 {
1155   struct Curl_easy *data = conn->data;
1156   struct timeval before = Curl_tvnow();
1157   CURLcode result = CURLE_COULDNT_CONNECT;
1158
1159   long timeout_ms = Curl_timeleft(data, &before, TRUE);
1160
1161   if(timeout_ms < 0) {
1162     /* a precaution, no need to continue if time already is up */
1163     failf(data, "Connection time-out");
1164     return CURLE_OPERATION_TIMEDOUT;
1165   }
1166
1167   conn->num_addr = Curl_num_addresses(remotehost->addr);
1168   conn->tempaddr[0] = remotehost->addr;
1169   conn->tempaddr[1] = NULL;
1170   conn->tempsock[0] = CURL_SOCKET_BAD;
1171   conn->tempsock[1] = CURL_SOCKET_BAD;
1172   Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
1173
1174   /* Max time for the next connection attempt */
1175   conn->timeoutms_per_addr =
1176     conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
1177
1178   /* start connecting to first IP */
1179   while(conn->tempaddr[0]) {
1180     result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1181     if(!result)
1182       break;
1183     conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
1184   }
1185
1186   if(conn->tempsock[0] == CURL_SOCKET_BAD) {
1187     if(!result)
1188       result = CURLE_COULDNT_CONNECT;
1189     return result;
1190   }
1191
1192   data->info.numconnects++; /* to track the number of connections made */
1193
1194   return CURLE_OK;
1195 }
1196
1197 struct connfind {
1198   struct connectdata *tofind;
1199   bool found;
1200 };
1201
1202 static int conn_is_conn(struct connectdata *conn, void *param)
1203 {
1204   struct connfind *f = (struct connfind *)param;
1205   if(conn == f->tofind) {
1206     f->found = TRUE;
1207     return 1;
1208   }
1209   return 0;
1210 }
1211
1212 /*
1213  * Used to extract socket and connectdata struct for the most recent
1214  * transfer on the given Curl_easy.
1215  *
1216  * The returned socket will be CURL_SOCKET_BAD in case of failure!
1217  */
1218 curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
1219                                   struct connectdata **connp)
1220 {
1221   curl_socket_t sockfd;
1222
1223   DEBUGASSERT(data);
1224
1225   /* this works for an easy handle:
1226    * - that has been used for curl_easy_perform()
1227    * - that is associated with a multi handle, and whose connection
1228    *   was detached with CURLOPT_CONNECT_ONLY
1229    */
1230   if(data->state.lastconnect && (data->multi_easy || data->multi)) {
1231     struct connectdata *c = data->state.lastconnect;
1232     struct connfind find;
1233     find.tofind = data->state.lastconnect;
1234     find.found = FALSE;
1235
1236     Curl_conncache_foreach(data->multi_easy?
1237                            &data->multi_easy->conn_cache:
1238                            &data->multi->conn_cache, &find, conn_is_conn);
1239
1240     if(!find.found) {
1241       data->state.lastconnect = NULL;
1242       return CURL_SOCKET_BAD;
1243     }
1244
1245     if(connp)
1246       /* only store this if the caller cares for it */
1247       *connp = c;
1248     sockfd = c->sock[FIRSTSOCKET];
1249     /* we have a socket connected, let's determine if the server shut down */
1250     /* determine if ssl */
1251     if(c->ssl[FIRSTSOCKET].use) {
1252       /* use the SSL context */
1253       if(!Curl_ssl_check_cxn(c))
1254         return CURL_SOCKET_BAD;   /* FIN received */
1255     }
1256 /* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1257 #ifdef MSG_PEEK
1258     else if(sockfd != CURL_SOCKET_BAD) {
1259       /* use the socket */
1260       char buf;
1261       if(recv((RECV_TYPE_ARG1)sockfd, (RECV_TYPE_ARG2)&buf,
1262               (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
1263         return CURL_SOCKET_BAD;   /* FIN received */
1264       }
1265     }
1266 #endif
1267   }
1268   else
1269     return CURL_SOCKET_BAD;
1270
1271   return sockfd;
1272 }
1273
1274 /*
1275  * Close a socket.
1276  *
1277  * 'conn' can be NULL, beware!
1278  */
1279 int Curl_closesocket(struct connectdata *conn,
1280                       curl_socket_t sock)
1281 {
1282   if(conn && conn->fclosesocket) {
1283     if((sock == conn->sock[SECONDARYSOCKET]) &&
1284        conn->sock_accepted[SECONDARYSOCKET])
1285       /* if this socket matches the second socket, and that was created with
1286          accept, then we MUST NOT call the callback but clear the accepted
1287          status */
1288       conn->sock_accepted[SECONDARYSOCKET] = FALSE;
1289     else {
1290       Curl_multi_closed(conn, sock);
1291       return conn->fclosesocket(conn->closesocket_client, sock);
1292     }
1293   }
1294
1295   if(conn)
1296     /* tell the multi-socket code about this */
1297     Curl_multi_closed(conn, sock);
1298
1299   sclose(sock);
1300
1301   return 0;
1302 }
1303
1304 /*
1305  * Create a socket based on info from 'conn' and 'ai'.
1306  *
1307  * 'addr' should be a pointer to the correct struct to get data back, or NULL.
1308  * 'sockfd' must be a pointer to a socket descriptor.
1309  *
1310  * If the open socket callback is set, used that!
1311  *
1312  */
1313 CURLcode Curl_socket(struct connectdata *conn,
1314                      const Curl_addrinfo *ai,
1315                      struct Curl_sockaddr_ex *addr,
1316                      curl_socket_t *sockfd)
1317 {
1318   struct Curl_easy *data = conn->data;
1319   struct Curl_sockaddr_ex dummy;
1320
1321   if(!addr)
1322     /* if the caller doesn't want info back, use a local temp copy */
1323     addr = &dummy;
1324
1325   /*
1326    * The Curl_sockaddr_ex structure is basically libcurl's external API
1327    * curl_sockaddr structure with enough space available to directly hold
1328    * any protocol-specific address structures. The variable declared here
1329    * will be used to pass / receive data to/from the fopensocket callback
1330    * if this has been set, before that, it is initialized from parameters.
1331    */
1332
1333   addr->family = ai->ai_family;
1334   addr->socktype = conn->socktype;
1335   addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1336   addr->addrlen = ai->ai_addrlen;
1337
1338   if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
1339      addr->addrlen = sizeof(struct Curl_sockaddr_storage);
1340   memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
1341
1342   if(data->set.fopensocket)
1343    /*
1344     * If the opensocket callback is set, all the destination address
1345     * information is passed to the callback. Depending on this information the
1346     * callback may opt to abort the connection, this is indicated returning
1347     * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
1348     * the callback returns a valid socket the destination address information
1349     * might have been changed and this 'new' address will actually be used
1350     * here to connect.
1351     */
1352     *sockfd = data->set.fopensocket(data->set.opensocket_client,
1353                                     CURLSOCKTYPE_IPCXN,
1354                                     (struct curl_sockaddr *)addr);
1355   else
1356     /* opensocket callback not set, so simply create the socket now */
1357     *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1358
1359   if(*sockfd == CURL_SOCKET_BAD)
1360     /* no socket, no connection */
1361     return CURLE_COULDNT_CONNECT;
1362
1363 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
1364   if(conn->scope_id && (addr->family == AF_INET6)) {
1365     struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
1366     sa6->sin6_scope_id = conn->scope_id;
1367   }
1368 #endif
1369
1370   return CURLE_OK;
1371
1372 }
1373
1374 /*
1375  * Curl_conncontrol() marks streams or connection for closure.
1376  */
1377 void Curl_conncontrol(struct connectdata *conn,
1378                       int ctrl /* see defines in header */
1379 #ifdef DEBUGBUILD
1380                       , const char *reason
1381 #endif
1382   )
1383 {
1384   /* close if a connection, or a stream that isn't multiplexed */
1385   bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
1386     ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
1387   if((ctrl == CONNCTRL_STREAM) &&
1388      (conn->handler->flags & PROTOPT_STREAM))
1389     DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
1390   else if(closeit != conn->bits.close) {
1391     DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
1392                  closeit?"closure":"keep alive", reason));
1393     conn->bits.close = closeit; /* the only place in the source code that
1394                                    should assign this bit */
1395   }
1396 }