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-27 09:04:13 +00:00
committed by Tobias Klauser
parent 119d4633e4
commit e1471140ff
16 changed files with 223 additions and 1 deletions
+1
View File
@@ -66,6 +66,7 @@ includes_Darwin='
#include <sys/select.h> #include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/sys_domain.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/mount.h> #include <sys/mount.h>
+1 -1
View File
@@ -277,7 +277,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
} }
return sa, nil return sa, nil
} }
return nil, EAFNOSUPPORT return anyToSockaddrGOOS(fd, rsa)
} }
func Accept(fd int) (nfd int, sa Sockaddr, err error) { func Accept(fd int) (nfd int, sa Sockaddr, err error) {
+30
View File
@@ -31,6 +31,36 @@ type SockaddrDatalink struct {
raw RawSockaddrDatalink 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 // Some external packages rely on SYS___SYSCTL being defined to implement their
// own sysctl wrappers. Provide it here, even though direct syscalls are no // own sysctl wrappers. Provide it here, even though direct syscalls are no
// longer supported on darwin. // longer supported on darwin.
+4
View File
@@ -54,6 +54,10 @@ type SockaddrDatalink struct {
raw RawSockaddrDatalink raw RawSockaddrDatalink
} }
func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
return nil, EAFNOSUPPORT
}
// Translate "kern.hostname" to []_C_int{0,1,2,3}. // Translate "kern.hostname" to []_C_int{0,1,2,3}.
func nametomib(name string) (mib []_C_int, err error) { func nametomib(name string) (mib []_C_int, err error) {
const siz = unsafe.Sizeof(mib[0]) const siz = unsafe.Sizeof(mib[0])
+132
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
}
+4
View File
@@ -31,6 +31,10 @@ type SockaddrDatalink struct {
raw RawSockaddrDatalink 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 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) { func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) {
+4
View File
@@ -31,6 +31,10 @@ type SockaddrDatalink struct {
raw RawSockaddrDatalink 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 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) { func nametomib(name string) (mib []_C_int, err error) {
+3
View File
@@ -146,6 +146,8 @@ type RawSockaddr C.struct_sockaddr
type RawSockaddrAny C.struct_sockaddr_any type RawSockaddrAny C.struct_sockaddr_any
type RawSockaddrCtl C.struct_sockaddr_ctl
type _Socklen C.socklen_t type _Socklen C.socklen_t
type Linger C.struct_linger type Linger C.struct_linger
@@ -174,6 +176,7 @@ const (
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
SizeofSockaddrCtl = C.sizeof_struct_sockaddr_ctl
SizeofLinger = C.sizeof_struct_linger SizeofLinger = C.sizeof_struct_linger
SizeofIPMreq = C.sizeof_struct_ip_mreq SizeofIPMreq = C.sizeof_struct_ip_mreq
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
+1
View File
@@ -45,6 +45,7 @@ const (
AF_SIP = 0x18 AF_SIP = 0x18
AF_SNA = 0xb AF_SNA = 0xb
AF_SYSTEM = 0x20 AF_SYSTEM = 0x20
AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1 AF_UNIX = 0x1
AF_UNSPEC = 0x0 AF_UNSPEC = 0x0
AF_UTUN = 0x26 AF_UTUN = 0x26
+1
View File
@@ -45,6 +45,7 @@ const (
AF_SIP = 0x18 AF_SIP = 0x18
AF_SNA = 0xb AF_SNA = 0xb
AF_SYSTEM = 0x20 AF_SYSTEM = 0x20
AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1 AF_UNIX = 0x1
AF_UNSPEC = 0x0 AF_UNSPEC = 0x0
AF_UTUN = 0x26 AF_UTUN = 0x26
+1
View File
@@ -45,6 +45,7 @@ const (
AF_SIP = 0x18 AF_SIP = 0x18
AF_SNA = 0xb AF_SNA = 0xb
AF_SYSTEM = 0x20 AF_SYSTEM = 0x20
AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1 AF_UNIX = 0x1
AF_UNSPEC = 0x0 AF_UNSPEC = 0x0
AF_UTUN = 0x26 AF_UTUN = 0x26
+1
View File
@@ -45,6 +45,7 @@ const (
AF_SIP = 0x18 AF_SIP = 0x18
AF_SNA = 0xb AF_SNA = 0xb
AF_SYSTEM = 0x20 AF_SYSTEM = 0x20
AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1 AF_UNIX = 0x1
AF_UNSPEC = 0x0 AF_UNSPEC = 0x0
AF_UTUN = 0x26 AF_UTUN = 0x26
+10
View File
@@ -194,6 +194,15 @@ type RawSockaddrAny struct {
Pad [92]int8 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 _Socklen uint32
type Linger struct { type Linger struct {
@@ -258,6 +267,7 @@ const (
SizeofSockaddrAny = 0x6c SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14 SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8 SizeofLinger = 0x8
SizeofIPMreq = 0x8 SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14 SizeofIPv6Mreq = 0x14
+10
View File
@@ -199,6 +199,15 @@ type RawSockaddrAny struct {
Pad [92]int8 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 _Socklen uint32
type Linger struct { type Linger struct {
@@ -263,6 +272,7 @@ const (
SizeofSockaddrAny = 0x6c SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14 SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8 SizeofLinger = 0x8
SizeofIPMreq = 0x8 SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14 SizeofIPv6Mreq = 0x14
+10
View File
@@ -194,6 +194,15 @@ type RawSockaddrAny struct {
Pad [92]int8 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 _Socklen uint32
type Linger struct { type Linger struct {
@@ -258,6 +267,7 @@ const (
SizeofSockaddrAny = 0x6c SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14 SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8 SizeofLinger = 0x8
SizeofIPMreq = 0x8 SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14 SizeofIPv6Mreq = 0x14
+10
View File
@@ -199,6 +199,15 @@ type RawSockaddrAny struct {
Pad [92]int8 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 _Socklen uint32
type Linger struct { type Linger struct {
@@ -263,6 +272,7 @@ const (
SizeofSockaddrAny = 0x6c SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14 SizeofSockaddrDatalink = 0x14
SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8 SizeofLinger = 0x8
SizeofIPMreq = 0x8 SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14 SizeofIPv6Mreq = 0x14