unix: implement AF_SYSTEM/AF_SYS_CONTROL sockets on darwin

See https://developer.apple.com/documentation/kernel/sockaddr_ctl for
details.

AF_SYSTEM is darwin-specific, so the BSD-specific anyToSockaddr func
needs to call GOOS-specific funcs which return nil, EAFNOSUPPORT on all
BSD platforms but darwin.

For golang/go#41868

Change-Id: Id7794aba5988dd9511053b76be5efeb66c104a26
Reviewed-on: https://go-review.googlesource.com/c/sys/+/264638
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matt Layher <mdlayher@gmail.com>
This commit is contained in:
Tobias Klauser
2020-10-24 20:27:56 +02:00
committed by Tobias Klauser
parent 119d4633e4
commit e1471140ff
16 changed files with 223 additions and 1 deletions

View File

@@ -66,6 +66,7 @@ includes_Darwin='
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sys_domain.h>
#include <sys/sysctl.h>
#include <sys/mman.h>
#include <sys/mount.h>

View File

@@ -277,7 +277,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
}
return sa, nil
}
return nil, EAFNOSUPPORT
return anyToSockaddrGOOS(fd, rsa)
}
func Accept(fd int) (nfd int, sa Sockaddr, err error) {

View File

@@ -31,6 +31,36 @@ type SockaddrDatalink struct {
raw RawSockaddrDatalink
}
// SockaddrCtl implements the Sockaddr interface for AF_SYSTEM type sockets.
type SockaddrCtl struct {
ID uint32
Unit uint32
raw RawSockaddrCtl
}
func (sa *SockaddrCtl) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Sc_len = SizeofSockaddrCtl
sa.raw.Sc_family = AF_SYSTEM
sa.raw.Ss_sysaddr = AF_SYS_CONTROL
sa.raw.Sc_id = sa.ID
sa.raw.Sc_unit = sa.Unit
return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil
}
func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family {
case AF_SYSTEM:
pp := (*RawSockaddrCtl)(unsafe.Pointer(rsa))
if pp.Ss_sysaddr == AF_SYS_CONTROL {
sa := new(SockaddrCtl)
sa.ID = pp.Sc_id
sa.Unit = pp.Sc_unit
return sa, nil
}
}
return nil, EAFNOSUPPORT
}
// Some external packages rely on SYS___SYSCTL being defined to implement their
// own sysctl wrappers. Provide it here, even though direct syscalls are no
// longer supported on darwin.

View File

@@ -54,6 +54,10 @@ type SockaddrDatalink struct {
raw RawSockaddrDatalink
}
func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
return nil, EAFNOSUPPORT
}
// Translate "kern.hostname" to []_C_int{0,1,2,3}.
func nametomib(name string) (mib []_C_int, err error) {
const siz = unsafe.Sizeof(mib[0])

View File

@@ -0,0 +1,132 @@
// Copyright 2020 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.
package unix
import (
"reflect"
"testing"
"unsafe"
)
func Test_anyToSockaddr_darwin(t *testing.T) {
tests := []struct {
name string
rsa *RawSockaddrAny
sa Sockaddr
err error
}{
{
name: "AF_SYSTEM emtpy",
rsa: sockaddrCtlToAny(RawSockaddrCtl{}),
err: EAFNOSUPPORT,
},
{
name: "AF_SYSTEM no sysaddr",
rsa: sockaddrCtlToAny(RawSockaddrCtl{
Sc_family: AF_SYSTEM,
}),
err: EAFNOSUPPORT,
},
{
name: "AF_SYSTEM/AF_SYS_CONTROL empty ",
rsa: sockaddrCtlToAny(RawSockaddrCtl{
Sc_family: AF_SYSTEM,
Ss_sysaddr: AF_SYS_CONTROL,
}),
sa: &SockaddrCtl{},
},
{
name: "AF_SYSTEM ID and unit",
rsa: sockaddrCtlToAny(RawSockaddrCtl{
Sc_family: AF_SYSTEM,
Ss_sysaddr: AF_SYS_CONTROL,
Sc_id: 0x42,
Sc_unit: 0xC71,
}),
sa: &SockaddrCtl{
ID: 0x42,
Unit: 0xC71,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fd := int(0)
var err error
sa, err := anyToSockaddr(fd, tt.rsa)
if err != tt.err {
t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
}
if !reflect.DeepEqual(sa, tt.sa) {
t.Fatalf("unexpected Sockaddr:\n got: %#v\nwant: %#v", sa, tt.sa)
}
})
}
}
func TestSockaddrCtl_sockaddr(t *testing.T) {
tests := []struct {
name string
sa *SockaddrCtl
raw *RawSockaddrCtl
err error
}{
{
name: "empty",
sa: &SockaddrCtl{},
raw: &RawSockaddrCtl{
Sc_len: SizeofSockaddrCtl,
Sc_family: AF_SYSTEM,
Ss_sysaddr: AF_SYS_CONTROL,
},
},
{
name: "with ID and unit",
sa: &SockaddrCtl{
ID: 0x42,
Unit: 0xff,
},
raw: &RawSockaddrCtl{
Sc_len: SizeofSockaddrCtl,
Sc_family: AF_SYSTEM,
Ss_sysaddr: AF_SYS_CONTROL,
Sc_id: 0x42,
Sc_unit: 0xff,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out, l, err := tt.sa.sockaddr()
if err != tt.err {
t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
}
// Must be 0 on error or a fixed size otherwise.
if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrCtl) {
t.Fatalf("unexpected Socklen: %d", l)
}
if out != nil {
raw := (*RawSockaddrCtl)(out)
if !reflect.DeepEqual(raw, tt.raw) {
t.Fatalf("unexpected RawSockaddrCtl:\n got: %#v\nwant: %#v", raw, tt.raw)
}
}
})
}
}
func sockaddrCtlToAny(in RawSockaddrCtl) *RawSockaddrAny {
var out RawSockaddrAny
copy(
(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
(*(*[SizeofSockaddrCtl]byte)(unsafe.Pointer(&in)))[:],
)
return &out
}

View File

@@ -31,6 +31,10 @@ type SockaddrDatalink struct {
raw RawSockaddrDatalink
}
func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
return nil, EAFNOSUPPORT
}
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) {

View File

@@ -31,6 +31,10 @@ type SockaddrDatalink struct {
raw RawSockaddrDatalink
}
func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
return nil, EAFNOSUPPORT
}
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func nametomib(name string) (mib []_C_int, err error) {

View File

@@ -146,6 +146,8 @@ type RawSockaddr C.struct_sockaddr
type RawSockaddrAny C.struct_sockaddr_any
type RawSockaddrCtl C.struct_sockaddr_ctl
type _Socklen C.socklen_t
type Linger C.struct_linger
@@ -174,6 +176,7 @@ const (
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
SizeofSockaddrCtl = C.sizeof_struct_sockaddr_ctl
SizeofLinger = C.sizeof_struct_linger
SizeofIPMreq = C.sizeof_struct_ip_mreq
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq

View File

@@ -45,6 +45,7 @@ const (
AF_SIP = 0x18
AF_SNA = 0xb
AF_SYSTEM = 0x20
AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1
AF_UNSPEC = 0x0
AF_UTUN = 0x26

View File

@@ -45,6 +45,7 @@ const (
AF_SIP = 0x18
AF_SNA = 0xb
AF_SYSTEM = 0x20
AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1
AF_UNSPEC = 0x0
AF_UTUN = 0x26

View File

@@ -45,6 +45,7 @@ const (
AF_SIP = 0x18
AF_SNA = 0xb
AF_SYSTEM = 0x20
AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1
AF_UNSPEC = 0x0
AF_UTUN = 0x26

View File

@@ -45,6 +45,7 @@ const (
AF_SIP = 0x18
AF_SNA = 0xb
AF_SYSTEM = 0x20
AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1
AF_UNSPEC = 0x0
AF_UTUN = 0x26

View File

@@ -194,6 +194,15 @@ type RawSockaddrAny struct {
Pad [92]int8
}
type RawSockaddrCtl struct {
Sc_len uint8
Sc_family uint8
Ss_sysaddr uint16
Sc_id uint32
Sc_unit uint32
Sc_reserved [5]uint32
}
type _Socklen uint32
type Linger struct {
@@ -258,6 +267,7 @@ const (
SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14

View File

@@ -199,6 +199,15 @@ type RawSockaddrAny struct {
Pad [92]int8
}
type RawSockaddrCtl struct {
Sc_len uint8
Sc_family uint8
Ss_sysaddr uint16
Sc_id uint32
Sc_unit uint32
Sc_reserved [5]uint32
}
type _Socklen uint32
type Linger struct {
@@ -263,6 +272,7 @@ const (
SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14

View File

@@ -194,6 +194,15 @@ type RawSockaddrAny struct {
Pad [92]int8
}
type RawSockaddrCtl struct {
Sc_len uint8
Sc_family uint8
Ss_sysaddr uint16
Sc_id uint32
Sc_unit uint32
Sc_reserved [5]uint32
}
type _Socklen uint32
type Linger struct {
@@ -258,6 +267,7 @@ const (
SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14

View File

@@ -199,6 +199,15 @@ type RawSockaddrAny struct {
Pad [92]int8
}
type RawSockaddrCtl struct {
Sc_len uint8
Sc_family uint8
Ss_sysaddr uint16
Sc_id uint32
Sc_unit uint32
Sc_reserved [5]uint32
}
type _Socklen uint32
type Linger struct {
@@ -263,6 +272,7 @@ const (
SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14