internal/nettest: add SupportsRawIPSocket that reports raw IP socket availability

This change copies a few code fragments from
https://golang.org/cl/13422044.

Change-Id: I7ceae3a59e15dc9f9ef4b2b64a41753aa9d6798b
Reviewed-on: https://go-review.googlesource.com/3400
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/internal/nettest/stack_stub.go b/internal/nettest/stack_stub.go
new file mode 100644
index 0000000..1b5fde1
--- /dev/null
+++ b/internal/nettest/stack_stub.go
@@ -0,0 +1,18 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build nacl plan9
+
+package nettest
+
+import (
+	"fmt"
+	"runtime"
+)
+
+// SupportsRawIPSocket reports whether the platform supports raw IP
+// sockets.
+func SupportsRawIPSocket() (string, bool) {
+	return fmt.Sprintf("not supported on %s", runtime.GOOS), false
+}
diff --git a/internal/nettest/stack_unix.go b/internal/nettest/stack_unix.go
new file mode 100644
index 0000000..af89229
--- /dev/null
+++ b/internal/nettest/stack_unix.go
@@ -0,0 +1,22 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package nettest
+
+import (
+	"fmt"
+	"os"
+	"runtime"
+)
+
+// SupportsRawIPSocket reports whether the platform supports raw IP
+// sockets.
+func SupportsRawIPSocket() (string, bool) {
+	if os.Getuid() != 0 {
+		return fmt.Sprintf("must be root on %s", runtime.GOOS), false
+	}
+	return "", true
+}
diff --git a/internal/nettest/stack_windows.go b/internal/nettest/stack_windows.go
new file mode 100644
index 0000000..a21f499
--- /dev/null
+++ b/internal/nettest/stack_windows.go
@@ -0,0 +1,32 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package nettest
+
+import (
+	"fmt"
+	"runtime"
+	"syscall"
+)
+
+// SupportsRawIPSocket reports whether the platform supports raw IP
+// sockets.
+func SupportsRawIPSocket() (string, bool) {
+	// From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx:
+	// Note: To use a socket of type SOCK_RAW requires administrative privileges.
+	// Users running Winsock applications that use raw sockets must be a member of
+	// the Administrators group on the local computer, otherwise raw socket calls
+	// will fail with an error code of WSAEACCES. On Windows Vista and later, access
+	// for raw sockets is enforced at socket creation. In earlier versions of Windows,
+	// access for raw sockets is enforced during other socket operations.
+	s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0)
+	if err == syscall.WSAEACCES {
+		return fmt.Sprintf("no access to raw socket allowed on %s", runtime.GOOS), false
+	}
+	if err != nil {
+		return err.Error(), false
+	}
+	syscall.Closesocket(s)
+	return "", true
+}