Commit 72dbe9da authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

praise Bjorn Reese for mastering these dusty corners of socket hacking, now

we check for the error state before believing we are connected in IPv6
cases
parent dd028817
Loading
Loading
Loading
Loading
+52 −30
Original line number Diff line number Diff line
@@ -72,6 +72,16 @@
#include "memdebug.h"
#endif

static
int geterrno(void)
{
#ifdef WIN32
  return (int)GetLastError();
#else
  return errno;
#endif
}

/*************************************************************************
 * Curl_nonblock
 *
@@ -300,6 +310,19 @@ static CURLcode bindlocal(struct connectdata *conn,
}
#endif /* end of ipv4-specific section */

static
int socketerror(int sockfd)
{
  int err = 0;
  socklen_t errSize = sizeof(err);

  if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
                       (void *)&err, &errSize))
    err = geterrno();
  
  return err;
}

/*
 * TCP connect to the given host with timeout, proxy or remote doesn't matter.
 * There might be more than one IP address to try out. Fill in the passed
@@ -355,6 +378,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
   */
  {
    struct addrinfo *ai;
    port =0; /* prevent compiler warning */

    for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) {
      sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
@@ -367,12 +391,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
      rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);

      if(-1 == rc) {
        int error;
#ifdef WIN32
        error = (int)GetLastError();
#else
        error = errno;
#endif
        int error=geterrno();

        switch (error) {
        case EINPROGRESS:
        case EWOULDBLOCK:
@@ -391,15 +411,22 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
        case ECONNREFUSED: /* no one listening */
        default:
          /* unknown error, fallthrough and try another address! */
          failf(data, "Failed to connect to IP number %d", aliasindex+1);
          failf(data, "Failed to connect");
          break;
        }
      }
      if(0 == rc)
        /* direct connect, awesome! */
      if(0 == rc) {
        /* we might be connected, if the socket says it is OK! Ask it! */
        int err;

        err = socketerror(sockfd);
        if ((0 == err) || (EISCONN == err)) {
          /* we are connected, awesome! */
          break;
	}
        /* we are _not_ connected, it was a false alert, continue please */
      }

      else {
      /* connect failed or timed out */
      sclose(sockfd);
      sockfd = -1;
@@ -414,7 +441,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
      before = after;
      continue;
    }
    }
    if (sockfd < 0) {
      failf(data, "connect() failed");
      return CURLE_COULDNT_CONNECT;
@@ -466,12 +492,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
                 sizeof(serv_addr));

    if(-1 == rc) {
      int error;
#ifdef WIN32
      error = (int)GetLastError();
#else
      error = errno;
#endif
      int error=geterrno();

      switch (error) {
      case EINPROGRESS:
      case EWOULDBLOCK: