diff --git a/unix/mkerrors.sh b/unix/mkerrors.sh index 2363df86..4a92a558 100755 --- a/unix/mkerrors.sh +++ b/unix/mkerrors.sh @@ -66,6 +66,7 @@ includes_Darwin=' #include #include #include +#include #include #include #include diff --git a/unix/syscall_bsd.go b/unix/syscall_bsd.go index 123536a0..bc634a28 100644 --- a/unix/syscall_bsd.go +++ b/unix/syscall_bsd.go @@ -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) { diff --git a/unix/syscall_darwin.go b/unix/syscall_darwin.go index 7fc58d6d..bf4dc9a4 100644 --- a/unix/syscall_darwin.go +++ b/unix/syscall_darwin.go @@ -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. diff --git a/unix/syscall_freebsd.go b/unix/syscall_freebsd.go index f6db02af..acc00c2e 100644 --- a/unix/syscall_freebsd.go +++ b/unix/syscall_freebsd.go @@ -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]) diff --git a/unix/syscall_internal_darwin_test.go b/unix/syscall_internal_darwin_test.go new file mode 100644 index 00000000..529e9778 --- /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 dbd5e03b..1e6843b4 100644 --- a/unix/syscall_netbsd.go +++ b/unix/syscall_netbsd.go @@ -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) { diff --git a/unix/syscall_openbsd.go b/unix/syscall_openbsd.go index 2c1f46ea..6a50b50b 100644 --- a/unix/syscall_openbsd.go +++ b/unix/syscall_openbsd.go @@ -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) { diff --git a/unix/types_darwin.go b/unix/types_darwin.go index 95b89eac..1764b312 100644 --- a/unix/types_darwin.go +++ b/unix/types_darwin.go @@ -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 diff --git a/unix/zerrors_darwin_386.go b/unix/zerrors_darwin_386.go index c8f9f7a1..ec376f51 100644 --- a/unix/zerrors_darwin_386.go +++ b/unix/zerrors_darwin_386.go @@ -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 diff --git a/unix/zerrors_darwin_amd64.go b/unix/zerrors_darwin_amd64.go index 7180064b..fea5dfaa 100644 --- a/unix/zerrors_darwin_amd64.go +++ b/unix/zerrors_darwin_amd64.go @@ -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 diff --git a/unix/zerrors_darwin_arm.go b/unix/zerrors_darwin_arm.go index 3b9ca758..03feefbf 100644 --- a/unix/zerrors_darwin_arm.go +++ b/unix/zerrors_darwin_arm.go @@ -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 diff --git a/unix/zerrors_darwin_arm64.go b/unix/zerrors_darwin_arm64.go index 4687c73a..b40fb1f6 100644 --- a/unix/zerrors_darwin_arm64.go +++ b/unix/zerrors_darwin_arm64.go @@ -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 diff --git a/unix/ztypes_darwin_386.go b/unix/ztypes_darwin_386.go index 9ea0293a..830fbb35 100644 --- a/unix/ztypes_darwin_386.go +++ b/unix/ztypes_darwin_386.go @@ -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 diff --git a/unix/ztypes_darwin_amd64.go b/unix/ztypes_darwin_amd64.go index 255e6cbb..e53a7c49 100644 --- a/unix/ztypes_darwin_amd64.go +++ b/unix/ztypes_darwin_amd64.go @@ -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 diff --git a/unix/ztypes_darwin_arm.go b/unix/ztypes_darwin_arm.go index e21c8285..98be973e 100644 --- a/unix/ztypes_darwin_arm.go +++ b/unix/ztypes_darwin_arm.go @@ -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 diff --git a/unix/ztypes_darwin_arm64.go b/unix/ztypes_darwin_arm64.go index 5eff2c1c..ddae5afe 100644 --- a/unix/ztypes_darwin_arm64.go +++ b/unix/ztypes_darwin_arm64.go @@ -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