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:
parent
97a929aac9
commit
5d6f118f23
@ -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=\
|
||||
|
@ -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
|
||||
|
65
src/pkg/syscall/sockcmsg_unix.go
Normal file
65
src/pkg/syscall/sockcmsg_unix.go
Normal 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
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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]))
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user