1
0
mirror of https://github.com/golang/go synced 2024-11-19 14:54:43 -07:00

syscall: add socket control message support for darwin, freebsd, linux

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4528113
This commit is contained in:
Mikio Hara 2011-06-20 18:40:20 -04:00 committed by Russ Cox
parent 97a929aac9
commit 5d6f118f23
14 changed files with 263 additions and 13 deletions

View File

@ -20,6 +20,7 @@ GOFILES_freebsd=\
bpf_bsd.go\
exec_unix.go\
route_bsd.go\
sockcmsg_unix.go\
syscall_bsd.go\
syscall_unix.go\
@ -27,6 +28,7 @@ GOFILES_darwin=\
bpf_bsd.go\
exec_unix.go\
route_bsd.go\
sockcmsg_unix.go\
syscall_bsd.go\
syscall_unix.go\
@ -34,6 +36,7 @@ GOFILES_linux=\
exec_unix.go\
lsf_linux.go\
netlink_linux.go\
sockcmsg_unix.go\
syscall_unix.go\
GOFILES_windows=\

View File

@ -10,8 +10,6 @@ import (
"unsafe"
)
const darwinAMD64 = OS == "darwin" && ARCH == "amd64"
// Round the length of a raw sockaddr up to align it properly.
func rsaAlignOf(salen int) int {
salign := sizeofPtr

View File

@ -0,0 +1,65 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Socket control messages
package syscall
import (
"unsafe"
)
// Round the length of a raw sockaddr up to align it propery.
func cmsgAlignOf(salen int) int {
salign := sizeofPtr
// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
// aligned access to BSD subsystem.
if darwinAMD64 {
salign = 4
}
if salen == 0 {
return salign
}
return (salen + salign - 1) & ^(salign - 1)
}
func cmsgLen(datalen int) int {
return cmsgAlignOf(SizeofCmsghdr) + datalen
}
type SocketControlMessage struct {
Header Cmsghdr
Data []byte
}
func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, int) {
var (
h *Cmsghdr
dbuf []byte
e int
cmsgs []SocketControlMessage
)
for len(buf) >= cmsgLen(0) {
h, dbuf, e = socketControlMessageHeaderAndData(buf)
if e != 0 {
break
}
m := SocketControlMessage{}
m.Header = *h
m.Data = dbuf[:int(h.Len)-cmsgAlignOf(SizeofCmsghdr)]
cmsgs = append(cmsgs, m)
buf = buf[cmsgAlignOf(int(h.Len)):]
}
return cmsgs, e
}
func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, int) {
h := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
if h.Len < SizeofCmsghdr || int(h.Len) > len(buf) {
return nil, nil, EINVAL
}
return h, buf[cmsgAlignOf(SizeofCmsghdr):], 0
}

View File

@ -425,6 +425,80 @@ func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
return sendto(fd, p, flags, ptr, n)
}
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, errno int)
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, 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)
// source address is only specified if the socket is unconnected
if rsa.Addr.Family != AF_UNSPEC {
from, errno = anyToSockaddr(&rsa)
}
return
}
//sys sendmsg(s int, msg *Msghdr, flags int) (errno int)
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
var ptr uintptr
var salen _Socklen
if to != nil {
var err int
ptr, salen, err = to.sockaddr()
if err != 0 {
return err
}
}
var msg Msghdr
msg.Name = (*byte)(unsafe.Pointer(ptr))
msg.Namelen = uint32(salen)
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
}
// TODO:
// FreeBSD has IP_SENDIF. Darwin probably needs BSDLLCTest, see:
// http://developer.apple.com/mac/library/samplecode/BSDLLCTest/index.html
@ -540,14 +614,6 @@ func Futimes(fd int, tv []Timeval) (errno int) {
//sys fcntl(fd int, cmd int, arg int) (val int, errno int)
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, errno int) {
return 0, 0, 0, nil, EAFNOSUPPORT
}
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
return EAFNOSUPPORT
}
// TODO: wrap
// Acct(name nil-string) (errno int)
// Gethostuuid(uuid *byte, timeout *Timespec) (errno int)

View File

@ -40,4 +40,16 @@ func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Flags = uint16(flags)
}
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)
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) // sic

View File

@ -39,3 +39,15 @@ func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Filter = int16(mode)
k.Flags = uint16(flags)
}
func (iov *Iovec) SetLen(length int) {
iov.Len = uint64(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}

View File

@ -29,4 +29,16 @@ func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Flags = uint16(flags)
}
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)
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) // sic

View File

@ -28,3 +28,15 @@ func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Filter = int16(mode)
k.Flags = uint16(flags)
}
func (iov *Iovec) SetLen(length int) {
iov.Len = uint64(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}

View File

@ -529,17 +529,17 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
var ptr uintptr
var nsock _Socklen
var salen _Socklen
if to != nil {
var err int
ptr, nsock, err = to.sockaddr()
ptr, salen, err = to.sockaddr()
if err != 0 {
return err
}
}
var msg Msghdr
msg.Name = (*byte)(unsafe.Pointer(ptr))
msg.Namelen = uint32(nsock)
msg.Namelen = uint32(salen)
var iov Iovec
if len(p) > 0 {
iov.Base = (*byte)(unsafe.Pointer(&p[0]))

View File

@ -16,6 +16,8 @@ var (
Stderr = 2
)
const darwinAMD64 = OS == "darwin" && ARCH == "amd64"
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)

View File

@ -154,6 +154,23 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
// 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
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
n = int(r0)

View File

@ -154,6 +154,23 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
// 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
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
n = int(r0)

View File

@ -154,6 +154,23 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
// 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
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
n = int(r0)

View File

@ -154,6 +154,23 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
// 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
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
n = int(r0)