From 3ff754bf58a9922e2b8a1a0bd199be6c9a806123 Mon Sep 17 00:00:00 2001 From: Christian Svensson Date: Sun, 16 Aug 2020 22:12:57 +0000 Subject: [PATCH] unix: add AF_IUCV and SockaddrIUCV On z series machines the IUCV address family is used to communicate between parts of the machine and other VMs that may be running. This adds support for addressing these services using AF_IUCV. Fixes golang/go#40826 Change-Id: I3aba3beb5cb98d9c548d7abc874ca86fb25c8a52 GitHub-Last-Rev: b964d186b45dd907f4ae302ea9b1ff63e3592eb6 GitHub-Pull-Request: golang/sys#76 Reviewed-on: https://go-review.googlesource.com/c/sys/+/248777 Run-TryBot: Tobias Klauser TryBot-Result: Gobot Gobot Reviewed-by: Tobias Klauser --- unix/linux/types.go | 13 +++++++++ unix/syscall_internal_linux_test.go | 21 ++++++++++++++ unix/syscall_linux.go | 43 +++++++++++++++++++++++++++++ unix/ztypes_linux.go | 10 +++++++ 4 files changed, 87 insertions(+) diff --git a/unix/linux/types.go b/unix/linux/types.go index 31a20c7b..b1daba7f 100644 --- a/unix/linux/types.go +++ b/unix/linux/types.go @@ -257,6 +257,16 @@ struct my_sockaddr_un { #endif }; +// copied from /usr/include/netiucv/iucv.h modified with explicit signed chars. +struct sockaddr_iucv { + sa_family_t siucv_family; + unsigned short siucv_port; + unsigned int siucv_addr; + signed char siucv_nodeid[8]; + signed char siucv_user_id[8]; + signed char siucv_name[8]; +}; + #ifdef __ARM_EABI__ typedef struct user_regs PtraceRegs; #elif defined(__aarch64__) @@ -540,6 +550,8 @@ type RawSockaddrL2TPIP C.struct_sockaddr_l2tpip type RawSockaddrL2TPIP6 C.struct_sockaddr_l2tpip6 +type RawSockaddrIUCV C.struct_sockaddr_iucv + type RawSockaddr C.struct_sockaddr type RawSockaddrAny C.struct_sockaddr_any @@ -594,6 +606,7 @@ const ( SizeofSockaddrTIPC = C.sizeof_struct_sockaddr_tipc SizeofSockaddrL2TPIP = C.sizeof_struct_sockaddr_l2tpip SizeofSockaddrL2TPIP6 = C.sizeof_struct_sockaddr_l2tpip6 + SizeofSockaddrIUCV = C.sizeof_struct_sockaddr_iucv SizeofLinger = C.sizeof_struct_linger SizeofIovec = C.sizeof_struct_iovec SizeofIPMreq = C.sizeof_struct_ip_mreq diff --git a/unix/syscall_internal_linux_test.go b/unix/syscall_internal_linux_test.go index af48c2af..a690b991 100644 --- a/unix/syscall_internal_linux_test.go +++ b/unix/syscall_internal_linux_test.go @@ -156,6 +156,18 @@ func Test_anyToSockaddr(t *testing.T) { Name: "gopher", }, }, + { + name: "AF_IUCV", + rsa: sockaddrIUCVToAny(RawSockaddrIUCV{ + Family: AF_IUCV, + User_id: [8]int8{'*', 'M', 'S', 'G', ' ', ' ', ' ', ' '}, + Name: [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, + }), + sa: &SockaddrIUCV{ + UserID: "*MSG ", + Name: " ", + }, + }, { name: "AF_MAX EAFNOSUPPORT", rsa: &RawSockaddrAny{ @@ -505,3 +517,12 @@ func sockaddrUnixToAny(in RawSockaddrUnix) *RawSockaddrAny { return &out } + +func sockaddrIUCVToAny(in RawSockaddrIUCV) *RawSockaddrAny { + var out RawSockaddrAny + copy( + (*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:], + (*(*[SizeofSockaddrUnix]byte)(unsafe.Pointer(&in)))[:], + ) + return &out +} diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go index 027bcafd..e12f9bab 100644 --- a/unix/syscall_linux.go +++ b/unix/syscall_linux.go @@ -885,6 +885,32 @@ func (sa *SockaddrL2TPIP6) sockaddr() (unsafe.Pointer, _Socklen, error) { return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP6, nil } +// SockaddrIUCV implements the Sockaddr interface for AF_IUCV sockets. +type SockaddrIUCV struct { + UserID string + Name string + raw RawSockaddrIUCV +} + +func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Family = AF_IUCV + // These are EBCDIC encoded by the kernel, but we still need to pad them + // with blanks. Initializing with blanks allows the caller to feed in either + // a padded or an unpadded string. + for i := 0; i < 8; i++ { + sa.raw.Nodeid[i] = ' ' + sa.raw.User_id[i] = ' ' + sa.raw.Name[i] = ' ' + } + for i, b := range []byte(sa.UserID[:8]) { + sa.raw.User_id[i] = int8(b) + } + for i, b := range []byte(sa.Name[:8]) { + sa.raw.Name[i] = int8(b) + } + return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil +} + func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { switch rsa.Addr.Family { case AF_NETLINK: @@ -1065,6 +1091,23 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { } return sa, nil + case AF_IUCV: + pp := (*RawSockaddrIUCV)(unsafe.Pointer(rsa)) + + var user [8]byte + var name [8]byte + + for i := 0; i < 8; i++ { + user[i] = byte(pp.User_id[i]) + name[i] = byte(pp.Name[i]) + } + + sa := &SockaddrIUCV{ + UserID: string(user[:]), + Name: string(name[:]), + } + return sa, nil + } return nil, EAFNOSUPPORT } diff --git a/unix/ztypes_linux.go b/unix/ztypes_linux.go index 83364d75..77449a9e 100644 --- a/unix/ztypes_linux.go +++ b/unix/ztypes_linux.go @@ -310,6 +310,15 @@ type RawSockaddrL2TPIP6 struct { Conn_id uint32 } +type RawSockaddrIUCV struct { + Family uint16 + Port uint16 + Addr uint32 + Nodeid [8]int8 + User_id [8]int8 + Name [8]int8 +} + type _Socklen uint32 type Linger struct { @@ -422,6 +431,7 @@ const ( SizeofSockaddrTIPC = 0x10 SizeofSockaddrL2TPIP = 0x10 SizeofSockaddrL2TPIP6 = 0x20 + SizeofSockaddrIUCV = 0x20 SizeofLinger = 0x8 SizeofIPMreq = 0x8 SizeofIPMreqn = 0xc