diff --git a/http2/server_test.go b/http2/server_test.go index 0a507294..7f644d4b 100644 --- a/http2/server_test.go +++ b/http2/server_test.go @@ -1189,10 +1189,9 @@ func TestServer_MaxQueuedControlFrames(t *testing.T) { } func TestServer_RejectsLargeFrames(t *testing.T) { - if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { + if runtime.GOOS == "windows" || runtime.GOOS == "plan9" || runtime.GOOS == "zos" { t.Skip("see golang.org/issue/13434, golang.org/issue/37321") } - st := newServerTester(t, nil) defer st.Close() st.greet() diff --git a/internal/socket/cmsghdr.go b/internal/socket/cmsghdr.go index 0a73e277..0cde35a4 100644 --- a/internal/socket/cmsghdr.go +++ b/internal/socket/cmsghdr.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package socket diff --git a/internal/socket/cmsghdr_stub.go b/internal/socket/cmsghdr_stub.go index 8328b7d1..83c35ecd 100644 --- a/internal/socket/cmsghdr_stub.go +++ b/internal/socket/cmsghdr_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos package socket diff --git a/internal/socket/cmsghdr_zos_s390x.go b/internal/socket/cmsghdr_zos_s390x.go new file mode 100644 index 00000000..98be146b --- /dev/null +++ b/internal/socket/cmsghdr_zos_s390x.go @@ -0,0 +1,25 @@ +// 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 socket + +import "syscall" + +func (h *cmsghdr) set(l, lvl, typ int) { + h.Len = int32(l) + h.Level = int32(lvl) + h.Type = int32(typ) +} + +func controlHeaderLen() int { + return syscall.CmsgLen(0) +} + +func controlMessageLen(dataLen int) int { + return syscall.CmsgLen(dataLen) +} + +func controlMessageSpace(dataLen int) int { + return syscall.CmsgSpace(dataLen) +} diff --git a/internal/socket/error_unix.go b/internal/socket/error_unix.go index f14872d3..47f0d6e2 100644 --- a/internal/socket/error_unix.go +++ b/internal/socket/error_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package socket diff --git a/internal/socket/iovec_64bit.go b/internal/socket/iovec_64bit.go index dfeda752..0309e10f 100644 --- a/internal/socket/iovec_64bit.go +++ b/internal/socket/iovec_64bit.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build arm64 amd64 ppc64 ppc64le mips64 mips64le riscv64 s390x -// +build aix darwin dragonfly freebsd linux netbsd openbsd +// +build aix darwin dragonfly freebsd linux netbsd openbsd zos package socket diff --git a/internal/socket/iovec_stub.go b/internal/socket/iovec_stub.go index a746e90e..f44d4f52 100644 --- a/internal/socket/iovec_stub.go +++ b/internal/socket/iovec_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos package socket diff --git a/internal/socket/msghdr_stub.go b/internal/socket/msghdr_stub.go index 873490a7..1a253d2d 100644 --- a/internal/socket/msghdr_stub.go +++ b/internal/socket/msghdr_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos package socket diff --git a/internal/socket/msghdr_zos_s390x.go b/internal/socket/msghdr_zos_s390x.go new file mode 100644 index 00000000..eb1a99a3 --- /dev/null +++ b/internal/socket/msghdr_zos_s390x.go @@ -0,0 +1,36 @@ +// 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. + +// +build s390x +// +build zos + +package socket + +import "unsafe" + +func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) { + for i := range vs { + vs[i].set(bs[i]) + } + if len(vs) > 0 { + h.Iov = &vs[0] + h.Iovlen = int32(len(vs)) + } + if len(oob) > 0 { + h.Control = (*byte)(unsafe.Pointer(&oob[0])) + h.Controllen = uint32(len(oob)) + } + if sa != nil { + h.Name = (*byte)(unsafe.Pointer(&sa[0])) + h.Namelen = uint32(len(sa)) + } +} + +func (h *msghdr) controllen() int { + return int(h.Controllen) +} + +func (h *msghdr) flags() int { + return int(h.Flags) +} diff --git a/internal/socket/rawconn_msg.go b/internal/socket/rawconn_msg.go index d5ae3f8e..610b1a1a 100644 --- a/internal/socket/rawconn_msg.go +++ b/internal/socket/rawconn_msg.go @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows zos package socket import ( "os" + "runtime" "syscall" ) @@ -24,7 +25,7 @@ func (c *Conn) recvMsg(m *Message, flags int) error { var n int fn := func(s uintptr) bool { n, operr = recvmsg(s, &h, flags) - if operr == syscall.EAGAIN { + if operr == syscall.EAGAIN || (runtime.GOOS == "zos" && operr == syscall.EWOULDBLOCK) { return false } return true @@ -61,7 +62,7 @@ func (c *Conn) sendMsg(m *Message, flags int) error { var n int fn := func(s uintptr) bool { n, operr = sendmsg(s, &h, flags) - if operr == syscall.EAGAIN { + if operr == syscall.EAGAIN || (runtime.GOOS == "zos" && operr == syscall.EWOULDBLOCK) { return false } return true diff --git a/internal/socket/rawconn_nomsg.go b/internal/socket/rawconn_nomsg.go index b8cea6fe..e51b60d1 100644 --- a/internal/socket/rawconn_nomsg.go +++ b/internal/socket/rawconn_nomsg.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package socket diff --git a/internal/socket/socket_test.go b/internal/socket/socket_test.go index 038e8e91..8952c221 100644 --- a/internal/socket/socket_test.go +++ b/internal/socket/socket_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows zos package socket_test diff --git a/internal/socket/sys_const_zos.go b/internal/socket/sys_const_zos.go new file mode 100644 index 00000000..01b63720 --- /dev/null +++ b/internal/socket/sys_const_zos.go @@ -0,0 +1,17 @@ +// 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. + +// +build zos + +package socket + +import "syscall" + +const ( + sysAF_UNSPEC = syscall.AF_UNSPEC + sysAF_INET = syscall.AF_INET + sysAF_INET6 = syscall.AF_INET6 + + sysSOCK_RAW = syscall.SOCK_RAW +) diff --git a/internal/socket/sys_posix.go b/internal/socket/sys_posix.go index 22eae809..05ded237 100644 --- a/internal/socket/sys_posix.go +++ b/internal/socket/sys_posix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows zos package socket diff --git a/internal/socket/sys_stub.go b/internal/socket/sys_stub.go index 8e1e0742..3c97008d 100644 --- a/internal/socket/sys_stub.go +++ b/internal/socket/sys_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package socket diff --git a/internal/socket/sys_zos_s390x.go b/internal/socket/sys_zos_s390x.go new file mode 100644 index 00000000..1e38b922 --- /dev/null +++ b/internal/socket/sys_zos_s390x.go @@ -0,0 +1,38 @@ +// 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 socket + +import ( + "syscall" + "unsafe" +) + +func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) +func syscall_syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) + +func probeProtocolStack() int { + return 4 // sizeof(int) on GOOS=zos GOARCH=s390x +} + +func getsockopt(s uintptr, level, name int, b []byte) (int, error) { + l := uint32(len(b)) + _, _, errno := syscall_syscall6(syscall.SYS_GETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0) + return int(l), errnoErr(errno) +} + +func setsockopt(s uintptr, level, name int, b []byte) error { + _, _, errno := syscall_syscall6(syscall.SYS_SETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0) + return errnoErr(errno) +} + +func recvmsg(s uintptr, h *msghdr, flags int) (int, error) { + n, _, errno := syscall_syscall(syscall.SYS___RECVMSG_A, s, uintptr(unsafe.Pointer(h)), uintptr(flags)) + return int(n), errnoErr(errno) +} + +func sendmsg(s uintptr, h *msghdr, flags int) (int, error) { + n, _, errno := syscall_syscall(syscall.SYS___SENDMSG_A, s, uintptr(unsafe.Pointer(h)), uintptr(flags)) + return int(n), errnoErr(errno) +} diff --git a/internal/socket/sys_zos_s390x.s b/internal/socket/sys_zos_s390x.s new file mode 100644 index 00000000..60d5839c --- /dev/null +++ b/internal/socket/sys_zos_s390x.s @@ -0,0 +1,11 @@ +// 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. + +#include "textflag.h" + +TEXT ·syscall_syscall(SB),NOSPLIT,$0 + JMP syscall·_syscall(SB) + +TEXT ·syscall_syscall6(SB),NOSPLIT,$0 + JMP syscall·_syscall6(SB) diff --git a/internal/socket/zsys_zos_s390x.go b/internal/socket/zsys_zos_s390x.go new file mode 100644 index 00000000..514ca375 --- /dev/null +++ b/internal/socket/zsys_zos_s390x.go @@ -0,0 +1,32 @@ +// 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 socket + +type iovec struct { + Base *byte + Len uint64 +} + +type msghdr struct { + Name *byte + Iov *iovec + Control *byte + Flags int32 + Namelen uint32 + Iovlen int32 + Controllen uint32 +} + +type cmsghdr struct { + Len int32 + Level int32 + Type int32 +} + +const ( + sizeofCmsghdr = 12 + sizeofSockaddrInet = 16 + sizeofSockaddrInet6 = 28 +) diff --git a/ipv4/control_stub.go b/ipv4/control_stub.go index a0c049d6..9d825347 100644 --- a/ipv4/control_stub.go +++ b/ipv4/control_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package ipv4 diff --git a/ipv4/control_zos.go b/ipv4/control_zos.go new file mode 100644 index 00000000..04420003 --- /dev/null +++ b/ipv4/control_zos.go @@ -0,0 +1,86 @@ +// 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 ipv4 + +import ( + "net" + "unsafe" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" +) + +func marshalPacketInfo(b []byte, cm *ControlMessage) []byte { + m := socket.ControlMessage(b) + m.MarshalHeader(iana.ProtocolIP, sysIP_PKTINFO, sizeofInetPktinfo) + if cm != nil { + pi := (*inetPktinfo)(unsafe.Pointer(&m.Data(sizeofInetPktinfo)[0])) + if ip := cm.Src.To4(); ip != nil { + copy(pi.Addr[:], ip) + } + if cm.IfIndex > 0 { + pi.setIfindex(cm.IfIndex) + } + } + return m.Next(sizeofInetPktinfo) +} + +func parsePacketInfo(cm *ControlMessage, b []byte) { + pi := (*inetPktinfo)(unsafe.Pointer(&b[0])) + cm.IfIndex = int(pi.Ifindex) + if len(cm.Dst) < net.IPv4len { + cm.Dst = make(net.IP, net.IPv4len) + } + copy(cm.Dst, pi.Addr[:]) +} + +func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error { + opt.Lock() + defer opt.Unlock() + if so, ok := sockOpts[ssoReceiveTTL]; ok && cf&FlagTTL != 0 { + if err := so.SetInt(c, boolint(on)); err != nil { + return err + } + if on { + opt.set(FlagTTL) + } else { + opt.clear(FlagTTL) + } + } + if so, ok := sockOpts[ssoPacketInfo]; ok { + if cf&(FlagSrc|FlagDst|FlagInterface) != 0 { + if err := so.SetInt(c, boolint(on)); err != nil { + return err + } + if on { + opt.set(cf & (FlagSrc | FlagDst | FlagInterface)) + } else { + opt.clear(cf & (FlagSrc | FlagDst | FlagInterface)) + } + } + } else { + if so, ok := sockOpts[ssoReceiveDst]; ok && cf&FlagDst != 0 { + if err := so.SetInt(c, boolint(on)); err != nil { + return err + } + if on { + opt.set(FlagDst) + } else { + opt.clear(FlagDst) + } + } + if so, ok := sockOpts[ssoReceiveInterface]; ok && cf&FlagInterface != 0 { + if err := so.SetInt(c, boolint(on)); err != nil { + return err + } + if on { + opt.set(FlagInterface) + } else { + opt.clear(FlagInterface) + } + } + } + return nil +} diff --git a/ipv4/helper_posix_test.go b/ipv4/helper_posix_test.go index ee66dd28..638eaf28 100644 --- a/ipv4/helper_posix_test.go +++ b/ipv4/helper_posix_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows zos package ipv4_test diff --git a/ipv4/helper_stub_test.go b/ipv4/helper_stub_test.go index 4ba01714..03ad2a92 100644 --- a/ipv4/helper_stub_test.go +++ b/ipv4/helper_stub_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package ipv4_test diff --git a/ipv4/multicast_test.go b/ipv4/multicast_test.go index 57e7a960..09463bff 100644 --- a/ipv4/multicast_test.go +++ b/ipv4/multicast_test.go @@ -30,7 +30,7 @@ var packetConnReadWriteMulticastUDPTests = []struct { func TestPacketConnReadWriteMulticastUDP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "illumos", "js", "nacl", "plan9", "solaris", "windows": + case "fuchsia", "hurd", "illumos", "js", "nacl", "plan9", "solaris", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } ifi, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) @@ -139,6 +139,11 @@ func TestPacketConnReadWriteMulticastICMP(t *testing.T) { t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) } ifi, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) + // Unable to obtain loopback interface on z/OS, so instead we test on any multicast + // capable interface. + if runtime.GOOS == "zos" { + ifi, err = nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast) + } if err != nil { t.Skip(err) } diff --git a/ipv4/multicastlistener_test.go b/ipv4/multicastlistener_test.go index dc3f199a..534ded67 100644 --- a/ipv4/multicastlistener_test.go +++ b/ipv4/multicastlistener_test.go @@ -21,7 +21,7 @@ var udpMultipleGroupListenerTests = []net.Addr{ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { @@ -61,7 +61,7 @@ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) { func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { @@ -116,7 +116,7 @@ func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) { func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { @@ -172,7 +172,7 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { @@ -217,7 +217,7 @@ func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) { func TestIPPerInterfaceSingleRawConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { diff --git a/ipv4/multicastsockopt_test.go b/ipv4/multicastsockopt_test.go index 234c775b..b0ddd071 100644 --- a/ipv4/multicastsockopt_test.go +++ b/ipv4/multicastsockopt_test.go @@ -26,7 +26,7 @@ var packetConnMulticastSocketOptionTests = []struct { func TestPacketConnMulticastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9": + case "fuchsia", "hurd", "js", "nacl", "plan9", "zos": t.Skipf("not supported on %s", runtime.GOOS) } ifi, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) @@ -66,7 +66,7 @@ var rawConnMulticastSocketOptionTests = []struct { func TestRawConnMulticastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9": + case "fuchsia", "hurd", "js", "nacl", "plan9", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsRawSocket() { diff --git a/ipv4/payload_cmsg.go b/ipv4/payload_cmsg.go index e7614661..7bde6894 100644 --- a/ipv4/payload_cmsg.go +++ b/ipv4/payload_cmsg.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package ipv4 diff --git a/ipv4/payload_nocmsg.go b/ipv4/payload_nocmsg.go index 1116256f..251bd0c7 100644 --- a/ipv4/payload_nocmsg.go +++ b/ipv4/payload_nocmsg.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos package ipv4 diff --git a/ipv4/sockopt_posix.go b/ipv4/sockopt_posix.go index dea64519..ef29718d 100644 --- a/ipv4/sockopt_posix.go +++ b/ipv4/sockopt_posix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows zos package ipv4 diff --git a/ipv4/sockopt_stub.go b/ipv4/sockopt_stub.go index 37d4806b..fbca5268 100644 --- a/ipv4/sockopt_stub.go +++ b/ipv4/sockopt_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package ipv4 diff --git a/ipv4/sys_stub.go b/ipv4/sys_stub.go index b9c85b33..55558518 100644 --- a/ipv4/sys_stub.go +++ b/ipv4/sys_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package ipv4 diff --git a/ipv4/sys_zos.go b/ipv4/sys_zos.go new file mode 100644 index 00000000..7426606c --- /dev/null +++ b/ipv4/sys_zos.go @@ -0,0 +1,55 @@ +// 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 ipv4 + +import ( + "net" + "syscall" + "unsafe" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" +) + +var ( + ctlOpts = [ctlMax]ctlOpt{ + ctlPacketInfo: {sysIP_PKTINFO, sizeofInetPktinfo, marshalPacketInfo, parsePacketInfo}, + } + + sockOpts = map[int]*sockOpt{ + ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}}, + ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}}, + ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 1}}, + ssoPacketInfo: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVPKTINFO, Len: 4}}, + ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + } +) + +func (pi *inetPktinfo) setIfindex(i int) { + pi.Ifindex = uint32(i) +} + +func (gr *groupReq) setGroup(grp net.IP) { + sa := (*sockaddrInet4)(unsafe.Pointer(&gr.Group)) + sa.Family = syscall.AF_INET + sa.Len = sizeofSockaddrInet4 + copy(sa.Addr[:], grp) +} + +func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) { + sa := (*sockaddrInet4)(unsafe.Pointer(&gsr.Group)) + sa.Family = syscall.AF_INET + sa.Len = sizeofSockaddrInet4 + copy(sa.Addr[:], grp) + sa = (*sockaddrInet4)(unsafe.Pointer(&gsr.Source)) + sa.Family = syscall.AF_INET + sa.Len = sizeofSockaddrInet4 + copy(sa.Addr[:], src) +} diff --git a/ipv4/unicast_test.go b/ipv4/unicast_test.go index fce18b0d..a2b03387 100644 --- a/ipv4/unicast_test.go +++ b/ipv4/unicast_test.go @@ -23,7 +23,9 @@ func TestPacketConnReadWriteUnicastUDP(t *testing.T) { case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": t.Skipf("not supported on %s", runtime.GOOS) } - if _, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); err != nil { + // Skip this check on z/OS since net.Interfaces() does not return loopback, however + // this does not affect the test and it will still pass. + if _, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); err != nil && runtime.GOOS != "zos" { t.Skipf("not available on %s", runtime.GOOS) } @@ -76,7 +78,9 @@ func TestPacketConnReadWriteUnicastICMP(t *testing.T) { if !nettest.SupportsRawSocket() { t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) } - if _, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); err != nil { + // Skip this check on z/OS since net.Interfaces() does not return loopback, however + // this does not affect the test and it will still pass. + if _, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); err != nil && runtime.GOOS != "zos" { t.Skipf("not available on %s", runtime.GOOS) } diff --git a/ipv4/unicastsockopt_test.go b/ipv4/unicastsockopt_test.go index 7527bc17..58d653ea 100644 --- a/ipv4/unicastsockopt_test.go +++ b/ipv4/unicastsockopt_test.go @@ -16,7 +16,7 @@ import ( func TestConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if _, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); err != nil { @@ -61,7 +61,7 @@ var packetConnUnicastSocketOptionTests = []struct { func TestPacketConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if _, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); err != nil { @@ -86,7 +86,7 @@ func TestPacketConnUnicastSocketOptions(t *testing.T) { func TestRawConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsRawSocket() { diff --git a/ipv4/zsys_zos_s390x.go b/ipv4/zsys_zos_s390x.go new file mode 100644 index 00000000..4bbfda07 --- /dev/null +++ b/ipv4/zsys_zos_s390x.go @@ -0,0 +1,80 @@ +// 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. + +// Hand edited based on zerrors_zos_s390x.go +// TODO(Bill O'Farrell): auto-generate. + +package ipv4 + +const ( + sysIP_ADD_MEMBERSHIP = 5 + sysIP_ADD_SOURCE_MEMBERSHIP = 12 + sysIP_BLOCK_SOURCE = 10 + sysIP_DEFAULT_MULTICAST_LOOP = 1 + sysIP_DEFAULT_MULTICAST_TTL = 1 + sysIP_DROP_MEMBERSHIP = 6 + sysIP_DROP_SOURCE_MEMBERSHIP = 13 + sysIP_MAX_MEMBERSHIPS = 20 + sysIP_MULTICAST_IF = 7 + sysIP_MULTICAST_LOOP = 4 + sysIP_MULTICAST_TTL = 3 + sysIP_OPTIONS = 1 + sysIP_PKTINFO = 101 + sysIP_RECVPKTINFO = 102 + sysIP_TOS = 2 + sysIP_UNBLOCK_SOURCE = 11 + + sysMCAST_JOIN_GROUP = 40 + sysMCAST_LEAVE_GROUP = 41 + sysMCAST_JOIN_SOURCE_GROUP = 42 + sysMCAST_LEAVE_SOURCE_GROUP = 43 + sysMCAST_BLOCK_SOURCE = 44 + sysMCAST_UNBLOCK_SOURCE = 45 + + sizeofIPMreq = 8 + sizeofSockaddrInet4 = 16 + sizeofSockaddrStorage = 128 + sizeofGroupReq = 136 + sizeofGroupSourceReq = 264 + sizeofInetPktinfo = 8 +) + +type sockaddrInet4 struct { + Len uint8 + Family uint8 + Port uint16 + Addr [4]byte + Zero [8]uint8 +} + +type inetPktinfo struct { + Addr [4]byte + Ifindex uint32 +} + +type sockaddrStorage struct { + Len uint8 + Family byte + ss_pad1 [6]byte + ss_align int64 + ss_pad2 [112]byte +} + +type groupReq struct { + Interface uint32 + reserved uint32 + Group sockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + reserved uint32 + Group sockaddrStorage + Source sockaddrStorage +} + +type ipMreq struct { + Multiaddr [4]byte /* in_addr */ + Interface [4]byte /* in_addr */ +} diff --git a/ipv6/control_rfc3542_unix.go b/ipv6/control_rfc3542_unix.go index 8c221b59..77c449ec 100644 --- a/ipv6/control_rfc3542_unix.go +++ b/ipv6/control_rfc3542_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package ipv6 diff --git a/ipv6/control_stub.go b/ipv6/control_stub.go index 1d773cbc..e50b8864 100644 --- a/ipv6/control_stub.go +++ b/ipv6/control_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package ipv6 diff --git a/ipv6/control_unix.go b/ipv6/control_unix.go index 0971a008..ec31ca2a 100644 --- a/ipv6/control_unix.go +++ b/ipv6/control_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package ipv6 diff --git a/ipv6/helper_posix_test.go b/ipv6/helper_posix_test.go index cc85cea3..6f5e78f0 100644 --- a/ipv6/helper_posix_test.go +++ b/ipv6/helper_posix_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows zos package ipv6_test diff --git a/ipv6/helper_stub_test.go b/ipv6/helper_stub_test.go index cc515d1b..066de62a 100644 --- a/ipv6/helper_stub_test.go +++ b/ipv6/helper_stub_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package ipv6_test diff --git a/ipv6/helper_unix_test.go b/ipv6/helper_unix_test.go index d94d912a..e76d1ca8 100644 --- a/ipv6/helper_unix_test.go +++ b/ipv6/helper_unix_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package ipv6_test diff --git a/ipv6/icmp_stub.go b/ipv6/icmp_stub.go index 370e51ac..297e191f 100644 --- a/ipv6/icmp_stub.go +++ b/ipv6/icmp_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package ipv6 diff --git a/ipv6/icmp_zos.go b/ipv6/icmp_zos.go new file mode 100644 index 00000000..ddf8f093 --- /dev/null +++ b/ipv6/icmp_zos.go @@ -0,0 +1,29 @@ +// 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 ipv6 + +func (f *icmpv6Filter) accept(typ ICMPType) { + f.Filt[typ>>5] |= 1 << (uint32(typ) & 31) + +} + +func (f *icmpv6Filter) block(typ ICMPType) { + f.Filt[typ>>5] &^= 1 << (uint32(typ) & 31) + +} + +func (f *icmpv6Filter) setAll(block bool) { + for i := range f.Filt { + if block { + f.Filt[i] = 0 + } else { + f.Filt[i] = 1<<32 - 1 + } + } +} + +func (f *icmpv6Filter) willBlock(typ ICMPType) bool { + return f.Filt[typ>>5]&(1<<(uint32(typ)&31)) == 0 +} diff --git a/ipv6/multicastlistener_test.go b/ipv6/multicastlistener_test.go index 66699ab7..353327e0 100644 --- a/ipv6/multicastlistener_test.go +++ b/ipv6/multicastlistener_test.go @@ -61,7 +61,7 @@ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) { func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { diff --git a/ipv6/payload_cmsg.go b/ipv6/payload_cmsg.go index 284a0427..8baa26e7 100644 --- a/ipv6/payload_cmsg.go +++ b/ipv6/payload_cmsg.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package ipv6 diff --git a/ipv6/payload_nocmsg.go b/ipv6/payload_nocmsg.go index c5a4c967..00c4f587 100644 --- a/ipv6/payload_nocmsg.go +++ b/ipv6/payload_nocmsg.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos package ipv6 diff --git a/ipv6/sockopt_posix.go b/ipv6/sockopt_posix.go index 824c623c..f7187927 100644 --- a/ipv6/sockopt_posix.go +++ b/ipv6/sockopt_posix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows zos package ipv6 diff --git a/ipv6/sockopt_stub.go b/ipv6/sockopt_stub.go index 0a87a93b..d87db6a0 100644 --- a/ipv6/sockopt_stub.go +++ b/ipv6/sockopt_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package ipv6 diff --git a/ipv6/sockopt_test.go b/ipv6/sockopt_test.go index cbba049c..8ac322b0 100644 --- a/ipv6/sockopt_test.go +++ b/ipv6/sockopt_test.go @@ -17,7 +17,7 @@ import ( func TestConnInitiatorPathMTU(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { @@ -55,7 +55,7 @@ func TestConnInitiatorPathMTU(t *testing.T) { func TestConnResponderPathMTU(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { diff --git a/ipv6/sys_ssmreq.go b/ipv6/sys_ssmreq.go index 9b52e978..88d64f17 100644 --- a/ipv6/sys_ssmreq.go +++ b/ipv6/sys_ssmreq.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin freebsd linux solaris +// +build aix darwin freebsd linux solaris zos package ipv6 diff --git a/ipv6/sys_ssmreq_stub.go b/ipv6/sys_ssmreq_stub.go index d5bc1108..b0708868 100644 --- a/ipv6/sys_ssmreq_stub.go +++ b/ipv6/sys_ssmreq_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!freebsd,!linux,!solaris +// +build !aix,!darwin,!freebsd,!linux,!solaris,!zos package ipv6 diff --git a/ipv6/sys_stub.go b/ipv6/sys_stub.go index 4f252d09..cbe4a029 100644 --- a/ipv6/sys_stub.go +++ b/ipv6/sys_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package ipv6 diff --git a/ipv6/sys_zos.go b/ipv6/sys_zos.go new file mode 100644 index 00000000..d4567f90 --- /dev/null +++ b/ipv6/sys_zos.go @@ -0,0 +1,70 @@ +// 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 ipv6 + +import ( + "net" + "syscall" + "unsafe" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" +) + +var ( + ctlOpts = [ctlMax]ctlOpt{ + ctlHopLimit: {sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit}, + ctlPacketInfo: {sysIPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo}, + ctlPathMTU: {sysIPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU}, + } + + sockOpts = map[int]*sockOpt{ + ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_TCLASS, Len: 4}}, + ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_UNICAST_HOPS, Len: 4}}, + ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_IF, Len: 4}}, + ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_HOPS, Len: 4}}, + ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_MULTICAST_LOOP, Len: 4}}, + ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVTCLASS, Len: 4}}, + ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVHOPLIMIT, Len: 4}}, + ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPKTINFO, Len: 4}}, + ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_RECVPATHMTU, Len: 4}}, + ssoChecksum: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysIPV6_CHECKSUM, Len: 4}}, + ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: sysICMP6_FILTER, Len: sizeofICMPv6Filter}}, + ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + } +) + +func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) { + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(i) +} + +func (pi *inet6Pktinfo) setIfindex(i int) { + pi.Ifindex = uint32(i) +} + +func (gr *groupReq) setGroup(grp net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(&gr.Group)) + sa.Family = syscall.AF_INET6 + sa.Len = sizeofSockaddrInet6 + copy(sa.Addr[:], grp) +} + +func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(&gsr.Group)) + sa.Family = syscall.AF_INET6 + sa.Len = sizeofSockaddrInet6 + copy(sa.Addr[:], grp) + sa = (*sockaddrInet6)(unsafe.Pointer(&gsr.Source)) + sa.Family = syscall.AF_INET6 + sa.Len = sizeofSockaddrInet6 + copy(sa.Addr[:], src) +} diff --git a/ipv6/unicast_test.go b/ipv6/unicast_test.go index a7429f41..32c42c92 100644 --- a/ipv6/unicast_test.go +++ b/ipv6/unicast_test.go @@ -78,7 +78,7 @@ func TestPacketConnReadWriteUnicastUDP(t *testing.T) { func TestPacketConnReadWriteUnicastICMP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { diff --git a/ipv6/zsys_zos_s390x.go b/ipv6/zsys_zos_s390x.go new file mode 100644 index 00000000..3f980691 --- /dev/null +++ b/ipv6/zsys_zos_s390x.go @@ -0,0 +1,106 @@ +// 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. + +// Hand edited based on zerrors_zos_s390x.go +// TODO(Bill O'Farrell): auto-generate. + +package ipv6 + +const ( + sysIPV6_ADDR_PREFERENCES = 32 + sysIPV6_CHECKSUM = 19 + sysIPV6_DONTFRAG = 29 + sysIPV6_DSTOPTS = 23 + sysIPV6_HOPLIMIT = 11 + sysIPV6_HOPOPTS = 22 + sysIPV6_JOIN_GROUP = 5 + sysIPV6_LEAVE_GROUP = 6 + sysIPV6_MULTICAST_HOPS = 9 + sysIPV6_MULTICAST_IF = 7 + sysIPV6_MULTICAST_LOOP = 4 + sysIPV6_NEXTHOP = 20 + sysIPV6_PATHMTU = 12 + sysIPV6_PKTINFO = 13 + sysIPV6_PREFER_SRC_CGA = 0x10 + sysIPV6_PREFER_SRC_COA = 0x02 + sysIPV6_PREFER_SRC_HOME = 0x01 + sysIPV6_PREFER_SRC_NONCGA = 0x20 + sysIPV6_PREFER_SRC_PUBLIC = 0x08 + sysIPV6_PREFER_SRC_TMP = 0x04 + sysIPV6_RECVDSTOPTS = 28 + sysIPV6_RECVHOPLIMIT = 14 + sysIPV6_RECVHOPOPTS = 26 + sysIPV6_RECVPATHMTU = 16 + sysIPV6_RECVPKTINFO = 15 + sysIPV6_RECVRTHDR = 25 + sysIPV6_RECVTCLASS = 31 + sysIPV6_RTHDR = 21 + sysIPV6_RTHDRDSTOPTS = 24 + sysIPV6_RTHDR_TYPE_0 = 0 + sysIPV6_TCLASS = 30 + sysIPV6_UNICAST_HOPS = 3 + sysIPV6_USE_MIN_MTU = 18 + sysIPV6_V6ONLY = 10 + + sysMCAST_JOIN_GROUP = 40 + sysMCAST_LEAVE_GROUP = 41 + sysMCAST_JOIN_SOURCE_GROUP = 42 + sysMCAST_LEAVE_SOURCE_GROUP = 43 + sysMCAST_BLOCK_SOURCE = 44 + sysMCAST_UNBLOCK_SOURCE = 45 + + sysICMP6_FILTER = 0x1 + + sizeofSockaddrStorage = 128 + sizeofICMPv6Filter = 32 + sizeofInet6Pktinfo = 20 + sizeofIPv6Mtuinfo = 32 + sizeofSockaddrInet6 = 28 + sizeofGroupReq = 136 + sizeofGroupSourceReq = 264 +) + +type sockaddrStorage struct { + Len uint8 + Family byte + ss_pad1 [6]byte + ss_align int64 + ss_pad2 [112]byte +} + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type groupReq struct { + Interface uint32 + reserved uint32 + Group sockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + reserved uint32 + Group sockaddrStorage + Source sockaddrStorage +} + +type icmpv6Filter struct { + Filt [8]uint32 +} diff --git a/nettest/nettest.go b/nettest/nettest.go index 953562f7..83ba858e 100644 --- a/nettest/nettest.go +++ b/nettest/nettest.go @@ -126,7 +126,7 @@ func TestableNetwork(network string) bool { } case "unixpacket": switch runtime.GOOS { - case "aix", "android", "fuchsia", "hurd", "darwin", "ios", "js", "nacl", "plan9", "windows": + case "aix", "android", "fuchsia", "hurd", "darwin", "ios", "js", "nacl", "plan9", "windows", "zos": return false case "netbsd": // It passes on amd64 at least. 386 fails diff --git a/nettest/nettest_stub.go b/nettest/nettest_stub.go index 2bb8c057..22c2461c 100644 --- a/nettest/nettest_stub.go +++ b/nettest/nettest_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package nettest diff --git a/nettest/nettest_unix.go b/nettest/nettest_unix.go index afff744e..c1b13593 100644 --- a/nettest/nettest_unix.go +++ b/nettest/nettest_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package nettest diff --git a/webdav/file.go b/webdav/file.go index 9f537787..3fcc0539 100644 --- a/webdav/file.go +++ b/webdav/file.go @@ -12,6 +12,7 @@ import ( "os" "path" "path/filepath" + "runtime" "strings" "sync" "time" @@ -272,8 +273,14 @@ func (fs *memFS) OpenFile(ctx context.Context, name string, flag int, perm os.Fi var n *memFSNode if dir == nil { // We're opening the root. - if flag&(os.O_WRONLY|os.O_RDWR) != 0 { - return nil, os.ErrPermission + if runtime.GOOS == "zos" { + if flag&os.O_WRONLY != 0 { + return nil, os.ErrPermission + } + } else { + if flag&(os.O_WRONLY|os.O_RDWR) != 0 { + return nil, os.ErrPermission + } } n, frag = &fs.root, "/"