1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2014, 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#define _MPRINTF_REPLACE /* use our functions only */
60#include <curl/mprintf.h>
61
62#include "urldata.h"
63#include "sendf.h"
64#include "if2ip.h"
65#include "strerror.h"
66#include "connect.h"
67#include "curl_memory.h"
68#include "select.h"
69#include "url.h" /* for Curl_safefree() */
70#include "multiif.h"
71#include "sockaddr.h" /* required for Curl_sockaddr_storage */
72#include "inet_ntop.h"
73#include "inet_pton.h"
74#include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
75#include "progress.h"
76#include "warnless.h"
77#include "conncache.h"
78#include "multihandle.h"
79
80/* The last #include file should be: */
81#include "memdebug.h"
82
83#ifdef __SYMBIAN32__
84/* This isn't actually supported under Symbian OS */
85#undef SO_NOSIGPIPE
86#endif
87
88static bool verifyconnect(curl_socket_t sockfd, int *error);
89
90#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
91/* DragonFlyBSD and Windows use millisecond units */
92#define KEEPALIVE_FACTOR(x) (x *= 1000)
93#else
94#define KEEPALIVE_FACTOR(x)
95#endif
96
97#if defined(HAVE_WINSOCK_H) && !defined(SIO_KEEPALIVE_VALS)
98#define SIO_KEEPALIVE_VALS    _WSAIOW(IOC_VENDOR,4)
99
100struct tcp_keepalive {
101  u_long onoff;
102  u_long keepalivetime;
103  u_long keepaliveinterval;
104};
105#endif
106
107static void
108tcpkeepalive(struct SessionHandle *data,
109             curl_socket_t sockfd)
110{
111  int optval = data->set.tcp_keepalive?1:0;
112
113  /* only set IDLE and INTVL if setting KEEPALIVE is successful */
114  if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
115        (void *)&optval, sizeof(optval)) < 0) {
116    infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd);
117  }
118  else {
119#if defined(SIO_KEEPALIVE_VALS)
120    struct tcp_keepalive vals;
121    DWORD dummy;
122    vals.onoff = 1;
123    optval = curlx_sltosi(data->set.tcp_keepidle);
124    KEEPALIVE_FACTOR(optval);
125    vals.keepalivetime = optval;
126    optval = curlx_sltosi(data->set.tcp_keepintvl);
127    KEEPALIVE_FACTOR(optval);
128    vals.keepaliveinterval = optval;
129    if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
130                NULL, 0, &dummy, NULL, NULL) != 0) {
131      infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
132            (int)sockfd, WSAGetLastError());
133    }
134#else
135#ifdef TCP_KEEPIDLE
136    optval = curlx_sltosi(data->set.tcp_keepidle);
137    KEEPALIVE_FACTOR(optval);
138    if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
139          (void *)&optval, sizeof(optval)) < 0) {
140      infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd);
141    }
142#endif
143#ifdef TCP_KEEPINTVL
144    optval = curlx_sltosi(data->set.tcp_keepintvl);
145    KEEPALIVE_FACTOR(optval);
146    if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
147          (void *)&optval, sizeof(optval)) < 0) {
148      infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd);
149    }
150#endif
151#ifdef TCP_KEEPALIVE
152    /* Mac OS X style */
153    optval = curlx_sltosi(data->set.tcp_keepidle);
154    KEEPALIVE_FACTOR(optval);
155    if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
156          (void *)&optval, sizeof(optval)) < 0) {
157      infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd);
158    }
159#endif
160#endif
161  }
162}
163
164static CURLcode
165singleipconnect(struct connectdata *conn,
166                const Curl_addrinfo *ai, /* start connecting to this */
167                curl_socket_t *sock);
168
169/*
170 * Curl_timeleft() returns the amount of milliseconds left allowed for the
171 * transfer/connection. If the value is negative, the timeout time has already
172 * elapsed.
173 *
174 * The start time is stored in progress.t_startsingle - as set with
175 * Curl_pgrsTime(..., TIMER_STARTSINGLE);
176 *
177 * If 'nowp' is non-NULL, it points to the current time.
178 * 'duringconnect' is FALSE if not during a connect, as then of course the
179 * connect timeout is not taken into account!
180 *
181 * @unittest: 1303
182 */
183long Curl_timeleft(struct SessionHandle *data,
184                   struct timeval *nowp,
185                   bool duringconnect)
186{
187  int timeout_set = 0;
188  long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
189  struct timeval now;
190
191  /* if a timeout is set, use the most restrictive one */
192
193  if(data->set.timeout > 0)
194    timeout_set |= 1;
195  if(duringconnect && (data->set.connecttimeout > 0))
196    timeout_set |= 2;
197
198  switch (timeout_set) {
199  case 1:
200    timeout_ms = data->set.timeout;
201    break;
202  case 2:
203    timeout_ms = data->set.connecttimeout;
204    break;
205  case 3:
206    if(data->set.timeout < data->set.connecttimeout)
207      timeout_ms = data->set.timeout;
208    else
209      timeout_ms = data->set.connecttimeout;
210    break;
211  default:
212    /* use the default */
213    if(!duringconnect)
214      /* if we're not during connect, there's no default timeout so if we're
215         at zero we better just return zero and not make it a negative number
216         by the math below */
217      return 0;
218    break;
219  }
220
221  if(!nowp) {
222    now = Curl_tvnow();
223    nowp = &now;
224  }
225
226  /* subtract elapsed time */
227  if(duringconnect)
228    /* since this most recent connect started */
229    timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
230  else
231    /* since the entire operation started */
232    timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop);
233  if(!timeout_ms)
234    /* avoid returning 0 as that means no timeout! */
235    return -1;
236
237  return timeout_ms;
238}
239
240static CURLcode bindlocal(struct connectdata *conn,
241                          curl_socket_t sockfd, int af)
242{
243  struct SessionHandle *data = conn->data;
244
245  struct Curl_sockaddr_storage sa;
246  struct sockaddr *sock = (struct sockaddr *)&sa;  /* bind to this address */
247  curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
248  struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
249#ifdef ENABLE_IPV6
250  struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
251#endif
252
253  struct Curl_dns_entry *h=NULL;
254  unsigned short port = data->set.localport; /* use this port number, 0 for
255                                                "random" */
256  /* how many port numbers to try to bind to, increasing one at a time */
257  int portnum = data->set.localportrange;
258  const char *dev = data->set.str[STRING_DEVICE];
259  int error;
260  char myhost[256] = "";
261  int done = 0; /* -1 for error, 1 for address found */
262  bool is_interface = FALSE;
263  bool is_host = FALSE;
264  static const char *if_prefix = "if!";
265  static const char *host_prefix = "host!";
266
267  /*************************************************************
268   * Select device to bind socket to
269   *************************************************************/
270  if(!dev && !port)
271    /* no local kind of binding was requested */
272    return CURLE_OK;
273
274  memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
275
276  if(dev && (strlen(dev)<255) ) {
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, conn->scope, dev, 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 */
473static 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 */
539static CURLcode trynextip(struct connectdata *conn,
540                          int sockindex,
541                          int tempindex)
542{
543  CURLcode rc = CURLE_COULDNT_CONNECT;
544
545  /* First clean up after the failed socket.
546     Don't close it yet to ensure that the next IP's socket gets a different
547     file descriptor, which can prevent bugs when the curl_multi_socket_action
548     interface is used with certain select() replacements such as kqueue. */
549  curl_socket_t fd_to_close = conn->tempsock[tempindex];
550  conn->tempsock[tempindex] = CURL_SOCKET_BAD;
551
552  if(sockindex == FIRSTSOCKET) {
553    Curl_addrinfo *ai = NULL;
554    int family = AF_UNSPEC;
555
556    if(conn->tempaddr[tempindex]) {
557      /* find next address in the same protocol family */
558      family = conn->tempaddr[tempindex]->ai_family;
559      ai = conn->tempaddr[tempindex]->ai_next;
560    }
561    else if(conn->tempaddr[0]) {
562      /* happy eyeballs - try the other protocol family */
563      int firstfamily = conn->tempaddr[0]->ai_family;
564#ifdef ENABLE_IPV6
565      family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
566#else
567      family = firstfamily;
568#endif
569      ai = conn->tempaddr[0]->ai_next;
570    }
571
572    while(ai) {
573      while(ai && ai->ai_family != family)
574        ai = ai->ai_next;
575
576      if(ai) {
577        rc = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
578        if(rc == CURLE_COULDNT_CONNECT) {
579          ai = ai->ai_next;
580          continue;
581        }
582        conn->tempaddr[tempindex] = ai;
583      }
584      break;
585    }
586  }
587
588  if(fd_to_close != CURL_SOCKET_BAD)
589    Curl_closesocket(conn, fd_to_close);
590
591  return rc;
592}
593
594/* Copies connection info into the session handle to make it available
595   when the session handle is no longer associated with a connection. */
596void Curl_persistconninfo(struct connectdata *conn)
597{
598  memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
599  memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
600  conn->data->info.conn_primary_port = conn->primary_port;
601  conn->data->info.conn_local_port = conn->local_port;
602}
603
604/* retrieves ip address and port from a sockaddr structure */
605static bool getaddressinfo(struct sockaddr* sa, char* addr,
606                           long* port)
607{
608  unsigned short us_port;
609  struct sockaddr_in* si = NULL;
610#ifdef ENABLE_IPV6
611  struct sockaddr_in6* si6 = NULL;
612#endif
613#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
614  struct sockaddr_un* su = NULL;
615#endif
616
617  switch (sa->sa_family) {
618    case AF_INET:
619      si = (struct sockaddr_in*) sa;
620      if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
621                        addr, MAX_IPADR_LEN)) {
622        us_port = ntohs(si->sin_port);
623        *port = us_port;
624        return TRUE;
625      }
626      break;
627#ifdef ENABLE_IPV6
628    case AF_INET6:
629      si6 = (struct sockaddr_in6*)sa;
630      if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
631                        addr, MAX_IPADR_LEN)) {
632        us_port = ntohs(si6->sin6_port);
633        *port = us_port;
634        return TRUE;
635      }
636      break;
637#endif
638#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
639    case AF_UNIX:
640      su = (struct sockaddr_un*)sa;
641      snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
642      *port = 0;
643      return TRUE;
644#endif
645    default:
646      break;
647  }
648
649  addr[0] = '\0';
650  *port = 0;
651
652  return FALSE;
653}
654
655/* retrieves the start/end point information of a socket of an established
656   connection */
657void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
658{
659  int error;
660  curl_socklen_t len;
661  struct Curl_sockaddr_storage ssrem;
662  struct Curl_sockaddr_storage ssloc;
663  struct SessionHandle *data = conn->data;
664
665  if(conn->socktype == SOCK_DGRAM)
666    /* there's no connection! */
667    return;
668
669  if(!conn->bits.reuse) {
670
671    len = sizeof(struct Curl_sockaddr_storage);
672    if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
673      error = SOCKERRNO;
674      failf(data, "getpeername() failed with errno %d: %s",
675            error, Curl_strerror(conn, error));
676      return;
677    }
678
679    len = sizeof(struct Curl_sockaddr_storage);
680    if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
681      error = SOCKERRNO;
682      failf(data, "getsockname() failed with errno %d: %s",
683            error, Curl_strerror(conn, error));
684      return;
685    }
686
687    if(!getaddressinfo((struct sockaddr*)&ssrem,
688                        conn->primary_ip, &conn->primary_port)) {
689      error = ERRNO;
690      failf(data, "ssrem inet_ntop() failed with errno %d: %s",
691            error, Curl_strerror(conn, error));
692      return;
693    }
694    memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
695
696    if(!getaddressinfo((struct sockaddr*)&ssloc,
697                       conn->local_ip, &conn->local_port)) {
698      error = ERRNO;
699      failf(data, "ssloc inet_ntop() failed with errno %d: %s",
700            error, Curl_strerror(conn, error));
701      return;
702    }
703
704  }
705
706  /* persist connection info in session handle */
707  Curl_persistconninfo(conn);
708}
709
710/*
711 * Curl_is_connected() checks if the socket has connected.
712 */
713
714CURLcode Curl_is_connected(struct connectdata *conn,
715                           int sockindex,
716                           bool *connected)
717{
718  struct SessionHandle *data = conn->data;
719  CURLcode code = CURLE_OK;
720  long allow;
721  int error = 0;
722  struct timeval now;
723  int result;
724  int i;
725
726  DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
727
728  *connected = FALSE; /* a very negative world view is best */
729
730  if(conn->bits.tcpconnect[sockindex]) {
731    /* we are connected already! */
732    *connected = TRUE;
733    return CURLE_OK;
734  }
735
736  now = Curl_tvnow();
737
738  /* figure out how long time we have left to connect */
739  allow = Curl_timeleft(data, &now, TRUE);
740
741  if(allow < 0) {
742    /* time-out, bail out, go home */
743    failf(data, "Connection time-out");
744    return CURLE_OPERATION_TIMEDOUT;
745  }
746
747  for(i=0; i<2; i++) {
748    if(conn->tempsock[i] == CURL_SOCKET_BAD)
749      continue;
750
751#ifdef mpeix
752    /* Call this function once now, and ignore the results. We do this to
753       "clear" the error state on the socket so that we can later read it
754       reliably. This is reported necessary on the MPE/iX operating system. */
755    (void)verifyconnect(conn->tempsock[i], NULL);
756#endif
757
758    /* check socket for connect */
759    result = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
760
761    if(result == 0) { /* no connection yet */
762      if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
763        infof(data, "After %ldms connect time, move on!\n",
764              conn->timeoutms_per_addr);
765        error = ETIMEDOUT;
766      }
767
768      /* should we try another protocol family? */
769      if(i == 0 && conn->tempaddr[1] == NULL &&
770         curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
771        trynextip(conn, sockindex, 1);
772      }
773    }
774    else if(result == CURL_CSELECT_OUT) {
775      if(verifyconnect(conn->tempsock[i], &error)) {
776        /* we are connected with TCP, awesome! */
777        int other = i ^ 1;
778
779        /* use this socket from now on */
780        conn->sock[sockindex] = conn->tempsock[i];
781        conn->ip_addr = conn->tempaddr[i];
782        conn->tempsock[i] = CURL_SOCKET_BAD;
783
784        /* close the other socket, if open */
785        if(conn->tempsock[other] != CURL_SOCKET_BAD) {
786          Curl_closesocket(conn, conn->tempsock[other]);
787          conn->tempsock[other] = CURL_SOCKET_BAD;
788        }
789
790        /* see if we need to do any proxy magic first once we connected */
791        code = Curl_connected_proxy(conn, sockindex);
792        if(code)
793          return code;
794
795        conn->bits.tcpconnect[sockindex] = TRUE;
796
797        *connected = TRUE;
798        if(sockindex == FIRSTSOCKET)
799          Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
800        Curl_updateconninfo(conn, conn->sock[sockindex]);
801        Curl_verboseconnect(conn);
802
803        return CURLE_OK;
804      }
805      else
806        infof(data, "Connection failed\n");
807    }
808    else if(result & CURL_CSELECT_ERR)
809      (void)verifyconnect(conn->tempsock[i], &error);
810
811    /*
812     * The connection failed here, we should attempt to connect to the "next
813     * address" for the given host. But first remember the latest error.
814     */
815    if(error) {
816      char ipaddress[MAX_IPADR_LEN];
817      data->state.os_errno = error;
818      SET_SOCKERRNO(error);
819      if(conn->tempaddr[i]) {
820        Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
821        infof(data, "connect to %s port %ld failed: %s\n",
822              ipaddress, conn->port, Curl_strerror(conn, error));
823
824        conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
825                                   allow : allow / 2;
826
827        code = trynextip(conn, sockindex, i);
828      }
829    }
830  }
831
832  if(code) {
833    /* no more addresses to try */
834
835    /* if the first address family runs out of addresses to try before
836       the happy eyeball timeout, go ahead and try the next family now */
837    if(conn->tempaddr[1] == NULL) {
838      int rc;
839      rc = trynextip(conn, sockindex, 1);
840      if(rc == CURLE_OK)
841        return CURLE_OK;
842    }
843
844    failf(data, "Failed to connect to %s port %ld: %s",
845          conn->bits.proxy?conn->proxy.name:conn->host.name,
846          conn->port, Curl_strerror(conn, error));
847  }
848
849  return code;
850}
851
852static void tcpnodelay(struct connectdata *conn,
853                       curl_socket_t sockfd)
854{
855#ifdef TCP_NODELAY
856  struct SessionHandle *data= conn->data;
857  curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
858  int level = IPPROTO_TCP;
859
860#if 0
861  /* The use of getprotobyname() is disabled since it isn't thread-safe on
862     numerous systems. On these getprotobyname_r() should be used instead, but
863     that exists in at least one 4 arg version and one 5 arg version, and
864     since the proto number rarely changes anyway we now just use the hard
865     coded number. The "proper" fix would need a configure check for the
866     correct function much in the same style the gethostbyname_r versions are
867     detected. */
868  struct protoent *pe = getprotobyname("tcp");
869  if(pe)
870    level = pe->p_proto;
871#endif
872
873  if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
874                sizeof(onoff)) < 0)
875    infof(data, "Could not set TCP_NODELAY: %s\n",
876          Curl_strerror(conn, SOCKERRNO));
877  else
878    infof(data,"TCP_NODELAY set\n");
879#else
880  (void)conn;
881  (void)sockfd;
882#endif
883}
884
885#ifdef SO_NOSIGPIPE
886/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
887   sending data to a dead peer (instead of relying on the 4th argument to send
888   being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
889   systems? */
890static void nosigpipe(struct connectdata *conn,
891                      curl_socket_t sockfd)
892{
893  struct SessionHandle *data= conn->data;
894  int onoff = 1;
895  if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
896                sizeof(onoff)) < 0)
897    infof(data, "Could not set SO_NOSIGPIPE: %s\n",
898          Curl_strerror(conn, SOCKERRNO));
899}
900#else
901#define nosigpipe(x,y) Curl_nop_stmt
902#endif
903
904#ifdef USE_WINSOCK
905/* When you run a program that uses the Windows Sockets API, you may
906   experience slow performance when you copy data to a TCP server.
907
908   http://support.microsoft.com/kb/823764
909
910   Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
911   Buffer Size
912
913   The problem described in this knowledge-base is applied only to pre-Vista
914   Windows.  Following function trying to detect OS version and skips
915   SO_SNDBUF adjustment for Windows Vista and above.
916*/
917#define DETECT_OS_NONE 0
918#define DETECT_OS_PREVISTA 1
919#define DETECT_OS_VISTA_OR_LATER 2
920
921void Curl_sndbufset(curl_socket_t sockfd)
922{
923  int val = CURL_MAX_WRITE_SIZE + 32;
924  int curval = 0;
925  int curlen = sizeof(curval);
926  DWORD majorVersion = 6;
927
928  static int detectOsState = DETECT_OS_NONE;
929
930  if(detectOsState == DETECT_OS_NONE) {
931#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
932    (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
933    OSVERSIONINFO osver;
934
935    memset(&osver, 0, sizeof(osver));
936    osver.dwOSVersionInfoSize = sizeof(osver);
937
938    detectOsState = DETECT_OS_PREVISTA;
939    if(GetVersionEx(&osver)) {
940      if(osver.dwMajorVersion >= majorVersion)
941        detectOsState = DETECT_OS_VISTA_OR_LATER;
942    }
943#else
944    ULONGLONG majorVersionMask;
945    OSVERSIONINFOEX osver;
946
947    memset(&osver, 0, sizeof(osver));
948    osver.dwOSVersionInfoSize = sizeof(osver);
949    osver.dwMajorVersion = majorVersion;
950    majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION,
951                                           VER_GREATER_EQUAL);
952
953    if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask))
954      detectOsState = DETECT_OS_VISTA_OR_LATER;
955    else
956      detectOsState = DETECT_OS_PREVISTA;
957#endif
958  }
959
960  if(detectOsState == DETECT_OS_VISTA_OR_LATER)
961    return;
962
963  if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
964    if(curval > val)
965      return;
966
967  setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
968}
969#endif
970
971/*
972 * singleipconnect()
973 *
974 * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
975 * CURL_SOCKET_BAD. Other errors will however return proper errors.
976 *
977 * singleipconnect() connects to the given IP only, and it may return without
978 * having connected.
979 */
980static CURLcode
981singleipconnect(struct connectdata *conn,
982                const Curl_addrinfo *ai,
983                curl_socket_t *sockp)
984{
985  struct Curl_sockaddr_ex addr;
986  int rc;
987  int error = 0;
988  bool isconnected = FALSE;
989  struct SessionHandle *data = conn->data;
990  curl_socket_t sockfd;
991  CURLcode res = CURLE_OK;
992  char ipaddress[MAX_IPADR_LEN];
993  long port;
994
995  *sockp = CURL_SOCKET_BAD;
996
997  res = Curl_socket(conn, ai, &addr, &sockfd);
998  if(res)
999    /* Failed to create the socket, but still return OK since we signal the
1000       lack of socket as well. This allows the parent function to keep looping
1001       over alternative addresses/socket families etc. */
1002    return CURLE_OK;
1003
1004  /* store remote address and port used in this connection attempt */
1005  if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
1006                     ipaddress, &port)) {
1007    /* malformed address or bug in inet_ntop, try next address */
1008    error = ERRNO;
1009    failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
1010          error, Curl_strerror(conn, error));
1011    Curl_closesocket(conn, sockfd);
1012    return CURLE_OK;
1013  }
1014  infof(data, "  Trying %s...\n", ipaddress);
1015
1016  if(data->set.tcp_nodelay)
1017    tcpnodelay(conn, sockfd);
1018
1019  nosigpipe(conn, sockfd);
1020
1021  Curl_sndbufset(sockfd);
1022
1023  if(data->set.tcp_keepalive)
1024    tcpkeepalive(data, sockfd);
1025
1026  if(data->set.fsockopt) {
1027    /* activate callback for setting socket options */
1028    error = data->set.fsockopt(data->set.sockopt_client,
1029                               sockfd,
1030                               CURLSOCKTYPE_IPCXN);
1031
1032    if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
1033      isconnected = TRUE;
1034    else if(error) {
1035      Curl_closesocket(conn, sockfd); /* close the socket and bail out */
1036      return CURLE_ABORTED_BY_CALLBACK;
1037    }
1038  }
1039
1040  /* possibly bind the local end to an IP, interface or port */
1041  res = bindlocal(conn, sockfd, addr.family);
1042  if(res) {
1043    Curl_closesocket(conn, sockfd); /* close socket and bail out */
1044    if(res == CURLE_UNSUPPORTED_PROTOCOL) {
1045      /* The address family is not supported on this interface.
1046         We can continue trying addresses */
1047      return CURLE_OK;
1048    }
1049    return res;
1050  }
1051
1052  /* set socket non-blocking */
1053  curlx_nonblock(sockfd, TRUE);
1054
1055  conn->connecttime = Curl_tvnow();
1056  if(conn->num_addr > 1)
1057    Curl_expire(data, conn->timeoutms_per_addr);
1058
1059  /* Connect TCP sockets, bind UDP */
1060  if(!isconnected && (conn->socktype == SOCK_STREAM)) {
1061    rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
1062    if(-1 == rc)
1063      error = SOCKERRNO;
1064  }
1065  else {
1066    *sockp = sockfd;
1067    return CURLE_OK;
1068  }
1069
1070#ifdef ENABLE_IPV6
1071  conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
1072#endif
1073
1074  if(-1 == rc) {
1075    switch(error) {
1076    case EINPROGRESS:
1077    case EWOULDBLOCK:
1078#if defined(EAGAIN)
1079#if (EAGAIN) != (EWOULDBLOCK)
1080      /* On some platforms EAGAIN and EWOULDBLOCK are the
1081       * same value, and on others they are different, hence
1082       * the odd #if
1083       */
1084    case EAGAIN:
1085#endif
1086#endif
1087      res = CURLE_OK;
1088      break;
1089
1090    default:
1091      /* unknown error, fallthrough and try another address! */
1092      infof(data, "Immediate connect fail for %s: %s\n",
1093            ipaddress, Curl_strerror(conn,error));
1094      data->state.os_errno = error;
1095
1096      /* connect failed */
1097      Curl_closesocket(conn, sockfd);
1098      res = CURLE_COULDNT_CONNECT;
1099    }
1100  }
1101
1102  if(!res)
1103    *sockp = sockfd;
1104
1105  return res;
1106}
1107
1108/*
1109 * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1110 * There might be more than one IP address to try out. Fill in the passed
1111 * pointer with the connected socket.
1112 */
1113
1114CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
1115                          const struct Curl_dns_entry *remotehost)
1116{
1117  struct SessionHandle *data = conn->data;
1118  struct timeval before = Curl_tvnow();
1119  CURLcode res = CURLE_COULDNT_CONNECT;
1120
1121  long timeout_ms = Curl_timeleft(data, &before, TRUE);
1122
1123  if(timeout_ms < 0) {
1124    /* a precaution, no need to continue if time already is up */
1125    failf(data, "Connection time-out");
1126    return CURLE_OPERATION_TIMEDOUT;
1127  }
1128
1129  conn->num_addr = Curl_num_addresses(remotehost->addr);
1130  conn->tempaddr[0] = remotehost->addr;
1131  conn->tempaddr[1] = NULL;
1132  conn->tempsock[0] = CURL_SOCKET_BAD;
1133  conn->tempsock[1] = CURL_SOCKET_BAD;
1134  Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
1135
1136  /* Max time for the next connection attempt */
1137  conn->timeoutms_per_addr =
1138    conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
1139
1140  /* start connecting to first IP */
1141  while(conn->tempaddr[0]) {
1142    res = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
1143    if(res == CURLE_OK)
1144        break;
1145    conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
1146  }
1147
1148  if(conn->tempsock[0] == CURL_SOCKET_BAD)
1149    return res;
1150
1151  data->info.numconnects++; /* to track the number of connections made */
1152
1153  return CURLE_OK;
1154}
1155
1156struct connfind {
1157  struct connectdata *tofind;
1158  bool found;
1159};
1160
1161static int conn_is_conn(struct connectdata *conn, void *param)
1162{
1163  struct connfind *f = (struct connfind *)param;
1164  if(conn == f->tofind) {
1165    f->found = TRUE;
1166    return 1;
1167  }
1168  return 0;
1169}
1170
1171/*
1172 * Used to extract socket and connectdata struct for the most recent
1173 * transfer on the given SessionHandle.
1174 *
1175 * The returned socket will be CURL_SOCKET_BAD in case of failure!
1176 */
1177curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
1178                                  struct connectdata **connp)
1179{
1180  curl_socket_t sockfd;
1181
1182  DEBUGASSERT(data);
1183
1184  /* this only works for an easy handle that has been used for
1185     curl_easy_perform()! */
1186  if(data->state.lastconnect && data->multi_easy) {
1187    struct connectdata *c = data->state.lastconnect;
1188    struct connfind find;
1189    find.tofind = data->state.lastconnect;
1190    find.found = FALSE;
1191
1192    Curl_conncache_foreach(data->multi_easy->conn_cache, &find, conn_is_conn);
1193
1194    if(!find.found) {
1195      data->state.lastconnect = NULL;
1196      return CURL_SOCKET_BAD;
1197    }
1198
1199    if(connp)
1200      /* only store this if the caller cares for it */
1201      *connp = c;
1202    sockfd = c->sock[FIRSTSOCKET];
1203    /* we have a socket connected, let's determine if the server shut down */
1204    /* determine if ssl */
1205    if(c->ssl[FIRSTSOCKET].use) {
1206      /* use the SSL context */
1207      if(!Curl_ssl_check_cxn(c))
1208        return CURL_SOCKET_BAD;   /* FIN received */
1209    }
1210/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1211#ifdef MSG_PEEK
1212    else {
1213      /* use the socket */
1214      char buf;
1215      if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1216              (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
1217        return CURL_SOCKET_BAD;   /* FIN received */
1218      }
1219    }
1220#endif
1221  }
1222  else
1223    return CURL_SOCKET_BAD;
1224
1225  return sockfd;
1226}
1227
1228/*
1229 * Close a socket.
1230 *
1231 * 'conn' can be NULL, beware!
1232 */
1233int Curl_closesocket(struct connectdata *conn,
1234                      curl_socket_t sock)
1235{
1236  if(conn && conn->fclosesocket) {
1237    if((sock == conn->sock[SECONDARYSOCKET]) &&
1238       conn->sock_accepted[SECONDARYSOCKET])
1239      /* if this socket matches the second socket, and that was created with
1240         accept, then we MUST NOT call the callback but clear the accepted
1241         status */
1242      conn->sock_accepted[SECONDARYSOCKET] = FALSE;
1243    else
1244      return conn->fclosesocket(conn->closesocket_client, sock);
1245  }
1246  sclose(sock);
1247
1248  if(conn)
1249    /* tell the multi-socket code about this */
1250    Curl_multi_closed(conn, sock);
1251
1252  return 0;
1253}
1254
1255/*
1256 * Create a socket based on info from 'conn' and 'ai'.
1257 *
1258 * 'addr' should be a pointer to the correct struct to get data back, or NULL.
1259 * 'sockfd' must be a pointer to a socket descriptor.
1260 *
1261 * If the open socket callback is set, used that!
1262 *
1263 */
1264CURLcode Curl_socket(struct connectdata *conn,
1265                     const Curl_addrinfo *ai,
1266                     struct Curl_sockaddr_ex *addr,
1267                     curl_socket_t *sockfd)
1268{
1269  struct SessionHandle *data = conn->data;
1270  struct Curl_sockaddr_ex dummy;
1271
1272  if(!addr)
1273    /* if the caller doesn't want info back, use a local temp copy */
1274    addr = &dummy;
1275
1276  /*
1277   * The Curl_sockaddr_ex structure is basically libcurl's external API
1278   * curl_sockaddr structure with enough space available to directly hold
1279   * any protocol-specific address structures. The variable declared here
1280   * will be used to pass / receive data to/from the fopensocket callback
1281   * if this has been set, before that, it is initialized from parameters.
1282   */
1283
1284  addr->family = ai->ai_family;
1285  addr->socktype = conn->socktype;
1286  addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
1287  addr->addrlen = ai->ai_addrlen;
1288
1289  if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
1290     addr->addrlen = sizeof(struct Curl_sockaddr_storage);
1291  memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
1292
1293  if(data->set.fopensocket)
1294   /*
1295    * If the opensocket callback is set, all the destination address
1296    * information is passed to the callback. Depending on this information the
1297    * callback may opt to abort the connection, this is indicated returning
1298    * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
1299    * the callback returns a valid socket the destination address information
1300    * might have been changed and this 'new' address will actually be used
1301    * here to connect.
1302    */
1303    *sockfd = data->set.fopensocket(data->set.opensocket_client,
1304                                    CURLSOCKTYPE_IPCXN,
1305                                    (struct curl_sockaddr *)addr);
1306  else
1307    /* opensocket callback not set, so simply create the socket now */
1308    *sockfd = socket(addr->family, addr->socktype, addr->protocol);
1309
1310  if(*sockfd == CURL_SOCKET_BAD)
1311    /* no socket, no connection */
1312    return CURLE_COULDNT_CONNECT;
1313
1314#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
1315  if(conn->scope && (addr->family == AF_INET6)) {
1316    struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
1317    sa6->sin6_scope_id = conn->scope;
1318  }
1319#endif
1320
1321  return CURLE_OK;
1322
1323}
1324
1325#ifdef CURLDEBUG
1326/*
1327 * Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
1328 * MUST be called with the connclose() or connclose() macros with a stated
1329 * reason. The reason is only shown in debug builds but helps to figure out
1330 * decision paths when connections are or aren't re-used as expected.
1331 */
1332void Curl_conncontrol(struct connectdata *conn, bool closeit,
1333                      const char *reason)
1334{
1335  infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
1336        reason);
1337  conn->bits.close = closeit; /* the only place in the source code that should
1338                                 assign this bit */
1339}
1340#endif
1341