1
0
mirror of https://github.com/golang/go synced 2024-11-19 16:54:44 -07:00

net: use WSASocket instead of socket call

WSASocket (unlike socket call) allows to create sockets that
will not be inherited by child process. So call WSASocket to
save on using syscall.ForkLock and calling syscall.CloseOnExec.

Some very old versions of Windows do not have that functionality.
Call socket, if WSASocket failed, to support these.

Change-Id: I2dab9fa00d1a8609dd6feae1c9cc31d4e55b8cb5
Reviewed-on: https://go-review.googlesource.com/72590
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Alex Brainman 2017-10-23 16:23:43 +11:00
parent 9e76ce7070
commit 44623c2ece
7 changed files with 79 additions and 6 deletions

View File

@ -266,7 +266,7 @@ var pkgDeps = map[string][]string{
"math/big": {"L4"},
"mime": {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
"mime/quotedprintable": {"L4"},
"net/internal/socktest": {"L4", "OS", "syscall"},
"net/internal/socktest": {"L4", "OS", "syscall", "internal/syscall/windows"},
"net/url": {"L4"},
"plugin": {"L0", "OS", "CGO"},
"runtime/pprof/internal/profile": {"L4", "OS", "compress/gzip", "regexp"},

View File

@ -112,6 +112,13 @@ const (
//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
//sys GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
const (
WSA_FLAG_OVERLAPPED = 0x01
WSA_FLAG_NO_HANDLE_INHERIT = 0x80
)
//sys WSASocket(af int32, typ int32, protocol int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = ws2_32.WSASocketW
const (
ComputerNameNetBIOS = 0
ComputerNameDnsHostname = 1

View File

@ -38,6 +38,7 @@ func errnoErr(e syscall.Errno) error {
var (
modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll"))
modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll"))
modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll"))
modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll"))
@ -46,6 +47,7 @@ var (
procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
procMoveFileExW = modkernel32.NewProc("MoveFileExW")
procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW")
procWSASocketW = modws2_32.NewProc("WSASocketW")
procGetACP = modkernel32.NewProc("GetACP")
procGetConsoleCP = modkernel32.NewProc("GetConsoleCP")
procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar")
@ -108,6 +110,19 @@ func GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32,
return
}
func WSASocket(af int32, typ int32, protocol int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (handle syscall.Handle, err error) {
r0, _, e1 := syscall.Syscall6(procWSASocketW.Addr(), 6, uintptr(af), uintptr(typ), uintptr(protocol), uintptr(unsafe.Pointer(protinfo)), uintptr(group), uintptr(flags))
handle = syscall.Handle(r0)
if handle == syscall.InvalidHandle {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func GetACP() (acp uint32) {
r0, _, _ := syscall.Syscall(procGetACP.Addr(), 0, 0, 0, 0)
acp = uint32(r0)

View File

@ -5,6 +5,7 @@
package net
import (
"internal/syscall/windows"
"syscall"
"time"
)
@ -13,7 +14,8 @@ var (
testHookDialChannel = func() { time.Sleep(time.Millisecond) } // see golang.org/issue/5349
// Placeholders for socket system calls.
socketFunc func(int, int, int) (syscall.Handle, error) = syscall.Socket
connectFunc func(syscall.Handle, syscall.Sockaddr) error = syscall.Connect
listenFunc func(syscall.Handle, int) error = syscall.Listen
socketFunc func(int, int, int) (syscall.Handle, error) = syscall.Socket
wsaSocketFunc func(int32, int32, int32, *syscall.WSAProtocolInfo, uint32, uint32) (syscall.Handle, error) = windows.WSASocket
connectFunc func(syscall.Handle, syscall.Sockaddr) error = syscall.Connect
listenFunc func(syscall.Handle, int) error = syscall.Listen
)

View File

@ -4,7 +4,10 @@
package socktest
import "syscall"
import (
"internal/syscall/windows"
"syscall"
)
// Socket wraps syscall.Socket.
func (sw *Switch) Socket(family, sotype, proto int) (s syscall.Handle, err error) {
@ -38,6 +41,38 @@ func (sw *Switch) Socket(family, sotype, proto int) (s syscall.Handle, err error
return s, nil
}
// WSASocket wraps syscall.WSASocket.
func (sw *Switch) WSASocket(family, sotype, proto int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (s syscall.Handle, err error) {
sw.once.Do(sw.init)
so := &Status{Cookie: cookie(int(family), int(sotype), int(proto))}
sw.fmu.RLock()
f, _ := sw.fltab[FilterSocket]
sw.fmu.RUnlock()
af, err := f.apply(so)
if err != nil {
return syscall.InvalidHandle, err
}
s, so.Err = windows.WSASocket(family, sotype, proto, protinfo, group, flags)
if err = af.apply(so); err != nil {
if so.Err == nil {
syscall.Closesocket(s)
}
return syscall.InvalidHandle, err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).OpenFailed++
return syscall.InvalidHandle, so.Err
}
nso := sw.addLocked(s, int(family), int(sotype), int(proto))
sw.stats.getLocked(nso.Cookie).Opened++
return s, nil
}
// Closesocket wraps syscall.Closesocket.
func (sw *Switch) Closesocket(s syscall.Handle) (err error) {
so := sw.sockso(s)

View File

@ -9,6 +9,7 @@ import "internal/poll"
var (
// Placeholders for saving original socket system calls.
origSocket = socketFunc
origWSASocket = wsaSocketFunc
origClosesocket = poll.CloseFunc
origConnect = connectFunc
origConnectEx = poll.ConnectExFunc
@ -18,6 +19,7 @@ var (
func installTestHooks() {
socketFunc = sw.Socket
wsaSocketFunc = sw.WSASocket
poll.CloseFunc = sw.Closesocket
connectFunc = sw.Connect
poll.ConnectExFunc = sw.ConnectEx
@ -27,6 +29,7 @@ func installTestHooks() {
func uninstallTestHooks() {
socketFunc = origSocket
wsaSocketFunc = origWSASocket
poll.CloseFunc = origClosesocket
connectFunc = origConnect
poll.ConnectExFunc = origConnectEx

View File

@ -5,6 +5,7 @@
package net
import (
"internal/syscall/windows"
"os"
"syscall"
)
@ -16,9 +17,19 @@ func maxListenerBacklog() int {
}
func sysSocket(family, sotype, proto int) (syscall.Handle, error) {
s, err := wsaSocketFunc(int32(family), int32(sotype), int32(proto),
nil, 0, windows.WSA_FLAG_OVERLAPPED|windows.WSA_FLAG_NO_HANDLE_INHERIT)
if err == nil {
return s, nil
}
// WSA_FLAG_NO_HANDLE_INHERIT flag is not supported on some
// old versions of Windows, see
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms742212(v=vs.85).aspx
// for details. Just use syscall.Socket, if windows.WSASocket failed.
// See ../syscall/exec_unix.go for description of ForkLock.
syscall.ForkLock.RLock()
s, err := socketFunc(family, sotype, proto)
s, err = socketFunc(family, sotype, proto)
if err == nil {
syscall.CloseOnExec(s)
}