diff options
Diffstat (limited to 'src/pkg/syscall/sockcmsg_unix.go')
-rw-r--r-- | src/pkg/syscall/sockcmsg_unix.go | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/src/pkg/syscall/sockcmsg_unix.go b/src/pkg/syscall/sockcmsg_unix.go index f0c05eaf3..b437560e7 100644 --- a/src/pkg/syscall/sockcmsg_unix.go +++ b/src/pkg/syscall/sockcmsg_unix.go @@ -24,10 +24,22 @@ func cmsgAlignOf(salen int) int { return (salen + salign - 1) & ^(salign - 1) } -func cmsgLen(datalen int) int { +// CmsgLen returns the value to store in the Len field of the Cmsghdr +// structure, taking into account any necessary alignment. +func CmsgLen(datalen int) int { return cmsgAlignOf(SizeofCmsghdr) + datalen } +// CmsgSpace returns the number of bytes an ancillary element with +// payload of the passed data length occupies. +func CmsgSpace(datalen int) int { + return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen) +} + +func cmsgData(cmsg *Cmsghdr) unsafe.Pointer { + return unsafe.Pointer(uintptr(unsafe.Pointer(cmsg)) + SizeofCmsghdr) +} + type SocketControlMessage struct { Header Cmsghdr Data []byte @@ -41,7 +53,7 @@ func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, int) { cmsgs []SocketControlMessage ) - for len(buf) >= cmsgLen(0) { + for len(buf) >= CmsgLen(0) { h, dbuf, e = socketControlMessageHeaderAndData(buf) if e != 0 { break @@ -63,3 +75,39 @@ func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, int) { } return h, buf[cmsgAlignOf(SizeofCmsghdr):], 0 } + +// UnixRights encodes a set of open file descriptors into a socket +// control message for sending to another process. +func UnixRights(fds ...int) []byte { + datalen := len(fds) * 4 + buf := make([]byte, CmsgSpace(datalen)) + cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0])) + cmsg.Level = SOL_SOCKET + cmsg.Type = SCM_RIGHTS + cmsg.SetLen(CmsgLen(datalen)) + + data := uintptr(cmsgData(cmsg)) + for _, fd := range fds { + *(*int32)(unsafe.Pointer(data)) = int32(fd) + data += 4 + } + + return buf +} + +// ParseUnixRights decodes a socket control message that contains an +// integer array of open file descriptors from another process. +func ParseUnixRights(msg *SocketControlMessage) ([]int, int) { + if msg.Header.Level != SOL_SOCKET { + return nil, EINVAL + } + if msg.Header.Type != SCM_RIGHTS { + return nil, EINVAL + } + fds := make([]int, len(msg.Data)>>2) + for i, j := 0, 0; i < len(msg.Data); i += 4 { + fds[j] = int(*(*int32)(unsafe.Pointer(&msg.Data[i]))) + j++ + } + return fds, 0 +} |