syscall, net: Add Recvmsg and Sendmsg on Linux.
Working on issue 1101.
R=rsc
CC=golang-dev
https://golang.org/cl/2331044
diff --git a/src/pkg/syscall/mkerrors.sh b/src/pkg/syscall/mkerrors.sh
index f7b4adb..f3fb942 100755
--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -25,6 +25,8 @@
#include <sys/epoll.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
#include <linux/ptrace.h>
#include <linux/wait.h>
#include <netpacket/packet.h>
@@ -84,11 +86,13 @@
$2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers
$2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
+ $2 ~ /^(SCM_SRCRT)$/ {next}
+ $2 ~ /^(MAP_FAILED)$/ {next}
$2 ~ /^E[A-Z0-9_]+$/ ||
$2 ~ /^SIG[^_]/ ||
$2 ~ /^IN_/ ||
- $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|EVFILT|EV|SHUT|PROT|MAP|PACKET)_/ ||
+ $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|EVFILT|EV|SHUT|PROT|MAP|PACKET|MSG|SCM)_/ ||
$2 == "SOMAXCONN" ||
$2 == "NAME_MAX" ||
$2 ~ /^(O|F|FD|NAME|S|PTRACE)_/ ||
diff --git a/src/pkg/syscall/syscall_bsd.go b/src/pkg/syscall/syscall_bsd.go
index 7675370..ff99fd9 100644
--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/pkg/syscall/syscall_bsd.go
@@ -485,6 +485,13 @@
//sys fcntl(fd int, cmd int, arg int) (val int, errno int)
+func Recvmsg(fd int, p, oob []byte, from Sockaddr, flags int) (n, oobn int, recvflags int, errno int) {
+ return 0, 0, 0, EAFNOSUPPORT
+}
+
+func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
+ return EAFNOSUPPORT
+}
// TODO: wrap
// Acct(name nil-string) (errno int)
@@ -495,5 +502,3 @@
// Msync(addr *byte, len int, flags int) (errno int)
// Munmap(addr *byte, len int) (errno int)
// Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, errno int)
-// Recvmsg(s int, msg *Msghdr, flags int) (n int, errno int)
-// Sendmsg(s int, msg *Msghdr, flags int) (n int, errno int)
diff --git a/src/pkg/syscall/syscall_linux.go b/src/pkg/syscall/syscall_linux.go
index d34956c..710ab74 100644
--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -447,6 +447,72 @@
return sendto(fd, p, flags, ptr, n)
}
+func Recvmsg(fd int, p, oob []byte, from Sockaddr, flags int) (n, oobn int, recvflags int, errno int) {
+ var msg Msghdr
+ var rsa RawSockaddrAny
+ msg.Name = (*byte)(unsafe.Pointer(&rsa))
+ msg.Namelen = uint32(SizeofSockaddrAny)
+ var iov Iovec
+ if len(p) > 0 {
+ iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+ iov.SetLen(len(p))
+ }
+ var dummy byte
+ if len(oob) > 0 {
+ // receive at least one normal byte
+ if len(p) == 0 {
+ iov.Base = &dummy
+ iov.SetLen(1)
+ }
+ msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
+ msg.SetControllen(len(oob))
+ }
+ msg.Iov = &iov
+ msg.Iovlen = 1
+ if n, errno = recvmsg(fd, &msg, flags); errno != 0 {
+ return
+ }
+ oobn = int(msg.Controllen)
+ recvflags = int(msg.Flags)
+ return
+}
+
+func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
+ var ptr uintptr
+ var nsock _Socklen
+ if to != nil {
+ var err int
+ ptr, nsock, err = to.sockaddr()
+ if err != 0 {
+ return err
+ }
+ }
+ var msg Msghdr
+ msg.Name = (*byte)(unsafe.Pointer(ptr))
+ msg.Namelen = uint32(nsock)
+ var iov Iovec
+ if len(p) > 0 {
+ iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+ iov.SetLen(len(p))
+ }
+ var dummy byte
+ if len(oob) > 0 {
+ // send at least one normal byte
+ if len(p) == 0 {
+ iov.Base = &dummy
+ iov.SetLen(1)
+ }
+ msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
+ msg.SetControllen(len(oob))
+ }
+ msg.Iov = &iov
+ msg.Iovlen = 1
+ if errno = sendmsg(fd, &msg, flags); errno != 0 {
+ return
+ }
+ return
+}
+
// BindToDevice binds the socket associated with fd to device.
func BindToDevice(fd int, device string) (errno int) {
return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device)
@@ -592,8 +658,6 @@
// Sendto
// Recvfrom
-// Sendmsg
-// Recvmsg
// Socketpair
// Getsockopt
diff --git a/src/pkg/syscall/syscall_linux_386.go b/src/pkg/syscall/syscall_linux_386.go
index 88b3034..bf5dd47 100644
--- a/src/pkg/syscall/syscall_linux_386.go
+++ b/src/pkg/syscall/syscall_linux_386.go
@@ -151,6 +151,16 @@
return
}
+func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
+ n, errno = socketcall(_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
+ return
+}
+
+func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
+ _, errno = socketcall(_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
+ return
+}
+
func Listen(s int, n int) (errno int) {
_, errno = socketcall(_LISTEN, uintptr(s), uintptr(n), 0, 0, 0, 0)
return
@@ -176,3 +186,15 @@
func (r *PtraceRegs) PC() uint64 { return uint64(uint32(r.Eip)) }
func (r *PtraceRegs) SetPC(pc uint64) { r.Eip = int32(pc) }
+
+func (iov *Iovec) SetLen(length int) {
+ iov.Len = uint32(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+ msghdr.Controllen = uint32(length)
+}
+
+func (cmsg *Cmsghdr) SetLen(length int) {
+ cmsg.Len = uint32(length)
+}
diff --git a/src/pkg/syscall/syscall_linux_amd64.go b/src/pkg/syscall/syscall_linux_amd64.go
index fda8260..0b8ccb0 100644
--- a/src/pkg/syscall/syscall_linux_amd64.go
+++ b/src/pkg/syscall/syscall_linux_amd64.go
@@ -46,6 +46,8 @@
//sys getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int)
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int)
//sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int)
+//sys recvmsg(s int, msg *Msghdr, flags int) (n int, errno int)
+//sys sendmsg(s int, msg *Msghdr, flags int) (errno int)
func Getpagesize() int { return 4096 }
@@ -72,3 +74,15 @@
func (r *PtraceRegs) PC() uint64 { return r.Rip }
func (r *PtraceRegs) SetPC(pc uint64) { r.Rip = pc }
+
+func (iov *Iovec) SetLen(length int) {
+ iov.Len = uint64(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+ msghdr.Controllen = uint64(length)
+}
+
+func (cmsg *Cmsghdr) SetLen(length int) {
+ cmsg.Len = uint64(length)
+}
diff --git a/src/pkg/syscall/zerrors_linux_386.go b/src/pkg/syscall/zerrors_linux_386.go
index c6b31a1..f685367 100644
--- a/src/pkg/syscall/zerrors_linux_386.go
+++ b/src/pkg/syscall/zerrors_linux_386.go
@@ -385,6 +385,40 @@
IP_TOS = 0x1
IP_TTL = 0x2
IP_UNBLOCK_SOURCE = 0x25
+ MAP_32BIT = 0x40
+ MAP_ANON = 0x20
+ MAP_ANONYMOUS = 0x20
+ MAP_DENYWRITE = 0x800
+ MAP_EXECUTABLE = 0x1000
+ MAP_FILE = 0
+ MAP_FIXED = 0x10
+ MAP_GROWSDOWN = 0x100
+ MAP_LOCKED = 0x2000
+ MAP_NONBLOCK = 0x10000
+ MAP_NORESERVE = 0x4000
+ MAP_POPULATE = 0x8000
+ MAP_PRIVATE = 0x2
+ MAP_SHARED = 0x1
+ MAP_STACK = 0x20000
+ MAP_TYPE = 0xf
+ MSG_CMSG_CLOEXEC = 0x40000000
+ MSG_CONFIRM = 0x800
+ MSG_CTRUNC = 0x8
+ MSG_DONTROUTE = 0x4
+ MSG_DONTWAIT = 0x40
+ MSG_EOR = 0x80
+ MSG_ERRQUEUE = 0x2000
+ MSG_FIN = 0x200
+ MSG_MORE = 0x8000
+ MSG_NOSIGNAL = 0x4000
+ MSG_OOB = 0x1
+ MSG_PEEK = 0x2
+ MSG_PROXY = 0x10
+ MSG_RST = 0x1000
+ MSG_SYN = 0x400
+ MSG_TRUNC = 0x20
+ MSG_TRYHARD = 0x4
+ MSG_WAITALL = 0x100
NAME_MAX = 0xff
O_ACCMODE = 0x3
O_APPEND = 0x400
@@ -423,6 +457,12 @@
PACKET_RECV_OUTPUT = 0x3
PACKET_RX_RING = 0x5
PACKET_STATISTICS = 0x6
+ PROT_EXEC = 0x4
+ PROT_GROWSDOWN = 0x1000000
+ PROT_GROWSUP = 0x2000000
+ PROT_NONE = 0
+ PROT_READ = 0x1
+ PROT_WRITE = 0x2
PTRACE_ATTACH = 0x10
PTRACE_BTS_CLEAR = 0x2c
PTRACE_BTS_CONFIG = 0x28
@@ -476,6 +516,11 @@
PTRACE_SYSEMU = 0x1f
PTRACE_SYSEMU_SINGLESTEP = 0x20
PTRACE_TRACEME = 0
+ SCM_CREDENTIALS = 0x2
+ SCM_RIGHTS = 0x1
+ SCM_TIMESTAMP = 0x1d
+ SCM_TIMESTAMPING = 0x25
+ SCM_TIMESTAMPNS = 0x23
SHUT_RD = 0
SHUT_RDWR = 0x2
SHUT_WR = 0x1
diff --git a/src/pkg/syscall/zerrors_linux_amd64.go b/src/pkg/syscall/zerrors_linux_amd64.go
index 9a5f035..bfe86bb 100644
--- a/src/pkg/syscall/zerrors_linux_amd64.go
+++ b/src/pkg/syscall/zerrors_linux_amd64.go
@@ -385,6 +385,40 @@
IP_TOS = 0x1
IP_TTL = 0x2
IP_UNBLOCK_SOURCE = 0x25
+ MAP_32BIT = 0x40
+ MAP_ANON = 0x20
+ MAP_ANONYMOUS = 0x20
+ MAP_DENYWRITE = 0x800
+ MAP_EXECUTABLE = 0x1000
+ MAP_FILE = 0
+ MAP_FIXED = 0x10
+ MAP_GROWSDOWN = 0x100
+ MAP_LOCKED = 0x2000
+ MAP_NONBLOCK = 0x10000
+ MAP_NORESERVE = 0x4000
+ MAP_POPULATE = 0x8000
+ MAP_PRIVATE = 0x2
+ MAP_SHARED = 0x1
+ MAP_STACK = 0x20000
+ MAP_TYPE = 0xf
+ MSG_CMSG_CLOEXEC = 0x40000000
+ MSG_CONFIRM = 0x800
+ MSG_CTRUNC = 0x8
+ MSG_DONTROUTE = 0x4
+ MSG_DONTWAIT = 0x40
+ MSG_EOR = 0x80
+ MSG_ERRQUEUE = 0x2000
+ MSG_FIN = 0x200
+ MSG_MORE = 0x8000
+ MSG_NOSIGNAL = 0x4000
+ MSG_OOB = 0x1
+ MSG_PEEK = 0x2
+ MSG_PROXY = 0x10
+ MSG_RST = 0x1000
+ MSG_SYN = 0x400
+ MSG_TRUNC = 0x20
+ MSG_TRYHARD = 0x4
+ MSG_WAITALL = 0x100
NAME_MAX = 0xff
O_ACCMODE = 0x3
O_APPEND = 0x400
@@ -423,6 +457,12 @@
PACKET_RECV_OUTPUT = 0x3
PACKET_RX_RING = 0x5
PACKET_STATISTICS = 0x6
+ PROT_EXEC = 0x4
+ PROT_GROWSDOWN = 0x1000000
+ PROT_GROWSUP = 0x2000000
+ PROT_NONE = 0
+ PROT_READ = 0x1
+ PROT_WRITE = 0x2
PTRACE_ARCH_PRCTL = 0x1e
PTRACE_ATTACH = 0x10
PTRACE_BTS_CLEAR = 0x2c
@@ -477,6 +517,11 @@
PTRACE_SYSEMU = 0x1f
PTRACE_SYSEMU_SINGLESTEP = 0x20
PTRACE_TRACEME = 0
+ SCM_CREDENTIALS = 0x2
+ SCM_RIGHTS = 0x1
+ SCM_TIMESTAMP = 0x1d
+ SCM_TIMESTAMPING = 0x25
+ SCM_TIMESTAMPNS = 0x23
SHUT_RD = 0
SHUT_RDWR = 0x2
SHUT_WR = 0x1
diff --git a/src/pkg/syscall/zsyscall_linux_amd64.go b/src/pkg/syscall/zsyscall_linux_amd64.go
index e08525b..94cdc02 100644
--- a/src/pkg/syscall/zsyscall_linux_amd64.go
+++ b/src/pkg/syscall/zsyscall_linux_amd64.go
@@ -1089,3 +1089,20 @@
errno = int(e1)
return
}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
+ r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+ n = int(r0)
+ errno = int(e1)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
+ _, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+ errno = int(e1)
+ return
+}