nettest: use RoutedInterface for probing network stack capability

The ipv4/ipv6 support capability is done by explicitly listening on
loopback interface. However, it can lead to false positive, especially
for ipv6 case. For example, ipv6 can be enabled, but explicitly disable
for loopback interface (for security, policy ...).

This CL changes probeStack to use another approach, by looking for any
interface that can route IP traffic and in "UP" state. If there's one,
then the platform can do ipv4/ipv6 networking functionality.

Fixes golang/go#57386

Change-Id: If911bc223b52c5a4562d3f61b4ee1032bdbec47c
Reviewed-on: https://go-review.googlesource.com/c/net/+/458096
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Benny Siegert <bsiegert@gmail.com>
Reviewed-by: Matt Layher <mdlayher@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
diff --git a/ipv6/bpf_test.go b/ipv6/bpf_test.go
index e249e1c..c43ddd0 100644
--- a/ipv6/bpf_test.go
+++ b/ipv6/bpf_test.go
@@ -19,8 +19,8 @@
 	if runtime.GOOS != "linux" {
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
-	if !nettest.SupportsIPv6() {
-		t.Skip("ipv6 is not supported")
+	if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil {
+		t.Skip("ipv6 is not enabled for loopback interface")
 	}
 
 	l, err := net.ListenPacket("udp6", "[::1]:0")
diff --git a/ipv6/readwrite_test.go b/ipv6/readwrite_test.go
index e8db119..131b190 100644
--- a/ipv6/readwrite_test.go
+++ b/ipv6/readwrite_test.go
@@ -223,10 +223,10 @@
 	case "fuchsia", "hurd", "js", "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
-	if !nettest.SupportsIPv6() {
-		t.Skip("ipv6 is not supported")
+	ifi, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
+	if err != nil {
+		t.Skip("ipv6 is not enabled for loopback interface")
 	}
-
 	c, err := nettest.NewLocalPacketListener("udp6")
 	if err != nil {
 		t.Fatal(err)
@@ -236,7 +236,6 @@
 	defer p.Close()
 
 	dst := c.LocalAddr()
-	ifi, _ := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
 	cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
 	wb := []byte("HELLO-R-U-THERE")
 
diff --git a/ipv6/sockopt_test.go b/ipv6/sockopt_test.go
index 3305cfc..ab0d2e4 100644
--- a/ipv6/sockopt_test.go
+++ b/ipv6/sockopt_test.go
@@ -20,8 +20,9 @@
 	case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
-	if !nettest.SupportsIPv6() {
-		t.Skip("ipv6 is not supported")
+
+	if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil {
+		t.Skip("ipv6 is not enabled for loopback interface")
 	}
 
 	ln, err := net.Listen("tcp6", "[::1]:0")
@@ -53,8 +54,8 @@
 	case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
-	if !nettest.SupportsIPv6() {
-		t.Skip("ipv6 is not supported")
+	if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil {
+		t.Skip("ipv6 is not enabled for loopback interface")
 	}
 
 	ln, err := net.Listen("tcp6", "[::1]:0")
diff --git a/ipv6/unicast_test.go b/ipv6/unicast_test.go
index fe1d44d..e03c2cd 100644
--- a/ipv6/unicast_test.go
+++ b/ipv6/unicast_test.go
@@ -23,8 +23,8 @@
 	case "fuchsia", "hurd", "js", "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
-	if !nettest.SupportsIPv6() {
-		t.Skip("ipv6 is not supported")
+	if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil {
+		t.Skip("ipv6 is not enabled for loopback interface")
 	}
 
 	c, err := nettest.NewLocalPacketListener("udp6")
diff --git a/ipv6/unicastsockopt_test.go b/ipv6/unicastsockopt_test.go
index ac0daf2..c3abe2d 100644
--- a/ipv6/unicastsockopt_test.go
+++ b/ipv6/unicastsockopt_test.go
@@ -19,8 +19,8 @@
 	case "fuchsia", "hurd", "js", "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
-	if !nettest.SupportsIPv6() {
-		t.Skip("ipv6 is not supported")
+	if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil {
+		t.Skip("ipv6 is not enabled for loopback interface")
 	}
 
 	ln, err := net.Listen("tcp6", "[::1]:0")
@@ -64,8 +64,8 @@
 	case "fuchsia", "hurd", "js", "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
-	if !nettest.SupportsIPv6() {
-		t.Skip("ipv6 is not supported")
+	if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil {
+		t.Skip("ipv6 is not enabled for loopback interface")
 	}
 
 	ok := nettest.SupportsRawSocket()
diff --git a/nettest/nettest.go b/nettest/nettest.go
index 6918f2c..3d970bf 100644
--- a/nettest/nettest.go
+++ b/nettest/nettest.go
@@ -34,12 +34,10 @@
 )
 
 func probeStack() {
-	if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil {
-		ln.Close()
+	if _, err := RoutedInterface("ip4", net.FlagUp); err == nil {
 		ipv4Enabled = true
 	}
-	if ln, err := net.Listen("tcp6", "[::1]:0"); err == nil {
-		ln.Close()
+	if _, err := RoutedInterface("ip6", net.FlagUp); err == nil {
 		ipv6Enabled = true
 	}
 	rawSocketSess = supportsRawSocket()