From 710a502c58a2a4b2d7417a4e24ccb96d8dc13fa3 Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Wed, 27 Mar 2019 05:40:43 +0900 Subject: [PATCH] nettest: add SupportsRawSocket Also updates API docs. Change-Id: I0c744a286bf637270156101bfdee1e87e306fa5e Reviewed-on: https://go-review.googlesource.com/c/net/+/169539 Run-TryBot: Mikio Hara TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- nettest/nettest.go | 27 +++++++++++++++++---------- nettest/nettest_stub.go | 11 +++++++++++ nettest/nettest_unix.go | 21 +++++++++++++++++++++ nettest/nettest_windows.go | 26 ++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 nettest/nettest_stub.go create mode 100644 nettest/nettest_unix.go create mode 100644 nettest/nettest_windows.go diff --git a/nettest/nettest.go b/nettest/nettest.go index c75facf7..717bbb06 100644 --- a/nettest/nettest.go +++ b/nettest/nettest.go @@ -20,10 +20,11 @@ import ( ) var ( - stackOnce sync.Once - ipv4Enabled bool - ipv6Enabled bool - aixTechLvl int + stackOnce sync.Once + ipv4Enabled bool + ipv6Enabled bool + rawSocketSess bool + aixTechLvl int aLongTimeAgo = time.Unix(233431200, 0) neverTimeout = time.Time{} @@ -41,12 +42,12 @@ func probeStack() { ln.Close() ipv6Enabled = true } + rawSocketSess = supportsRawSocket() if runtime.GOOS == "aix" { out, err := exec.Command("oslevel", "-s").Output() - if err != nil { - return + if err == nil { + aixTechLvl, _ = strconv.Atoi(string(out[5:7])) } - aixTechLvl, _ = strconv.Atoi(string(out[5:7])) } } @@ -69,8 +70,17 @@ func SupportsIPv6() bool { return ipv6Enabled } +// SupportsRawSocket reports whether the current session is available +// to use raw sockets. +func SupportsRawSocket() bool { + stackOnce.Do(probeStack) + return rawSocketSess +} + // TestableNetwork reports whether network is testable on the current // platform configuration. +// +// See func Dial of the standard library for the supported networks. func TestableNetwork(network string) bool { ss := strings.Split(network, ":") switch ss[0] { @@ -248,7 +258,6 @@ func MulticastSource(network string, ifi *net.Interface) (net.IP, error) { // LoopbackInterface returns an available logical network interface // for loopback test. -// It returns nil if no suitable interface is found. func LoopbackInterface() (*net.Interface, error) { ift, err := net.Interfaces() if err != nil { @@ -264,8 +273,6 @@ func LoopbackInterface() (*net.Interface, error) { // RoutedInterface returns a network interface that can route IP // traffic and satisfies flags. -// It returns nil when an appropriate network interface is not -// found. // // The provided network must be "ip", "ip4" or "ip6". func RoutedInterface(network string, flags net.Flags) (*net.Interface, error) { diff --git a/nettest/nettest_stub.go b/nettest/nettest_stub.go new file mode 100644 index 00000000..2bb8c057 --- /dev/null +++ b/nettest/nettest_stub.go @@ -0,0 +1,11 @@ +// Copyright 2019 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 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows + +package nettest + +func supportsRawSocket() bool { + return false +} diff --git a/nettest/nettest_unix.go b/nettest/nettest_unix.go new file mode 100644 index 00000000..afff744e --- /dev/null +++ b/nettest/nettest_unix.go @@ -0,0 +1,21 @@ +// Copyright 2019 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris + +package nettest + +import "syscall" + +func supportsRawSocket() bool { + for _, af := range []int{syscall.AF_INET, syscall.AF_INET6} { + s, err := syscall.Socket(af, syscall.SOCK_RAW, 0) + if err != nil { + continue + } + syscall.Close(s) + return true + } + return false +} diff --git a/nettest/nettest_windows.go b/nettest/nettest_windows.go new file mode 100644 index 00000000..4939964d --- /dev/null +++ b/nettest/nettest_windows.go @@ -0,0 +1,26 @@ +// Copyright 2019 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 "syscall" + +func supportsRawSocket() 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. + for _, af := range []int{syscall.AF_INET, syscall.AF_INET6} { + s, err := syscall.Socket(af, syscall.SOCK_RAW, 0) + if err != nil { + continue + } + syscall.Closesocket(s) + return true + } + return false +}