Test with IPv6 by default, and IPv4 only if that fails.

Change-Id: I1a17860245b7726a24576f5e1bddb0645171f28e
Reviewed-on: https://boringssl-review.googlesource.com/16486
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/bio/bio_test.cc b/crypto/bio/bio_test.cc
index beb182b..3d78635 100644
--- a/crypto/bio/bio_test.cc
+++ b/crypto/bio/bio_test.cc
@@ -69,31 +69,47 @@
 
 TEST(BIOTest, SocketConnect) {
   static const char kTestMessage[] = "test";
+  int listening_sock = -1;
+  socklen_t len = 0;
+  sockaddr_storage ss;
+  struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
+  struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
+  OPENSSL_memset(&ss, 0, sizeof(ss));
 
-  // Set up a listening socket on localhost.
-  int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
+  ss.ss_family = AF_INET6;
+  listening_sock = socket(AF_INET6, SOCK_STREAM, 0);
   ASSERT_NE(-1, listening_sock) << LastSocketError();
-  ScopedSocket listening_sock_closer(listening_sock);
+  len = sizeof(*sin6);
+  ASSERT_EQ(1, inet_pton(AF_INET6, "::1", &sin6->sin6_addr))
+      << LastSocketError();
+  if (bind(listening_sock, (struct sockaddr *)sin6, sizeof(*sin6)) == -1) {
+    closesocket(listening_sock);
 
-  struct sockaddr_in sin;
-  OPENSSL_memset(&sin, 0, sizeof(sin));
-  sin.sin_family = AF_INET;
-  ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr))
-      << LastSocketError();
-  ASSERT_EQ(0, bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)))
-      << LastSocketError();
+    ss.ss_family = AF_INET;
+    listening_sock = socket(AF_INET, SOCK_STREAM, 0);
+    ASSERT_NE(-1, listening_sock) << LastSocketError();
+    len = sizeof(*sin);
+    ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", &sin->sin_addr))
+        << LastSocketError();
+    ASSERT_EQ(0, bind(listening_sock, (struct sockaddr *)sin, sizeof(*sin)))
+        << LastSocketError();
+  }
+
+  ScopedSocket listening_sock_closer(listening_sock);
   ASSERT_EQ(0, listen(listening_sock, 1)) << LastSocketError();
-  socklen_t sockaddr_len = sizeof(sin);
-  ASSERT_EQ(0,
-            getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len))
-      << LastSocketError();
-  // The Android NDK, contrary to POSIX, makes |socklen_t| signed.
-  ASSERT_EQ(sizeof(sin), static_cast<size_t>(sockaddr_len));
+  ASSERT_EQ(0, getsockname(listening_sock, (struct sockaddr *)&ss, &len))
+        << LastSocketError();
+
+  char hostname[80];
+  if (ss.ss_family == AF_INET6) {
+    BIO_snprintf(hostname, sizeof(hostname), "[::1]:%d",
+                 ntohs(sin6->sin6_port));
+  } else if (ss.ss_family == AF_INET) {
+    BIO_snprintf(hostname, sizeof(hostname), "127.0.0.1:%d",
+                 ntohs(sin->sin_port));
+  }
 
   // Connect to it with a connect BIO.
-  char hostname[80];
-  BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
-               ntohs(sin.sin_port));
   bssl::UniquePtr<BIO> bio(BIO_new_connect(hostname));
   ASSERT_TRUE(bio);
 
@@ -102,7 +118,7 @@
             BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)));
 
   // Accept the socket.
-  int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
+  int sock = accept(listening_sock, (struct sockaddr *) &ss, &len);
   ASSERT_NE(-1, sock) << LastSocketError();
   ScopedSocket sock_closer(sock);
 
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 1542c3e..fc8e4a6 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -970,34 +970,51 @@
 // Connect returns a new socket connected to localhost on |port| or -1 on
 // error.
 static int Connect(uint16_t port) {
-  int sock = socket(AF_INET, SOCK_STREAM, 0);
-  if (sock == -1) {
-    PrintSocketError("socket");
-    return -1;
-  }
-  int nodelay = 1;
-  if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
-          reinterpret_cast<const char*>(&nodelay), sizeof(nodelay)) != 0) {
-    PrintSocketError("setsockopt");
+  for (int af : { AF_INET6, AF_INET }) {
+    int sock = socket(af, SOCK_STREAM, 0);
+    if (sock == -1) {
+      PrintSocketError("socket");
+      return -1;
+    }
+    int nodelay = 1;
+    if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+            reinterpret_cast<const char*>(&nodelay), sizeof(nodelay)) != 0) {
+      PrintSocketError("setsockopt");
+      closesocket(sock);
+      return -1;
+    }
+
+    sockaddr_storage ss;
+    OPENSSL_memset(&ss, 0, sizeof(ss));
+    ss.ss_family = af;
+    socklen_t len = 0;
+
+    if (af == AF_INET6) {
+      sockaddr_in6 *sin6 = (sockaddr_in6 *) &ss;
+      len = sizeof(*sin6);
+      sin6->sin6_port = htons(port);
+      if (!inet_pton(AF_INET6, "::1", &sin6->sin6_addr)) {
+        PrintSocketError("inet_pton");
+        closesocket(sock);
+        return -1;
+      }
+    } else if (af == AF_INET) {
+      sockaddr_in *sin = (sockaddr_in *) &ss;
+      len = sizeof(*sin);
+      sin->sin_port = htons(port);
+      if (!inet_pton(AF_INET, "127.0.0.1", &sin->sin_addr)) {
+        PrintSocketError("inet_pton");
+        closesocket(sock);
+        return -1;
+      }
+    }
+
+    if (connect(sock, reinterpret_cast<const sockaddr*>(&ss), len) == 0) {
+      return sock;
+    }
     closesocket(sock);
-    return -1;
   }
-  sockaddr_in sin;
-  OPENSSL_memset(&sin, 0, sizeof(sin));
-  sin.sin_family = AF_INET;
-  sin.sin_port = htons(port);
-  if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
-    PrintSocketError("inet_pton");
-    closesocket(sock);
-    return -1;
-  }
-  if (connect(sock, reinterpret_cast<const sockaddr*>(&sin),
-              sizeof(sin)) != 0) {
-    PrintSocketError("connect");
-    closesocket(sock);
-    return -1;
-  }
-  return sock;
+  return -1;
 }
 
 class SocketCloser {
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 6239dba..10e728e 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -906,7 +906,10 @@
 		panic(fmt.Sprintf("The name of test %q suggests that it's version specific, but min/max version in the Config is %x/%x. One of them should probably be %x", test.name, test.config.MinVersion, test.config.MaxVersion, ver.version))
 	}
 
-	listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
+	listener, err := net.ListenTCP("tcp", &net.TCPAddr{IP: net.IPv6loopback})
+	if err != nil {
+		listener, err = net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
+	}
 	if err != nil {
 		panic(err)
 	}