Commit 44623c2e authored by Alex Brainman's avatar Alex Brainman

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/72590Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 9e76ce70
......@@ -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"},
......
......@@ -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
......
......@@ -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)
......
......@@ -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
)
......@@ -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)
......
......@@ -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
......
......@@ -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)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment