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