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