syscall: fix Send{msg,msgN}, Recvmsg and control message handling on solaris

This change switches the use of socket implementation from the
conventional SUS-based one to the latest POSIX-based one to make
socket control message work correctly on Solaris.

It looks like those two implementations, Socket over TLI/XTI and
Socket, have different semantics in details but it wouldn't hurt
the existing applications because the exposed syscall API doesn't
support socket properties related to such a protocol independent
application framework.

Fixes #7402.

Change-Id: I45a4e782d606bfbebe1404086c50a8c69af53461
Reviewed-on: https://go-review.googlesource.com/30171
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Mikio Hara 2016-10-01 19:20:32 +09:00
parent 7e0218cdb2
commit 89c4cbd7ac
5 changed files with 52 additions and 54 deletions

View file

@ -13,9 +13,10 @@ import "unsafe"
// Round the length of a raw sockaddr up to align it properly.
func cmsgAlignOf(salen int) int {
salign := sizeofPtr
// NOTE: It seems like 64-bit Darwin and DragonFly BSD kernels
// still require 32-bit aligned access to network subsystem.
if darwin64Bit || dragonfly64Bit {
// NOTE: It seems like 64-bit Darwin, DragonFly BSD and
// Solaris kernels still require 32-bit aligned access to
// network subsystem.
if darwin64Bit || dragonfly64Bit || solaris64Bit {
salign = 4
}
return (salen + salign - 1) & ^(salign - 1)

View file

@ -370,6 +370,7 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
iov.SetLen(1)
}
msg.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
msg.Accrightslen = int32(len(oob))
}
msg.Iov = &iov
msg.Iovlen = 1
@ -389,7 +390,7 @@ func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
return
}
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.sendmsg
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
var ptr unsafe.Pointer
@ -416,6 +417,7 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
iov.SetLen(1)
}
msg.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
msg.Accrightslen = int32(len(oob))
}
msg.Iov = &iov
msg.Iovlen = 1
@ -458,7 +460,7 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
//sys Kill(pid int, signum Signal) (err error)
//sys Lchown(path string, uid int, gid int) (err error)
//sys Link(path string, link string) (err error)
//sys Listen(s int, backlog int) (err error) = libsocket.listen
//sys Listen(s int, backlog int) (err error) = libsocket.__xnet_listen
//sys Lstat(path string, stat *Stat_t) (err error)
//sys Mkdir(path string, mode uint32) (err error)
//sys Mknod(path string, mode uint32, dev int) (err error)
@ -493,20 +495,20 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
//sys Umask(newmask int) (oldmask int)
//sys Unlink(path string) (err error)
//sys Utimes(path string, times *[2]Timeval) (err error)
//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.bind
//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.connect
//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind
//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
//sys munmap(addr uintptr, length uintptr) (err error)
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.sendto
//sys socket(domain int, typ int, proto int) (fd int, err error) = libsocket.socket
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.socketpair
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto
//sys socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair
//sys write(fd int, p []byte) (n int, err error)
//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.getsockopt
//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt
//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername
//sys getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname
//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.recvmsg
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_read)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)

View file

@ -23,6 +23,7 @@ const (
darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8
dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4
solaris64Bit = runtime.GOOS == "solaris" && sizeofPtr == 8
)
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)

View file

@ -125,12 +125,6 @@ func TestFcntlFlock(t *testing.T) {
// "-test.run=^TestPassFD$" and an environment variable used to signal
// that the test should become the child process instead.
func TestPassFD(t *testing.T) {
switch runtime.GOOS {
case "solaris":
// TODO(aram): Figure out why ReadMsgUnix is returning empty message.
t.Skip("skipping test on solaris, see issue 7402")
}
testenv.MustHaveExec(t)
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {

View file

@ -12,7 +12,7 @@ import "unsafe"
//go:cgo_import_dynamic libc_setgroups setgroups "libc.so"
//go:cgo_import_dynamic libc_fcntl fcntl "libc.so"
//go:cgo_import_dynamic libc_accept accept "libsocket.so"
//go:cgo_import_dynamic libc_sendmsg sendmsg "libsocket.so"
//go:cgo_import_dynamic libc___xnet_sendmsg __xnet_sendmsg "libsocket.so"
//go:cgo_import_dynamic libc_Access access "libc.so"
//go:cgo_import_dynamic libc_Adjtime adjtime "libc.so"
//go:cgo_import_dynamic libc_Chdir chdir "libc.so"
@ -40,7 +40,7 @@ import "unsafe"
//go:cgo_import_dynamic libc_Kill kill "libc.so"
//go:cgo_import_dynamic libc_Lchown lchown "libc.so"
//go:cgo_import_dynamic libc_Link link "libc.so"
//go:cgo_import_dynamic libc_listen listen "libsocket.so"
//go:cgo_import_dynamic libc___xnet_listen __xnet_listen "libsocket.so"
//go:cgo_import_dynamic libc_Lstat lstat "libc.so"
//go:cgo_import_dynamic libc_Mkdir mkdir "libc.so"
//go:cgo_import_dynamic libc_Mknod mknod "libc.so"
@ -75,27 +75,27 @@ import "unsafe"
//go:cgo_import_dynamic libc_Umask umask "libc.so"
//go:cgo_import_dynamic libc_Unlink unlink "libc.so"
//go:cgo_import_dynamic libc_Utimes utimes "libc.so"
//go:cgo_import_dynamic libc_bind bind "libsocket.so"
//go:cgo_import_dynamic libc_connect connect "libsocket.so"
//go:cgo_import_dynamic libc___xnet_bind __xnet_bind "libsocket.so"
//go:cgo_import_dynamic libc___xnet_connect __xnet_connect "libsocket.so"
//go:cgo_import_dynamic libc_mmap mmap "libc.so"
//go:cgo_import_dynamic libc_munmap munmap "libc.so"
//go:cgo_import_dynamic libc_sendto sendto "libsocket.so"
//go:cgo_import_dynamic libc_socket socket "libsocket.so"
//go:cgo_import_dynamic libc_socketpair socketpair "libsocket.so"
//go:cgo_import_dynamic libc___xnet_sendto __xnet_sendto "libsocket.so"
//go:cgo_import_dynamic libc___xnet_socket __xnet_socket "libsocket.so"
//go:cgo_import_dynamic libc___xnet_socketpair __xnet_socketpair "libsocket.so"
//go:cgo_import_dynamic libc_write write "libc.so"
//go:cgo_import_dynamic libc_getsockopt getsockopt "libsocket.so"
//go:cgo_import_dynamic libc___xnet_getsockopt __xnet_getsockopt "libsocket.so"
//go:cgo_import_dynamic libc_getpeername getpeername "libsocket.so"
//go:cgo_import_dynamic libc_getsockname getsockname "libsocket.so"
//go:cgo_import_dynamic libc_setsockopt setsockopt "libsocket.so"
//go:cgo_import_dynamic libc_recvfrom recvfrom "libsocket.so"
//go:cgo_import_dynamic libc_recvmsg recvmsg "libsocket.so"
//go:cgo_import_dynamic libc___xnet_recvmsg __xnet_recvmsg "libsocket.so"
//go:linkname libc_Getcwd libc_Getcwd
//go:linkname libc_getgroups libc_getgroups
//go:linkname libc_setgroups libc_setgroups
//go:linkname libc_fcntl libc_fcntl
//go:linkname libc_accept libc_accept
//go:linkname libc_sendmsg libc_sendmsg
//go:linkname libc___xnet_sendmsg libc___xnet_sendmsg
//go:linkname libc_Access libc_Access
//go:linkname libc_Adjtime libc_Adjtime
//go:linkname libc_Chdir libc_Chdir
@ -123,7 +123,7 @@ import "unsafe"
//go:linkname libc_Kill libc_Kill
//go:linkname libc_Lchown libc_Lchown
//go:linkname libc_Link libc_Link
//go:linkname libc_listen libc_listen
//go:linkname libc___xnet_listen libc___xnet_listen
//go:linkname libc_Lstat libc_Lstat
//go:linkname libc_Mkdir libc_Mkdir
//go:linkname libc_Mknod libc_Mknod
@ -158,20 +158,20 @@ import "unsafe"
//go:linkname libc_Umask libc_Umask
//go:linkname libc_Unlink libc_Unlink
//go:linkname libc_Utimes libc_Utimes
//go:linkname libc_bind libc_bind
//go:linkname libc_connect libc_connect
//go:linkname libc___xnet_bind libc___xnet_bind
//go:linkname libc___xnet_connect libc___xnet_connect
//go:linkname libc_mmap libc_mmap
//go:linkname libc_munmap libc_munmap
//go:linkname libc_sendto libc_sendto
//go:linkname libc_socket libc_socket
//go:linkname libc_socketpair libc_socketpair
//go:linkname libc___xnet_sendto libc___xnet_sendto
//go:linkname libc___xnet_socket libc___xnet_socket
//go:linkname libc___xnet_socketpair libc___xnet_socketpair
//go:linkname libc_write libc_write
//go:linkname libc_getsockopt libc_getsockopt
//go:linkname libc___xnet_getsockopt libc___xnet_getsockopt
//go:linkname libc_getpeername libc_getpeername
//go:linkname libc_getsockname libc_getsockname
//go:linkname libc_setsockopt libc_setsockopt
//go:linkname libc_recvfrom libc_recvfrom
//go:linkname libc_recvmsg libc_recvmsg
//go:linkname libc___xnet_recvmsg libc___xnet_recvmsg
type libcFunc uintptr
@ -181,7 +181,7 @@ var (
libc_setgroups,
libc_fcntl,
libc_accept,
libc_sendmsg,
libc___xnet_sendmsg,
libc_Access,
libc_Adjtime,
libc_Chdir,
@ -209,7 +209,7 @@ var (
libc_Kill,
libc_Lchown,
libc_Link,
libc_listen,
libc___xnet_listen,
libc_Lstat,
libc_Mkdir,
libc_Mknod,
@ -244,20 +244,20 @@ var (
libc_Umask,
libc_Unlink,
libc_Utimes,
libc_bind,
libc_connect,
libc___xnet_bind,
libc___xnet_connect,
libc_mmap,
libc_munmap,
libc_sendto,
libc_socket,
libc_socketpair,
libc___xnet_sendto,
libc___xnet_socket,
libc___xnet_socketpair,
libc_write,
libc_getsockopt,
libc___xnet_getsockopt,
libc_getpeername,
libc_getsockname,
libc_setsockopt,
libc_recvfrom,
libc_recvmsg libcFunc
libc___xnet_recvmsg libcFunc
)
func Getcwd(buf []byte) (n int, err error) {
@ -309,7 +309,7 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
}
func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_sendmsg)), 3, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc___xnet_sendmsg)), 3, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
@ -575,7 +575,7 @@ func Link(path string, link string) (err error) {
}
func Listen(s int, backlog int) (err error) {
_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_listen)), 2, uintptr(s), uintptr(backlog), 0, 0, 0, 0)
_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc___xnet_listen)), 2, uintptr(s), uintptr(backlog), 0, 0, 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -968,7 +968,7 @@ func Utimes(path string, times *[2]Timeval) (err error) {
}
func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_bind)), 3, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc___xnet_bind)), 3, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -976,7 +976,7 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
}
func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_connect)), 3, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc___xnet_connect)), 3, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -1005,7 +1005,7 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (
if len(buf) > 0 {
_p0 = &buf[0]
}
_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_sendto)), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc___xnet_sendto)), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
if e1 != 0 {
err = errnoErr(e1)
}
@ -1013,7 +1013,7 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (
}
func socket(domain int, typ int, proto int) (fd int, err error) {
r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_socket)), 3, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0)
r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc___xnet_socket)), 3, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0)
fd = int(r0)
if e1 != 0 {
err = errnoErr(e1)
@ -1022,7 +1022,7 @@ func socket(domain int, typ int, proto int) (fd int, err error) {
}
func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
_, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&libc_socketpair)), 4, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
_, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&libc___xnet_socketpair)), 4, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -1043,7 +1043,7 @@ func write(fd int, p []byte) (n int, err error) {
}
func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) {
_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_getsockopt)), 5, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc___xnet_getsockopt)), 5, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
@ -1088,7 +1088,7 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
}
func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_recvmsg)), 3, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc___xnet_recvmsg)), 3, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)