18ac32c324cae9c5c82e5ebc824416bba5b4bd64
[platform/upstream/curl.git] / lib / connect.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2015, 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 http://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*) 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*)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 static void tcpnodelay(struct connectdata *conn,
861                        curl_socket_t sockfd)
862 {
863 #ifdef TCP_NODELAY
864   struct SessionHandle *data= conn->data;
865   curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
866   int level = IPPROTO_TCP;
867
868 #if 0
869   /* The use of getprotobyname() is disabled since it isn't thread-safe on
870      numerous systems. On these getprotobyname_r() should be used instead, but
871      that exists in at least one 4 arg version and one 5 arg version, and
872      since the proto number rarely changes anyway we now just use the hard
873      coded number. The "proper" fix would need a configure check for the
874      correct function much in the same style the gethostbyname_r versions are
875      detected. */
876   struct protoent *pe = getprotobyname("tcp");
877   if(pe)
878     level = pe->p_proto;
879 #endif
880
881   if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
882                 sizeof(onoff)) < 0)
883     infof(data, "Could not set TCP_NODELAY: %s\n",
884           Curl_strerror(conn, SOCKERRNO));
885   else
886     infof(data, "TCP_NODELAY set\n");
887 #else
888   (void)conn;
889   (void)sockfd;
890 #endif
891 }
892
893 #ifdef SO_NOSIGPIPE
894 /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
895    sending data to a dead peer (instead of relying on the 4th argument to send
896    being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
897    systems? */
898 static void nosigpipe(struct connectdata *conn,
899                       curl_socket_t sockfd)
900 {
901   struct SessionHandle *data= conn->data;
902   int onoff = 1;
903   if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
904                 sizeof(onoff)) < 0)
905     infof(data, "Could not set SO_NOSIGPIPE: %s\n",
906           Curl_strerror(conn, SOCKERRNO));
907 }
908 #else
909 #define nosigpipe(x,y) Curl_nop_stmt
910 #endif
911
912 #ifdef USE_WINSOCK
913 /* When you run a program that uses the Windows Sockets API, you may
914    experience slow performance when you copy data to a TCP server.
915
916    http://support.microsoft.com/kb/823764
917
918    Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
919    Buffer Size
920
921    The problem described in this knowledge-base is applied only to pre-Vista
922    Windows.  Following function trying to detect OS version and skips
923    SO_SNDBUF adjustment for Windows Vista and above.
924 */
925 #define DETECT_OS_NONE 0
926 #define DETECT_OS_PREVISTA 1
927 #define DETECT_OS_VISTA_OR_LATER 2
928
929 void Curl_sndbufset(curl_socket_t sockfd)
930 {
931   int val = CURL_MAX_WRITE_SIZE + 32;
932   int curval = 0;
933   int curlen = sizeof(curval);
934   DWORD majorVersion = 6;
935
936   static int detectOsState = DETECT_OS_NONE;
937
938   if(detectOsState == DETECT_OS_NONE) {
939 #if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
940     (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
941     OSVERSIONINFO osver;
942
943     memset(&osver, 0, sizeof(osver));
944     osver.dwOSVersionInfoSize = sizeof(osver);
945
946     detectOsState = DETECT_OS_PREVISTA;
947     if(GetVersionEx(&osver)) {
948       if(osver.dwMajorVersion >= majorVersion)
949         detectOsState = DETECT_OS_VISTA_OR_LATER;
950     }
951 #else
952     ULONGLONG cm;
953     OSVERSIONINFOEX osver;
954
955     memset(&osver, 0, sizeof(osver));
956     osver.dwOSVersionInfoSize = sizeof(osver);
957     osver.dwMajorVersion = majorVersion;
958
959     cm = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
960     cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_GREATER_EQUAL);
961     cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
962     cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
963
964     if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
965                                   VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
966                          cm))
967       detectOsState = DETECT_OS_VISTA_OR_LATER;
968     else
969       detectOsState = DETECT_OS_PREVISTA;
970 #endif
971   }
972
973   if(detectOsState == DETECT_OS_VISTA_OR_LATER)
974     return;
975
976   if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
977     if(curval > val)
978       return;
979
980   setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
981 }
982 #endif
983
984 /*
985  * singleipconnect()
986  *
987  * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
988  * CURL_SOCKET_BAD. Other errors will however return proper errors.
989  *
990  * singleipconnect() connects to the given IP only, and it may return without
991  * having connected.
992  */
993 static CURLcode singleipconnect(struct connectdata *conn,
994                                 const Curl_addrinfo *ai,
995                                 curl_socket_t *sockp)
996 {
997   struct Curl_sockaddr_ex addr;
998   int rc;
999   int error = 0;
1000   bool isconnected = FALSE;
1001   struct SessionHandle *data = conn->data;
1002   curl_socket_t sockfd;
1003   CURLcode result;
1004   char ipaddress[MAX_IPADR_LEN];
1005   long port;
1006   bool is_tcp;
1007
1008   *sockp = CURL_SOCKET_BAD;
1009
1010   result = Curl_socket(conn, ai, &addr, &sockfd);
1011   if(result)
1012     /* Failed to create the socket, but still return OK since we signal the
1013        lack of socket as well. This allows the parent function to keep looping
1014        over alternative addresses/socket families etc. */
1015     return CURLE_OK;
1016
1017   /* store remote address and port used in this connection attempt */
1018   if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
1019                      ipaddress, &port)) {
1020     /* malformed address or bug in inet_ntop, try next address */
1021     error = ERRNO;
1022     failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
1023           error, Curl_strerror(conn, error));
1024     Curl_closesocket(conn, sockfd);
1025     return CURLE_OK;
1026   }
1027   infof(data, "  Trying %s...\n", ipaddress);
1028
1029 #ifdef ENABLE_IPV6
1030   is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
1031     addr.socktype == SOCK_STREAM;
1032 #else
1033   is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
1034 #endif
1035   if(is_tcp && data->set.tcp_nodelay)
1036     tcpnodelay(conn, sockfd);
1037
1038   nosigpipe(conn, sockfd);
1039
1040   Curl_sndbufset(sockfd);
1041
1042   if(is_tcp && data->set.tcp_keepalive)
1043     tcpkeepalive(data, sockfd);
1044
1045   if(data->set.fsockopt) {
1046     /* activate callback for setting socket options */
1047     error = data->set.fsockopt(data->set.sockopt_client,
1048                                sockfd,
1049                                CURLSOCKTYPE_IPCXN);
1050
1051     if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
1052       isconnected = TRUE;
1053     else if(error) {
1054       Curl_closesocket(conn, sockfd); /* close the socket and bail out */
1055       return CURLE_ABORTED_BY_CALLBACK;
1056     }
1057   }
1058
1059   /* possibly bind the local end to an IP, interface or port */
1060   if(addr.family == AF_INET
1061 #ifdef ENABLE_IPV6
1062      || addr.family == AF_INET6
1063 #endif
1064     ) {
1065     result = bindlocal(conn, sockfd, addr.family,
1066                        Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
1067     if(result) {
1068       Curl_closesocket(conn, sockfd); /* close socket and bail out */
1069       if(result == CURLE_UNSUPPORTED_PROTOCOL) {
1070         /* The address family is not supported on this interface.
1071            We can continue trying addresses */
1072         return CURLE_COULDNT_CONNECT;
1073       }
1074       return result;
1075     }
1076   }
1077
1078   /* set socket non-blocking */
1079   (void)curlx_nonblock(sockfd, TRUE);
1080
1081   conn->connecttime = Curl_tvnow();
1082   if(conn->num_addr > 1)
1083     Curl_expire_latest(data, conn->timeoutms_per_addr);
1084
1085   /* Connect TCP sockets, bind UDP */
1086   if(!isconnected && (conn->socktype == SOCK_STREAM)) {
1087     rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1088     if(-1 == rc)
1089       error = SOCKERRNO;
1090   }
1091   else {
1092     *sockp = sockfd;
1093     return CURLE_OK;
1094   }
1095
1096 #ifdef ENABLE_IPV6
1097   conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
1098 #endif
1099
1100   if(-1 == rc) {
1101     switch(error) {
1102     case EINPROGRESS:
1103     case EWOULDBLOCK:
1104 #if defined(EAGAIN)
1105 #if (EAGAIN) != (EWOULDBLOCK)
1106       /* On some platforms EAGAIN and EWOULDBLOCK are the
1107        * same value, and on others they are different, hence
1108        * the odd #if
1109        */
1110     case EAGAIN:
1111 #endif
1112 #endif
1113       result = CURLE_OK;
1114       break;
1115
1116     default:
1117       /* unknown error, fallthrough and try another address! */
1118       infof(data, "Immediate connect fail for %s: %s\n",
1119             ipaddress, Curl_strerror(conn, error));
1120       data->state.os_errno = error;
1121
1122       /* connect failed */
1123       Curl_closesocket(conn, sockfd);
1124       result = CURLE_COULDNT_CONNECT;
1125     }
1126   }
1127
1128   if(!result)
1129     *sockp = sockfd;
1130
1131   return result;
1132 }
1133
1134 /*
1135  * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1136  * There might be more than one IP address to try out. Fill in the passed
1137  * pointer with the connected socket.
1138  */
1139
1140 CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
1141                           const struct Curl_dns_entry *remotehost)
1142 {
1143   struct SessionHandle *data = conn->data;
1144   struct timeval before = Curl_tvnow();
1145   CURLcode result = CURLE_COULDNT_CONNECT;
1146
1147   long timeout_ms = Curl_timeleft(data, &before, TRUE);
1148
1149   if(timeout_ms < 0) {
1150     /* a precaution, no need to continue if time already is up */
1151     failf(data, "Connection time-out");
1152     return CURLE_OPERATION_TIMEDOUT;
1153   }
1154
1155   conn->num_addr = Curl_num_addresses(remotehost->addr);
1156   conn->tempaddr[0] = remotehost->addr;
1157   conn->tempaddr[1] = NULL;
1158   conn->tempsock[0] = CURL_SOCKET_BAD;
1159   conn->tempsock[1] = CURL_SOCKET_BAD;
1160   Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
1161
1162   /* Max time for the next connection attempt */
1163   conn->timeoutms_per_addr =
1164     conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
1165
1166   /* start connecting to first IP */
1167   while(conn->tempaddr[0]) {
1168     result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1169     if(!result)
1170       break;
1171     conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
1172   }
1173
1174   if(conn->tempsock[0] == CURL_SOCKET_BAD) {
1175     if(!result)
1176       result = CURLE_COULDNT_CONNECT;
1177     return result;
1178   }
1179
1180   data->info.numconnects++; /* to track the number of connections made */
1181
1182   return CURLE_OK;
1183 }
1184
1185 struct connfind {
1186   struct connectdata *tofind;
1187   bool found;
1188 };
1189
1190 static int conn_is_conn(struct connectdata *conn, void *param)
1191 {
1192   struct connfind *f = (struct connfind *)param;
1193   if(conn == f->tofind) {
1194     f->found = TRUE;
1195     return 1;
1196   }
1197   return 0;
1198 }
1199
1200 /*
1201  * Used to extract socket and connectdata struct for the most recent
1202  * transfer on the given SessionHandle.
1203  *
1204  * The returned socket will be CURL_SOCKET_BAD in case of failure!
1205  */
1206 curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
1207                                   struct connectdata **connp)
1208 {
1209   curl_socket_t sockfd;
1210
1211   DEBUGASSERT(data);
1212
1213   /* this works for an easy handle:
1214    * - that has been used for curl_easy_perform()
1215    * - that is associated with a multi handle, and whose connection
1216    *   was detached with CURLOPT_CONNECT_ONLY
1217    */
1218   if(data->state.lastconnect && (data->multi_easy || data->multi)) {
1219     struct connectdata *c = data->state.lastconnect;
1220     struct connfind find;
1221     find.tofind = data->state.lastconnect;
1222     find.found = FALSE;
1223
1224     Curl_conncache_foreach(data->multi_easy?
1225                            &data->multi_easy->conn_cache:
1226                            &data->multi->conn_cache, &find, conn_is_conn);
1227
1228     if(!find.found) {
1229       data->state.lastconnect = NULL;
1230       return CURL_SOCKET_BAD;
1231     }
1232
1233     if(connp)
1234       /* only store this if the caller cares for it */
1235       *connp = c;
1236     sockfd = c->sock[FIRSTSOCKET];
1237     /* we have a socket connected, let's determine if the server shut down */
1238     /* determine if ssl */
1239     if(c->ssl[FIRSTSOCKET].use) {
1240       /* use the SSL context */
1241       if(!Curl_ssl_check_cxn(c))
1242         return CURL_SOCKET_BAD;   /* FIN received */
1243     }
1244 /* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1245 #ifdef MSG_PEEK
1246     else {
1247       /* use the socket */
1248       char buf;
1249       if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1250               (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
1251         return CURL_SOCKET_BAD;   /* FIN received */
1252       }
1253     }
1254 #endif
1255   }
1256   else
1257     return CURL_SOCKET_BAD;
1258
1259   return sockfd;
1260 }
1261
1262 /*
1263  * Close a socket.
1264  *
1265  * 'conn' can be NULL, beware!
1266  */
1267 int Curl_closesocket(struct connectdata *conn,
1268                       curl_socket_t sock)
1269 {
1270   if(conn && conn->fclosesocket) {
1271     if((sock == conn->sock[SECONDARYSOCKET]) &&
1272        conn->sock_accepted[SECONDARYSOCKET])
1273       /* if this socket matches the second socket, and that was created with
1274          accept, then we MUST NOT call the callback but clear the accepted
1275          status */
1276       conn->sock_accepted[SECONDARYSOCKET] = FALSE;
1277     else {
1278       Curl_multi_closed(conn, sock);
1279       return conn->fclosesocket(conn->closesocket_client, sock);
1280     }
1281   }
1282
1283   if(conn)
1284     /* tell the multi-socket code about this */
1285     Curl_multi_closed(conn, sock);
1286
1287   sclose(sock);
1288
1289   return 0;
1290 }
1291
1292 /*
1293  * Create a socket based on info from 'conn' and 'ai'.
1294  *
1295  * 'addr' should be a pointer to the correct struct to get data back, or NULL.
1296  * 'sockfd' must be a pointer to a socket descriptor.
1297  *
1298  * If the open socket callback is set, used that!
1299  *
1300  */
1301 CURLcode Curl_socket(struct connectdata *conn,
1302                      const Curl_addrinfo *ai,
1303                      struct Curl_sockaddr_ex *addr,
1304                      curl_socket_t *sockfd)
1305 {
1306   struct SessionHandle *data = conn->data;
1307   struct Curl_sockaddr_ex dummy;
1308
1309   if(!addr)
1310     /* if the caller doesn't want info back, use a local temp copy */
1311     addr = &dummy;
1312
1313   /*
1314    * The Curl_sockaddr_ex structure is basically libcurl's external API
1315    * curl_sockaddr structure with enough space available to directly hold
1316    * any protocol-specific address structures. The variable declared here
1317    * will be used to pass / receive data to/from the fopensocket callback
1318    * if this has been set, before that, it is initialized from parameters.
1319    */
1320
1321   addr->family = ai->ai_family;
1322   addr->socktype = conn->socktype;
1323   addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1324   addr->addrlen = ai->ai_addrlen;
1325
1326   if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
1327      addr->addrlen = sizeof(struct Curl_sockaddr_storage);
1328   memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
1329
1330   if(data->set.fopensocket)
1331    /*
1332     * If the opensocket callback is set, all the destination address
1333     * information is passed to the callback. Depending on this information the
1334     * callback may opt to abort the connection, this is indicated returning
1335     * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
1336     * the callback returns a valid socket the destination address information
1337     * might have been changed and this 'new' address will actually be used
1338     * here to connect.
1339     */
1340     *sockfd = data->set.fopensocket(data->set.opensocket_client,
1341                                     CURLSOCKTYPE_IPCXN,
1342                                     (struct curl_sockaddr *)addr);
1343   else
1344     /* opensocket callback not set, so simply create the socket now */
1345     *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1346
1347   if(*sockfd == CURL_SOCKET_BAD)
1348     /* no socket, no connection */
1349     return CURLE_COULDNT_CONNECT;
1350
1351 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
1352   if(conn->scope_id && (addr->family == AF_INET6)) {
1353     struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
1354     sa6->sin6_scope_id = conn->scope_id;
1355   }
1356 #endif
1357
1358   return CURLE_OK;
1359
1360 }
1361
1362 #ifdef CURLDEBUG
1363 /*
1364  * Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
1365  * MUST be called with the connclose() or connkeep() macros with a stated
1366  * reason. The reason is only shown in debug builds but helps to figure out
1367  * decision paths when connections are or aren't re-used as expected.
1368  */
1369 void Curl_conncontrol(struct connectdata *conn, bool closeit,
1370                       const char *reason)
1371 {
1372 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
1373   (void) reason;
1374 #endif
1375   if(closeit != conn->bits.close) {
1376     infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
1377           reason);
1378
1379     conn->bits.close = closeit; /* the only place in the source code that
1380                                    should assign this bit */
1381   }
1382 }
1383 #endif