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>
diff --git a/unix/mkerrors.sh b/unix/mkerrors.sh
index 2363df8..4a92a55 100755
--- a/unix/mkerrors.sh
+++ b/unix/mkerrors.sh
@@ -66,6 +66,7 @@
#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>
diff --git a/unix/syscall_bsd.go b/unix/syscall_bsd.go
index 123536a..bc634a2 100644
--- a/unix/syscall_bsd.go
+++ b/unix/syscall_bsd.go
@@ -277,7 +277,7 @@
}
return sa, nil
}
- return nil, EAFNOSUPPORT
+ return anyToSockaddrGOOS(fd, rsa)
}
func Accept(fd int) (nfd int, sa Sockaddr, err error) {
diff --git a/unix/syscall_darwin.go b/unix/syscall_darwin.go
index 7fc58d6..bf4dc9a 100644
--- a/unix/syscall_darwin.go
+++ b/unix/syscall_darwin.go
@@ -31,6 +31,36 @@
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.
diff --git a/unix/syscall_freebsd.go b/unix/syscall_freebsd.go
index f6db02a..acc00c2 100644
--- a/unix/syscall_freebsd.go
+++ b/unix/syscall_freebsd.go
@@ -54,6 +54,10 @@
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])
diff --git a/unix/syscall_internal_darwin_test.go b/unix/syscall_internal_darwin_test.go
new file mode 100644
index 0000000..529e977
--- /dev/null
+++ b/unix/syscall_internal_darwin_test.go
@@ -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
+}
diff --git a/unix/syscall_netbsd.go b/unix/syscall_netbsd.go
index dbd5e03..1e6843b 100644
--- a/unix/syscall_netbsd.go
+++ b/unix/syscall_netbsd.go
@@ -31,6 +31,10 @@
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) {
diff --git a/unix/syscall_openbsd.go b/unix/syscall_openbsd.go
index 2c1f46e..6a50b50 100644
--- a/unix/syscall_openbsd.go
+++ b/unix/syscall_openbsd.go
@@ -31,6 +31,10 @@
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) {
diff --git a/unix/types_darwin.go b/unix/types_darwin.go
index 95b89ea..1764b31 100644
--- a/unix/types_darwin.go
+++ b/unix/types_darwin.go
@@ -146,6 +146,8 @@
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 @@
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
diff --git a/unix/zerrors_darwin_386.go b/unix/zerrors_darwin_386.go
index c8f9f7a..ec376f5 100644
--- a/unix/zerrors_darwin_386.go
+++ b/unix/zerrors_darwin_386.go
@@ -45,6 +45,7 @@
AF_SIP = 0x18
AF_SNA = 0xb
AF_SYSTEM = 0x20
+ AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1
AF_UNSPEC = 0x0
AF_UTUN = 0x26
diff --git a/unix/zerrors_darwin_amd64.go b/unix/zerrors_darwin_amd64.go
index 7180064..fea5dfa 100644
--- a/unix/zerrors_darwin_amd64.go
+++ b/unix/zerrors_darwin_amd64.go
@@ -45,6 +45,7 @@
AF_SIP = 0x18
AF_SNA = 0xb
AF_SYSTEM = 0x20
+ AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1
AF_UNSPEC = 0x0
AF_UTUN = 0x26
diff --git a/unix/zerrors_darwin_arm.go b/unix/zerrors_darwin_arm.go
index 3b9ca75..03feefb 100644
--- a/unix/zerrors_darwin_arm.go
+++ b/unix/zerrors_darwin_arm.go
@@ -45,6 +45,7 @@
AF_SIP = 0x18
AF_SNA = 0xb
AF_SYSTEM = 0x20
+ AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1
AF_UNSPEC = 0x0
AF_UTUN = 0x26
diff --git a/unix/zerrors_darwin_arm64.go b/unix/zerrors_darwin_arm64.go
index 4687c73..b40fb1f 100644
--- a/unix/zerrors_darwin_arm64.go
+++ b/unix/zerrors_darwin_arm64.go
@@ -45,6 +45,7 @@
AF_SIP = 0x18
AF_SNA = 0xb
AF_SYSTEM = 0x20
+ AF_SYS_CONTROL = 0x2
AF_UNIX = 0x1
AF_UNSPEC = 0x0
AF_UTUN = 0x26
diff --git a/unix/ztypes_darwin_386.go b/unix/ztypes_darwin_386.go
index 9ea0293..830fbb3 100644
--- a/unix/ztypes_darwin_386.go
+++ b/unix/ztypes_darwin_386.go
@@ -194,6 +194,15 @@
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 @@
SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14
+ SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14
diff --git a/unix/ztypes_darwin_amd64.go b/unix/ztypes_darwin_amd64.go
index 255e6cb..e53a7c4 100644
--- a/unix/ztypes_darwin_amd64.go
+++ b/unix/ztypes_darwin_amd64.go
@@ -199,6 +199,15 @@
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 @@
SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14
+ SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14
diff --git a/unix/ztypes_darwin_arm.go b/unix/ztypes_darwin_arm.go
index e21c828..98be973 100644
--- a/unix/ztypes_darwin_arm.go
+++ b/unix/ztypes_darwin_arm.go
@@ -194,6 +194,15 @@
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 @@
SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14
+ SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14
diff --git a/unix/ztypes_darwin_arm64.go b/unix/ztypes_darwin_arm64.go
index 5eff2c1..ddae5af 100644
--- a/unix/ztypes_darwin_arm64.go
+++ b/unix/ztypes_darwin_arm64.go
@@ -199,6 +199,15 @@
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 @@
SizeofSockaddrAny = 0x6c
SizeofSockaddrUnix = 0x6a
SizeofSockaddrDatalink = 0x14
+ SizeofSockaddrCtl = 0x20
SizeofLinger = 0x8
SizeofIPMreq = 0x8
SizeofIPv6Mreq = 0x14