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/net/fd.go b/src/pkg/net/fd.go
index d300e4b..b2e24f5 100644
--- a/src/pkg/net/fd.go
+++ b/src/pkg/net/fd.go
@@ -401,6 +401,42 @@
 	return
 }
 
+func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err os.Error) {
+	if fd == nil || fd.sysfile == nil {
+		return 0, 0, 0, nil, os.EINVAL
+	}
+	fd.rio.Lock()
+	defer fd.rio.Unlock()
+	fd.incref()
+	defer fd.decref()
+	if fd.rdeadline_delta > 0 {
+		fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
+	} else {
+		fd.rdeadline = 0
+	}
+	var oserr os.Error
+	for {
+		var errno int
+		n, oobn, flags, errno = syscall.Recvmsg(fd.sysfd, p, oob, sa, 0)
+		if errno == syscall.EAGAIN && fd.rdeadline >= 0 {
+			pollserver.WaitRead(fd)
+			continue
+		}
+		if errno != 0 {
+			oserr = os.Errno(errno)
+		}
+		if n == 0 {
+			oserr = os.EOF
+		}
+		break
+	}
+	if oserr != nil {
+		err = &OpError{"read", fd.net, fd.laddr, oserr}
+		return
+	}
+	return
+}
+
 func (fd *netFD) Write(p []byte) (n int, err os.Error) {
 	if fd == nil {
 		return 0, os.EINVAL
@@ -481,6 +517,41 @@
 	return
 }
 
+func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err os.Error) {
+	if fd == nil || fd.sysfile == nil {
+		return 0, 0, os.EINVAL
+	}
+	fd.wio.Lock()
+	defer fd.wio.Unlock()
+	fd.incref()
+	defer fd.decref()
+	if fd.wdeadline_delta > 0 {
+		fd.wdeadline = pollserver.Now() + fd.wdeadline_delta
+	} else {
+		fd.wdeadline = 0
+	}
+	var oserr os.Error
+	for {
+		var errno int
+		errno = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
+		if errno == syscall.EAGAIN && fd.wdeadline >= 0 {
+			pollserver.WaitWrite(fd)
+			continue
+		}
+		if errno != 0 {
+			oserr = os.Errno(errno)
+		}
+		break
+	}
+	if oserr == nil {
+		n = len(p)
+		oobn = len(oob)
+	} else {
+		err = &OpError{"write", fd.net, fd.raddr, oserr}
+	}
+	return
+}
+
 func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) {
 	if fd == nil || fd.sysfile == nil {
 		return nil, os.EINVAL
diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index 75e2e4f..64eed4a 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -445,3 +445,11 @@
 	// TODO: Implement this
 	return nil, os.NewSyscallError("dup", syscall.EWINDOWS)
 }
+
+func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err os.Error) {
+	return 0, 0, 0, nil, os.EAFNOSUPPORT
+}
+
+func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err os.Error) {
+	return 0, 0, os.EAFNOSUPPORT
+}
diff --git a/src/pkg/net/unixsock.go b/src/pkg/net/unixsock.go
index 82c0b6d..1c15e5e 100644
--- a/src/pkg/net/unixsock.go
+++ b/src/pkg/net/unixsock.go
@@ -277,6 +277,32 @@
 	return c.WriteToUnix(b, a)
 }
 
+func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err os.Error) {
+	if !c.ok() {
+		return 0, 0, 0, nil, os.EINVAL
+	}
+	n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
+	switch sa := sa.(type) {
+	case *syscall.SockaddrUnix:
+		addr = &UnixAddr{sa.Name, c.fd.proto == syscall.SOCK_DGRAM}
+	}
+	return
+}
+
+func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err os.Error) {
+	if !c.ok() {
+		return 0, 0, os.EINVAL
+	}
+	if addr != nil {
+		if addr.Datagram != (c.fd.proto == syscall.SOCK_DGRAM) {
+			return 0, 0, os.EAFNOSUPPORT
+		}
+		sa := &syscall.SockaddrUnix{Name: addr.Name}
+		return c.fd.WriteMsg(b, oob, sa)
+	}
+	return c.fd.WriteMsg(b, oob, nil)
+}
+
 // File returns a copy of the underlying os.File, set to blocking mode.
 // It is the caller's responsibility to close f when finished.
 // Closing c does not affect f, and closing f does not affect c.