unix: add SockaddrVM type and AF_VSOCK to anyToSockaddrGOOS to darwin
Change-Id: I511be555d92ac87a797949fc4c99fd8ef9515ace
Reviewed-on: https://go-review.googlesource.com/c/sys/+/354269
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/syscall_darwin.go b/unix/syscall_darwin.go
index d59fb95..a8c1331 100644
--- a/unix/syscall_darwin.go
+++ b/unix/syscall_darwin.go
@@ -48,6 +48,30 @@
return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil
}
+// SockaddrVM implements the Sockaddr interface for AF_VSOCK type sockets.
+// SockaddrVM provides access to Darwin VM sockets: a mechanism that enables
+// bidirectional communication between a hypervisor and its guest virtual
+// machines.
+type SockaddrVM struct {
+ // CID and Port specify a context ID and port address for a VM socket.
+ // Guests have a unique CID, and hosts may have a well-known CID of:
+ // - VMADDR_CID_HYPERVISOR: refers to the hypervisor process.
+ // - VMADDR_CID_LOCAL: refers to local communication (loopback).
+ // - VMADDR_CID_HOST: refers to other processes on the host.
+ CID uint32
+ Port uint32
+ raw RawSockaddrVM
+}
+
+func (sa *SockaddrVM) sockaddr() (unsafe.Pointer, _Socklen, error) {
+ sa.raw.Len = SizeofSockaddrVM
+ sa.raw.Family = AF_VSOCK
+ sa.raw.Port = sa.Port
+ sa.raw.Cid = sa.CID
+
+ return unsafe.Pointer(&sa.raw), SizeofSockaddrVM, nil
+}
+
func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family {
case AF_SYSTEM:
@@ -58,6 +82,13 @@
sa.Unit = pp.Sc_unit
return sa, nil
}
+ case AF_VSOCK:
+ pp := (*RawSockaddrVM)(unsafe.Pointer(rsa))
+ sa := &SockaddrVM{
+ CID: pp.Cid,
+ Port: pp.Port,
+ }
+ return sa, nil
}
return nil, EAFNOSUPPORT
}
diff --git a/unix/syscall_internal_darwin_test.go b/unix/syscall_internal_darwin_test.go
index e443144..d89ac2a 100644
--- a/unix/syscall_internal_darwin_test.go
+++ b/unix/syscall_internal_darwin_test.go
@@ -50,6 +50,23 @@
Unit: 0xC71,
},
},
+ {
+ name: "AF_VSOCK emtpy",
+ rsa: sockaddrVMToAny(RawSockaddrVM{}),
+ err: EAFNOSUPPORT,
+ },
+ {
+ name: "AF_VSOCK Cid and Port",
+ rsa: sockaddrVMToAny(RawSockaddrVM{
+ Family: AF_VSOCK,
+ Cid: VMADDR_CID_HOST,
+ Port: VMADDR_PORT_ANY,
+ }),
+ sa: &SockaddrVM{
+ CID: VMADDR_CID_HOST,
+ Port: VMADDR_PORT_ANY,
+ },
+ },
}
for _, tt := range tests {
@@ -121,6 +138,58 @@
}
}
+func TestSockaddVM_sockaddr(t *testing.T) {
+ tests := []struct {
+ name string
+ sa *SockaddrVM
+ raw *RawSockaddrVM
+ err error
+ }{
+ {
+ name: "empty",
+ sa: &SockaddrVM{},
+ raw: &RawSockaddrVM{
+ Len: SizeofSockaddrVM,
+ Family: AF_VSOCK,
+ },
+ },
+ {
+ name: "with CID and Port",
+ sa: &SockaddrVM{
+ CID: VMADDR_CID_HOST,
+ Port: VMADDR_PORT_ANY,
+ },
+ raw: &RawSockaddrVM{
+ Len: SizeofSockaddrVM,
+ Family: AF_VSOCK,
+ Port: VMADDR_PORT_ANY,
+ Cid: VMADDR_CID_HOST,
+ },
+ },
+ }
+
+ 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 != SizeofSockaddrVM) {
+ t.Fatalf("unexpected Socklen: %d", l)
+ }
+
+ if out != nil {
+ raw := (*RawSockaddrVM)(out)
+ if !reflect.DeepEqual(raw, tt.raw) {
+ t.Fatalf("unexpected RawSockaddrVM:\n got: %#v\nwant: %#v", raw, tt.raw)
+ }
+ }
+ })
+ }
+}
+
func sockaddrCtlToAny(in RawSockaddrCtl) *RawSockaddrAny {
var out RawSockaddrAny
copy(
@@ -129,3 +198,12 @@
)
return &out
}
+
+func sockaddrVMToAny(in RawSockaddrVM) *RawSockaddrAny {
+ var out RawSockaddrAny
+ copy(
+ (*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
+ (*(*[SizeofSockaddrVM]byte)(unsafe.Pointer(&in)))[:],
+ )
+ return &out
+}