1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2011, 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 "setup.h"
24
25#ifdef HAVE_SYS_SOCKET_H
26#include <sys/socket.h>
27#endif
28#ifdef HAVE_NETINET_IN_H
29#include <netinet/in.h> /* <netinet/tcp.h> may need it */
30#endif
31#ifdef HAVE_SYS_UN_H
32#include <sys/un.h> /* for sockaddr_un */
33#endif
34#ifdef HAVE_NETINET_TCP_H
35#include <netinet/tcp.h> /* for TCP_NODELAY */
36#endif
37#ifdef HAVE_SYS_IOCTL_H
38#include <sys/ioctl.h>
39#endif
40#ifdef HAVE_UNISTD_H
41#include <unistd.h>
42#endif
43#ifdef HAVE_NETDB_H
44#include <netdb.h>
45#endif
46#ifdef HAVE_FCNTL_H
47#include <fcntl.h>
48#endif
49#ifdef HAVE_ARPA_INET_H
50#include <arpa/inet.h>
51#endif
52
53#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
54#include <sys/filio.h>
55#endif
56#ifdef NETWARE
57#undef in_addr_t
58#define in_addr_t unsigned long
59#endif
60#ifdef __VMS
61#include <in.h>
62#include <inet.h>
63#endif
64
65#define _MPRINTF_REPLACE /* use our functions only */
66#include <curl/mprintf.h>
67
68#include "urldata.h"
69#include "sendf.h"
70#include "if2ip.h"
71#include "strerror.h"
72#include "connect.h"
73#include "curl_memory.h"
74#include "select.h"
75#include "url.h" /* for Curl_safefree() */
76#include "multiif.h"
77#include "sockaddr.h" /* required for Curl_sockaddr_storage */
78#include "inet_ntop.h"
79#include "inet_pton.h"
80#include "sslgen.h" /* for Curl_ssl_check_cxn() */
81#include "progress.h"
82#include "warnless.h"
83
84/* The last #include file should be: */
85#include "memdebug.h"
86
87#ifdef __SYMBIAN32__
88/* This isn't actually supported under Symbian OS */
89#undef SO_NOSIGPIPE
90#endif
91
92struct Curl_sockaddr_ex {
93  int family;
94  int socktype;
95  int protocol;
96  unsigned int addrlen;
97  union {
98    struct sockaddr addr;
99    struct Curl_sockaddr_storage buff;
100  } _sa_ex_u;
101};
102#define sa_addr _sa_ex_u.addr
103
104static bool verifyconnect(curl_socket_t sockfd, int *error);
105
106static CURLcode
107singleipconnect(struct connectdata *conn,
108                const Curl_addrinfo *ai, /* start connecting to this */
109                long timeout_ms,
110                curl_socket_t *sock,
111                bool *connected);
112
113/*
114 * Curl_timeleft() returns the amount of milliseconds left allowed for the
115 * transfer/connection. If the value is negative, the timeout time has already
116 * elapsed.
117 *
118 * The start time is stored in progress.t_startsingle - as set with
119 * Curl_pgrsTime(..., TIMER_STARTSINGLE);
120 *
121 * If 'nowp' is non-NULL, it points to the current time.
122 * 'duringconnect' is FALSE if not during a connect, as then of course the
123 * connect timeout is not taken into account!
124 *
125 * @unittest: 1303
126 */
127long Curl_timeleft(struct SessionHandle *data,
128                   struct timeval *nowp,
129                   bool duringconnect)
130{
131  int timeout_set = 0;
132  long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
133  struct timeval now;
134
135  /* if a timeout is set, use the most restrictive one */
136
137  if(data->set.timeout > 0)
138    timeout_set |= 1;
139  if(duringconnect && (data->set.connecttimeout > 0))
140    timeout_set |= 2;
141
142  switch (timeout_set) {
143  case 1:
144    timeout_ms = data->set.timeout;
145    break;
146  case 2:
147    timeout_ms = data->set.connecttimeout;
148    break;
149  case 3:
150    if(data->set.timeout < data->set.connecttimeout)
151      timeout_ms = data->set.timeout;
152    else
153      timeout_ms = data->set.connecttimeout;
154    break;
155  default:
156    /* use the default */
157    if(!duringconnect)
158      /* if we're not during connect, there's no default timeout so if we're
159         at zero we better just return zero and not make it a negative number
160         by the math below */
161      return 0;
162    break;
163  }
164
165  if(!nowp) {
166    now = Curl_tvnow();
167    nowp = &now;
168  }
169
170  /* subtract elapsed time */
171  timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
172  if(!timeout_ms)
173    /* avoid returning 0 as that means no timeout! */
174    return -1;
175
176  return timeout_ms;
177}
178
179/*
180 * waitconnect() waits for a TCP connect on the given socket for the specified
181 * number if milliseconds. It returns:
182 */
183
184#define WAITCONN_CONNECTED     0
185#define WAITCONN_SELECT_ERROR -1
186#define WAITCONN_TIMEOUT       1
187#define WAITCONN_FDSET_ERROR   2
188#define WAITCONN_ABORTED       3
189
190static
191int waitconnect(struct connectdata *conn,
192                curl_socket_t sockfd, /* socket */
193                long timeout_msec)
194{
195  int rc;
196#ifdef mpeix
197  /* Call this function once now, and ignore the results. We do this to
198     "clear" the error state on the socket so that we can later read it
199     reliably. This is reported necessary on the MPE/iX operating system. */
200  (void)verifyconnect(sockfd, NULL);
201#endif
202
203  for(;;) {
204
205    /* now select() until we get connect or timeout */
206    rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, timeout_msec>1000?
207                           1000:timeout_msec);
208    if(Curl_pgrsUpdate(conn))
209      return WAITCONN_ABORTED;
210
211    if(-1 == rc)
212      /* error, no connect here, try next */
213      return WAITCONN_SELECT_ERROR;
214
215    else if(0 == rc) {
216      /* timeout */
217      timeout_msec -= 1000;
218      if(timeout_msec <= 0)
219        return WAITCONN_TIMEOUT;
220
221      continue;
222    }
223
224    if(rc & CURL_CSELECT_ERR)
225      /* error condition caught */
226      return WAITCONN_FDSET_ERROR;
227
228    break;
229  }
230  return WAITCONN_CONNECTED;
231}
232
233static CURLcode bindlocal(struct connectdata *conn,
234                          curl_socket_t sockfd, int af)
235{
236  struct SessionHandle *data = conn->data;
237
238  struct Curl_sockaddr_storage sa;
239  struct sockaddr *sock = (struct sockaddr *)&sa;  /* bind to this address */
240  curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
241  struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
242#ifdef ENABLE_IPV6
243  struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
244#endif
245
246  struct Curl_dns_entry *h=NULL;
247  unsigned short port = data->set.localport; /* use this port number, 0 for
248                                                "random" */
249  /* how many port numbers to try to bind to, increasing one at a time */
250  int portnum = data->set.localportrange;
251  const char *dev = data->set.str[STRING_DEVICE];
252  int error;
253  char myhost[256] = "";
254  int done = 0; /* -1 for error, 1 for address found */
255
256  /*************************************************************
257   * Select device to bind socket to
258   *************************************************************/
259  if(!dev && !port)
260    /* no local kind of binding was requested */
261    return CURLE_OK;
262
263  memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
264
265  if(dev && (strlen(dev)<255) ) {
266
267    /* interface */
268    if(Curl_if2ip(af, dev, myhost, sizeof(myhost))) {
269      /*
270       * We now have the numerical IP address in the 'myhost' buffer
271       */
272      infof(data, "Local Interface %s is ip %s using address family %i\n",
273            dev, myhost, af);
274      done = 1;
275
276#ifdef SO_BINDTODEVICE
277      /* I am not sure any other OSs than Linux that provide this feature, and
278       * at the least I cannot test. --Ben
279       *
280       * This feature allows one to tightly bind the local socket to a
281       * particular interface.  This will force even requests to other local
282       * interfaces to go out the external interface.
283       *
284       *
285       * Only bind to the interface when specified as interface, not just as a
286       * hostname or ip address.
287       */
288      if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
289                    dev, (curl_socklen_t)strlen(dev)+1) != 0) {
290        error = SOCKERRNO;
291        infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
292              " will do regular bind\n",
293              dev, error, Curl_strerror(conn, error));
294        /* This is typically "errno 1, error: Operation not permitted" if
295           you're not running as root or another suitable privileged user */
296      }
297#endif
298    }
299    else {
300      /*
301       * This was not an interface, resolve the name as a host name
302       * or IP number
303       *
304       * Temporarily force name resolution to use only the address type
305       * of the connection. The resolve functions should really be changed
306       * to take a type parameter instead.
307       */
308      long ipver = conn->ip_version;
309      int rc;
310
311      if(af == AF_INET)
312        conn->ip_version = CURL_IPRESOLVE_V4;
313#ifdef ENABLE_IPV6
314      else if(af == AF_INET6)
315        conn->ip_version = CURL_IPRESOLVE_V6;
316#endif
317
318      rc = Curl_resolv(conn, dev, 0, &h);
319      if(rc == CURLRESOLV_PENDING)
320        (void)Curl_resolver_wait_resolv(conn, &h);
321      conn->ip_version = ipver;
322
323      if(h) {
324        /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
325        Curl_printable_address(h->addr, myhost, sizeof(myhost));
326        infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
327              dev, af, myhost, h->addr->ai_family);
328        Curl_resolv_unlock(data, h);
329        done = 1;
330      }
331      else {
332        /*
333         * provided dev was no interface (or interfaces are not supported
334         * e.g. solaris) no ip address and no domain we fail here
335         */
336        done = -1;
337      }
338    }
339
340    if(done > 0) {
341#ifdef ENABLE_IPV6
342      /* ipv6 address */
343      if((af == AF_INET6) &&
344         (Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0)) {
345        si6->sin6_family = AF_INET6;
346        si6->sin6_port = htons(port);
347        sizeof_sa = sizeof(struct sockaddr_in6);
348      }
349      else
350#endif
351      /* ipv4 address */
352      if((af == AF_INET) &&
353         (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
354        si4->sin_family = AF_INET;
355        si4->sin_port = htons(port);
356        sizeof_sa = sizeof(struct sockaddr_in);
357      }
358    }
359
360    if(done < 1) {
361      failf(data, "Couldn't bind to '%s'", dev);
362      return CURLE_INTERFACE_FAILED;
363    }
364  }
365  else {
366    /* no device was given, prepare sa to match af's needs */
367#ifdef ENABLE_IPV6
368    if(af == AF_INET6) {
369      si6->sin6_family = AF_INET6;
370      si6->sin6_port = htons(port);
371      sizeof_sa = sizeof(struct sockaddr_in6);
372    }
373    else
374#endif
375    if(af == AF_INET) {
376      si4->sin_family = AF_INET;
377      si4->sin_port = htons(port);
378      sizeof_sa = sizeof(struct sockaddr_in);
379    }
380  }
381
382  for(;;) {
383    if(bind(sockfd, sock, sizeof_sa) >= 0) {
384      /* we succeeded to bind */
385      struct Curl_sockaddr_storage add;
386      curl_socklen_t size = sizeof(add);
387      memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
388      if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
389        data->state.os_errno = error = SOCKERRNO;
390        failf(data, "getsockname() failed with errno %d: %s",
391              error, Curl_strerror(conn, error));
392        return CURLE_INTERFACE_FAILED;
393      }
394      infof(data, "Local port: %hu\n", port);
395      conn->bits.bound = TRUE;
396      return CURLE_OK;
397    }
398
399    if(--portnum > 0) {
400      infof(data, "Bind to local port %hu failed, trying next\n", port);
401      port++; /* try next port */
402      /* We re-use/clobber the port variable here below */
403      if(sock->sa_family == AF_INET)
404        si4->sin_port = ntohs(port);
405#ifdef ENABLE_IPV6
406      else
407        si6->sin6_port = ntohs(port);
408#endif
409    }
410    else
411      break;
412  }
413
414  data->state.os_errno = error = SOCKERRNO;
415  failf(data, "bind failed with errno %d: %s",
416        error, Curl_strerror(conn, error));
417
418  return CURLE_INTERFACE_FAILED;
419}
420
421/*
422 * verifyconnect() returns TRUE if the connect really has happened.
423 */
424static bool verifyconnect(curl_socket_t sockfd, int *error)
425{
426  bool rc = TRUE;
427#ifdef SO_ERROR
428  int err = 0;
429  curl_socklen_t errSize = sizeof(err);
430
431#ifdef WIN32
432  /*
433   * In October 2003 we effectively nullified this function on Windows due to
434   * problems with it using all CPU in multi-threaded cases.
435   *
436   * In May 2004, we bring it back to offer more info back on connect failures.
437   * Gisle Vanem could reproduce the former problems with this function, but
438   * could avoid them by adding this SleepEx() call below:
439   *
440   *    "I don't have Rational Quantify, but the hint from his post was
441   *    ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
442   *    just Sleep(0) would be enough?) would release whatever
443   *    mutex/critical-section the ntdll call is waiting on.
444   *
445   *    Someone got to verify this on Win-NT 4.0, 2000."
446   */
447
448#ifdef _WIN32_WCE
449  Sleep(0);
450#else
451  SleepEx(0, FALSE);
452#endif
453
454#endif
455
456  if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
457    err = SOCKERRNO;
458#ifdef _WIN32_WCE
459  /* Old WinCE versions don't support SO_ERROR */
460  if(WSAENOPROTOOPT == err) {
461    SET_SOCKERRNO(0);
462    err = 0;
463  }
464#endif
465#ifdef __minix
466  /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
467  if(EBADIOCTL == err) {
468    SET_SOCKERRNO(0);
469    err = 0;
470  }
471#endif
472  if((0 == err) || (EISCONN == err))
473    /* we are connected, awesome! */
474    rc = TRUE;
475  else
476    /* This wasn't a successful connect */
477    rc = FALSE;
478  if(error)
479    *error = err;
480#else
481  (void)sockfd;
482  if(error)
483    *error = SOCKERRNO;
484#endif
485  return rc;
486}
487
488/* Used within the multi interface. Try next IP address, return TRUE if no
489   more address exists or error */
490static CURLcode trynextip(struct connectdata *conn,
491                          int sockindex,
492                          bool *connected)
493{
494  curl_socket_t sockfd;
495  Curl_addrinfo *ai;
496
497  /* First clean up after the failed socket.
498     Don't close it yet to ensure that the next IP's socket gets a different
499     file descriptor, which can prevent bugs when the curl_multi_socket_action
500     interface is used with certain select() replacements such as kqueue. */
501  curl_socket_t fd_to_close = conn->sock[sockindex];
502  conn->sock[sockindex] = CURL_SOCKET_BAD;
503  *connected = FALSE;
504
505  if(sockindex != FIRSTSOCKET) {
506    Curl_closesocket(conn, fd_to_close);
507    return CURLE_COULDNT_CONNECT; /* no next */
508  }
509
510  /* try the next address */
511  ai = conn->ip_addr->ai_next;
512
513  while(ai) {
514    CURLcode res = singleipconnect(conn, ai, 0L, &sockfd, connected);
515    if(res)
516      return res;
517    if(sockfd != CURL_SOCKET_BAD) {
518      /* store the new socket descriptor */
519      conn->sock[sockindex] = sockfd;
520      conn->ip_addr = ai;
521      Curl_closesocket(conn, fd_to_close);
522      return CURLE_OK;
523    }
524    ai = ai->ai_next;
525  }
526  Curl_closesocket(conn, fd_to_close);
527  return CURLE_COULDNT_CONNECT;
528}
529
530/* Copies connection info into the session handle to make it available
531   when the session handle is no longer associated with a connection. */
532void Curl_persistconninfo(struct connectdata *conn)
533{
534  memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
535  memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
536  conn->data->info.conn_primary_port = conn->primary_port;
537  conn->data->info.conn_local_port = conn->local_port;
538}
539
540/* retrieves ip address and port from a sockaddr structure */
541static bool getaddressinfo(struct sockaddr* sa, char* addr,
542                           long* port)
543{
544  unsigned short us_port;
545  struct sockaddr_in* si = NULL;
546#ifdef ENABLE_IPV6
547  struct sockaddr_in6* si6 = NULL;
548#endif
549#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
550  struct sockaddr_un* su = NULL;
551#endif
552
553  switch (sa->sa_family) {
554    case AF_INET:
555      si = (struct sockaddr_in*) sa;
556      if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
557                        addr, MAX_IPADR_LEN)) {
558        us_port = ntohs(si->sin_port);
559        *port = us_port;
560        return TRUE;
561      }
562      break;
563#ifdef ENABLE_IPV6
564    case AF_INET6:
565      si6 = (struct sockaddr_in6*)sa;
566      if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
567                        addr, MAX_IPADR_LEN)) {
568        us_port = ntohs(si6->sin6_port);
569        *port = us_port;
570        return TRUE;
571      }
572      break;
573#endif
574#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
575    case AF_UNIX:
576      su = (struct sockaddr_un*)sa;
577      snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
578      *port = 0;
579      return TRUE;
580#endif
581    default:
582      break;
583  }
584
585  addr[0] = '\0';
586  *port = 0;
587
588  return FALSE;
589}
590
591/* retrieves the start/end point information of a socket of an established
592   connection */
593void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
594{
595  int error;
596  curl_socklen_t len;
597  struct Curl_sockaddr_storage ssrem;
598  struct Curl_sockaddr_storage ssloc;
599  struct SessionHandle *data = conn->data;
600
601  if(!conn->bits.reuse) {
602
603    len = sizeof(struct Curl_sockaddr_storage);
604    if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
605      error = SOCKERRNO;
606      failf(data, "getpeername() failed with errno %d: %s",
607            error, Curl_strerror(conn, error));
608      return;
609    }
610
611    len = sizeof(struct Curl_sockaddr_storage);
612    if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
613      error = SOCKERRNO;
614      failf(data, "getsockname() failed with errno %d: %s",
615            error, Curl_strerror(conn, error));
616      return;
617    }
618
619    if(!getaddressinfo((struct sockaddr*)&ssrem,
620                        conn->primary_ip, &conn->primary_port)) {
621      error = ERRNO;
622      failf(data, "ssrem inet_ntop() failed with errno %d: %s",
623            error, Curl_strerror(conn, error));
624      return;
625    }
626
627    if(!getaddressinfo((struct sockaddr*)&ssloc,
628                       conn->local_ip, &conn->local_port)) {
629      error = ERRNO;
630      failf(data, "ssloc inet_ntop() failed with errno %d: %s",
631            error, Curl_strerror(conn, error));
632      return;
633    }
634
635  }
636
637  /* persist connection info in session handle */
638  Curl_persistconninfo(conn);
639}
640
641/*
642 * Curl_is_connected() is used from the multi interface to check if the
643 * firstsocket has connected.
644 */
645
646CURLcode Curl_is_connected(struct connectdata *conn,
647                           int sockindex,
648                           bool *connected)
649{
650  int rc;
651  struct SessionHandle *data = conn->data;
652  CURLcode code = CURLE_OK;
653  curl_socket_t sockfd = conn->sock[sockindex];
654  long allow = DEFAULT_CONNECT_TIMEOUT;
655  int error = 0;
656  struct timeval now;
657
658  DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
659
660  *connected = FALSE; /* a very negative world view is best */
661
662  if(conn->bits.tcpconnect[sockindex]) {
663    /* we are connected already! */
664    *connected = TRUE;
665    return CURLE_OK;
666  }
667
668  now = Curl_tvnow();
669
670  /* figure out how long time we have left to connect */
671  allow = Curl_timeleft(data, &now, TRUE);
672
673  if(allow < 0) {
674    /* time-out, bail out, go home */
675    failf(data, "Connection time-out");
676    return CURLE_OPERATION_TIMEDOUT;
677  }
678
679  /* check for connect without timeout as we want to return immediately */
680  rc = waitconnect(conn, sockfd, 0);
681  if(WAITCONN_TIMEOUT == rc) {
682    if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
683      infof(data, "After %ldms connect time, move on!\n",
684            conn->timeoutms_per_addr);
685      goto next;
686    }
687
688    /* not an error, but also no connection yet */
689    return code;
690  }
691
692  if(WAITCONN_CONNECTED == rc) {
693    if(verifyconnect(sockfd, &error)) {
694      /* we are connected with TCP, awesome! */
695
696      /* see if we need to do any proxy magic first once we connected */
697      code = Curl_connected_proxy(conn);
698      if(code)
699        return code;
700
701      conn->bits.tcpconnect[sockindex] = TRUE;
702      *connected = TRUE;
703      if(sockindex == FIRSTSOCKET)
704        Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
705      Curl_verboseconnect(conn);
706      Curl_updateconninfo(conn, sockfd);
707
708      return CURLE_OK;
709    }
710    /* nope, not connected for real */
711  }
712  else {
713    /* nope, not connected  */
714    if(WAITCONN_FDSET_ERROR == rc) {
715      (void)verifyconnect(sockfd, &error);
716      infof(data, "%s\n",Curl_strerror(conn, error));
717    }
718    else
719      infof(data, "Connection failed\n");
720  }
721
722  /*
723   * The connection failed here, we should attempt to connect to the "next
724   * address" for the given host. But first remember the latest error.
725   */
726  if(error) {
727    data->state.os_errno = error;
728    SET_SOCKERRNO(error);
729  }
730  next:
731
732  code = trynextip(conn, sockindex, connected);
733
734  if(code) {
735    error = SOCKERRNO;
736    data->state.os_errno = error;
737    failf(data, "Failed connect to %s:%ld; %s",
738          conn->host.name, conn->port, Curl_strerror(conn, error));
739  }
740
741  return code;
742}
743
744static void tcpnodelay(struct connectdata *conn,
745                       curl_socket_t sockfd)
746{
747#ifdef TCP_NODELAY
748  struct SessionHandle *data= conn->data;
749  curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
750  int level = IPPROTO_TCP;
751
752#if 0
753  /* The use of getprotobyname() is disabled since it isn't thread-safe on
754     numerous systems. On these getprotobyname_r() should be used instead, but
755     that exists in at least one 4 arg version and one 5 arg version, and
756     since the proto number rarely changes anyway we now just use the hard
757     coded number. The "proper" fix would need a configure check for the
758     correct function much in the same style the gethostbyname_r versions are
759     detected. */
760  struct protoent *pe = getprotobyname("tcp");
761  if(pe)
762    level = pe->p_proto;
763#endif
764
765  if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
766                sizeof(onoff)) < 0)
767    infof(data, "Could not set TCP_NODELAY: %s\n",
768          Curl_strerror(conn, SOCKERRNO));
769  else
770    infof(data,"TCP_NODELAY set\n");
771#else
772  (void)conn;
773  (void)sockfd;
774#endif
775}
776
777#ifdef SO_NOSIGPIPE
778/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
779   sending data to a dead peer (instead of relying on the 4th argument to send
780   being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
781   systems? */
782static void nosigpipe(struct connectdata *conn,
783                      curl_socket_t sockfd)
784{
785  struct SessionHandle *data= conn->data;
786  int onoff = 1;
787  if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
788                sizeof(onoff)) < 0)
789    infof(data, "Could not set SO_NOSIGPIPE: %s\n",
790          Curl_strerror(conn, SOCKERRNO));
791}
792#else
793#define nosigpipe(x,y) Curl_nop_stmt
794#endif
795
796#ifdef USE_WINSOCK
797/* When you run a program that uses the Windows Sockets API, you may
798   experience slow performance when you copy data to a TCP server.
799
800   http://support.microsoft.com/kb/823764
801
802   Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
803   Buffer Size
804
805*/
806void Curl_sndbufset(curl_socket_t sockfd)
807{
808  int val = CURL_MAX_WRITE_SIZE + 32;
809  int curval = 0;
810  int curlen = sizeof(curval);
811
812  if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
813    if(curval > val)
814      return;
815
816  setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
817}
818#endif
819
820
821/*
822 * singleipconnect()
823 *
824 * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
825 * CURL_SOCKET_BAD. Other errors will however return proper errors.
826 *
827 * singleipconnect() connects to the given IP only, and it may return without
828 * having connected if used from the multi interface.
829 */
830static CURLcode
831singleipconnect(struct connectdata *conn,
832                const Curl_addrinfo *ai,
833                long timeout_ms,
834                curl_socket_t *sockp,
835                bool *connected)
836{
837  struct Curl_sockaddr_ex addr;
838  int rc;
839  int error = 0;
840  bool isconnected = FALSE;
841  struct SessionHandle *data = conn->data;
842  curl_socket_t sockfd;
843  CURLcode res = CURLE_OK;
844#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
845  struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr;
846#endif
847
848  *sockp = CURL_SOCKET_BAD;
849
850  /*
851   * The Curl_sockaddr_ex structure is basically libcurl's external API
852   * curl_sockaddr structure with enough space available to directly hold
853   * any protocol-specific address structures. The variable declared here
854   * will be used to pass / receive data to/from the fopensocket callback
855   * if this has been set, before that, it is initialized from parameters.
856   */
857
858  addr.family = ai->ai_family;
859  addr.socktype = conn->socktype;
860  addr.protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
861  addr.addrlen = ai->ai_addrlen;
862
863  if(addr.addrlen > sizeof(struct Curl_sockaddr_storage))
864     addr.addrlen = sizeof(struct Curl_sockaddr_storage);
865  memcpy(&addr.sa_addr, ai->ai_addr, addr.addrlen);
866
867  *connected = FALSE; /* default is not connected */
868
869  if(data->set.fopensocket)
870   /*
871    * If the opensocket callback is set, all the destination address
872    * information is passed to the callback. Depending on this information the
873    * callback may opt to abort the connection, this is indicated returning
874    * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
875    * the callback returns a valid socket the destination address information
876    * might have been changed and this 'new' address will actually be used
877    * here to connect.
878    */
879    sockfd = data->set.fopensocket(data->set.opensocket_client,
880                                   CURLSOCKTYPE_IPCXN,
881                                   (struct curl_sockaddr *)&addr);
882  else
883    /* opensocket callback not set, so simply create the socket now */
884    sockfd = socket(addr.family, addr.socktype, addr.protocol);
885
886  if(sockfd == CURL_SOCKET_BAD)
887    /* no socket, no connection */
888    return CURLE_OK;
889
890#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
891  if(conn->scope && (addr.family == AF_INET6))
892    sa6->sin6_scope_id = conn->scope;
893#endif
894
895  /* store remote address and port used in this connection attempt */
896  if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
897                     conn->primary_ip, &conn->primary_port)) {
898    /* malformed address or bug in inet_ntop, try next address */
899    error = ERRNO;
900    failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
901          error, Curl_strerror(conn, error));
902    Curl_closesocket(conn, sockfd);
903    return CURLE_OK;
904  }
905  memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
906  infof(data, "  Trying %s... ", conn->ip_addr_str);
907
908  Curl_persistconninfo(conn);
909
910  if(data->set.tcp_nodelay)
911    tcpnodelay(conn, sockfd);
912
913  nosigpipe(conn, sockfd);
914
915  Curl_sndbufset(sockfd);
916
917  if(data->set.fsockopt) {
918    /* activate callback for setting socket options */
919    error = data->set.fsockopt(data->set.sockopt_client,
920                               sockfd,
921                               CURLSOCKTYPE_IPCXN);
922
923    if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
924      isconnected = TRUE;
925    else if(error) {
926      Curl_closesocket(conn, sockfd); /* close the socket and bail out */
927      return CURLE_ABORTED_BY_CALLBACK;
928    }
929  }
930
931  /* possibly bind the local end to an IP, interface or port */
932  res = bindlocal(conn, sockfd, addr.family);
933  if(res) {
934    Curl_closesocket(conn, sockfd); /* close socket and bail out */
935    return res;
936  }
937
938  /* set socket non-blocking */
939  curlx_nonblock(sockfd, TRUE);
940
941  /* Connect TCP sockets, bind UDP */
942  if(!isconnected && (conn->socktype == SOCK_STREAM)) {
943    rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
944    if(-1 == rc)
945      error = SOCKERRNO;
946    conn->connecttime = Curl_tvnow();
947    if(conn->num_addr > 1)
948      Curl_expire(data, conn->timeoutms_per_addr);
949  }
950  else
951    rc = 0;
952
953  if(-1 == rc) {
954    switch (error) {
955    case EINPROGRESS:
956    case EWOULDBLOCK:
957#if defined(EAGAIN)
958#if (EAGAIN) != (EWOULDBLOCK)
959      /* On some platforms EAGAIN and EWOULDBLOCK are the
960       * same value, and on others they are different, hence
961       * the odd #if
962       */
963    case EAGAIN:
964#endif
965#endif
966      rc = waitconnect(conn, sockfd, timeout_ms);
967      if(WAITCONN_ABORTED == rc) {
968        Curl_closesocket(conn, sockfd);
969        return CURLE_ABORTED_BY_CALLBACK;
970      }
971      break;
972    default:
973      /* unknown error, fallthrough and try another address! */
974      failf(data, "Failed to connect to %s: %s",
975            conn->ip_addr_str, Curl_strerror(conn,error));
976      data->state.os_errno = error;
977      break;
978    }
979  }
980
981  /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from
982     connect(). We can be sure of this since connect() cannot return 1. */
983  if((WAITCONN_TIMEOUT == rc) &&
984     (data->state.used_interface == Curl_if_multi)) {
985    /* Timeout when running the multi interface */
986    *sockp = sockfd;
987    return CURLE_OK;
988  }
989
990  if(!isconnected)
991    isconnected = verifyconnect(sockfd, &error);
992
993  if(!rc && isconnected) {
994    /* we are connected, awesome! */
995    *connected = TRUE; /* this is a true connect */
996    infof(data, "connected\n");
997#ifdef ENABLE_IPV6
998    conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
999#endif
1000
1001    Curl_updateconninfo(conn, sockfd);
1002    *sockp = sockfd;
1003    return CURLE_OK;
1004  }
1005  else if(WAITCONN_TIMEOUT == rc)
1006    infof(data, "Timeout\n");
1007  else {
1008    data->state.os_errno = error;
1009    infof(data, "%s\n", Curl_strerror(conn, error));
1010  }
1011
1012  /* connect failed or timed out */
1013  Curl_closesocket(conn, sockfd);
1014
1015  return CURLE_OK;
1016}
1017
1018/*
1019 * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1020 * There might be more than one IP address to try out. Fill in the passed
1021 * pointer with the connected socket.
1022 */
1023
1024CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
1025                          const struct Curl_dns_entry *remotehost,
1026                          curl_socket_t *sockconn,   /* the connected socket */
1027                          Curl_addrinfo **addr,      /* the one we used */
1028                          bool *connected)           /* really connected? */
1029{
1030  struct SessionHandle *data = conn->data;
1031  curl_socket_t sockfd = CURL_SOCKET_BAD;
1032  int aliasindex;
1033  Curl_addrinfo *ai;
1034  Curl_addrinfo *curr_addr;
1035
1036  struct timeval after;
1037  struct timeval before = Curl_tvnow();
1038
1039  /*************************************************************
1040   * Figure out what maximum time we have left
1041   *************************************************************/
1042  long timeout_ms;
1043
1044  DEBUGASSERT(sockconn);
1045  *connected = FALSE; /* default to not connected */
1046
1047  /* get the timeout left */
1048  timeout_ms = Curl_timeleft(data, &before, TRUE);
1049
1050  if(timeout_ms < 0) {
1051    /* a precaution, no need to continue if time already is up */
1052    failf(data, "Connection time-out");
1053    return CURLE_OPERATION_TIMEDOUT;
1054  }
1055
1056  /* Max time for each address */
1057  conn->num_addr = Curl_num_addresses(remotehost->addr);
1058  conn->timeoutms_per_addr = timeout_ms / conn->num_addr;
1059
1060  ai = remotehost->addr;
1061
1062  /* Below is the loop that attempts to connect to all IP-addresses we
1063   * know for the given host. One by one until one IP succeeds.
1064   */
1065
1066  /*
1067   * Connecting with a Curl_addrinfo chain
1068   */
1069  for(curr_addr = ai, aliasindex=0; curr_addr;
1070      curr_addr = curr_addr->ai_next, aliasindex++) {
1071
1072    /* start connecting to the IP curr_addr points to */
1073    CURLcode res =
1074      singleipconnect(conn, curr_addr,
1075                      /* don't hang when doing multi */
1076                      (data->state.used_interface == Curl_if_multi)?0:
1077                      conn->timeoutms_per_addr, &sockfd, connected);
1078
1079    if(res)
1080      return res;
1081
1082    if(sockfd != CURL_SOCKET_BAD)
1083      break;
1084
1085    /* get a new timeout for next attempt */
1086    after = Curl_tvnow();
1087    timeout_ms -= Curl_tvdiff(after, before);
1088    if(timeout_ms < 0) {
1089      failf(data, "connect() timed out!");
1090      return CURLE_OPERATION_TIMEDOUT;
1091    }
1092    before = after;
1093  }  /* end of connect-to-each-address loop */
1094
1095  *sockconn = sockfd;    /* the socket descriptor we've connected */
1096
1097  if(sockfd == CURL_SOCKET_BAD) {
1098    /* no good connect was made */
1099    failf(data, "couldn't connect to host");
1100    return CURLE_COULDNT_CONNECT;
1101  }
1102
1103  /* leave the socket in non-blocking mode */
1104
1105  /* store the address we use */
1106  if(addr)
1107    *addr = curr_addr;
1108
1109  data->info.numconnects++; /* to track the number of connections made */
1110
1111  return CURLE_OK;
1112}
1113
1114/*
1115 * Used to extract socket and connectdata struct for the most recent
1116 * transfer on the given SessionHandle.
1117 *
1118 * The returned socket will be CURL_SOCKET_BAD in case of failure!
1119 */
1120curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
1121                                  struct connectdata **connp)
1122{
1123  curl_socket_t sockfd;
1124
1125  DEBUGASSERT(data);
1126
1127  if((data->state.lastconnect != -1) &&
1128     (data->state.connc->connects[data->state.lastconnect] != NULL)) {
1129    struct connectdata *c =
1130      data->state.connc->connects[data->state.lastconnect];
1131    if(connp)
1132      /* only store this if the caller cares for it */
1133      *connp = c;
1134    sockfd = c->sock[FIRSTSOCKET];
1135    /* we have a socket connected, let's determine if the server shut down */
1136    /* determine if ssl */
1137    if(c->ssl[FIRSTSOCKET].use) {
1138      /* use the SSL context */
1139      if(!Curl_ssl_check_cxn(c))
1140        return CURL_SOCKET_BAD;   /* FIN received */
1141    }
1142/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1143#ifdef MSG_PEEK
1144    else {
1145      /* use the socket */
1146      char buf;
1147      if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1148              (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
1149        return CURL_SOCKET_BAD;   /* FIN received */
1150      }
1151    }
1152#endif
1153  }
1154  else
1155    return CURL_SOCKET_BAD;
1156
1157  return sockfd;
1158}
1159
1160/*
1161 * Close a socket.
1162 *
1163 * 'conn' can be NULL, beware!
1164 */
1165int Curl_closesocket(struct connectdata *conn,
1166                     curl_socket_t sock)
1167{
1168  if(conn && conn->fclosesocket)
1169    return conn->fclosesocket(conn->closesocket_client, sock);
1170  else
1171    return sclose(sock);
1172}
1173