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