aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordatabase64128 <free122448@hotmail.com>2022-04-29 17:29:58 +0000
committerDmitri Shuralyov <dmitshur@golang.org>2022-08-26 18:28:14 +0000
commitbf812b32b0b4105342af981330a4ffd50a2fb28e (patch)
tree31bee31bc3f67b8fb1a4ed08eedf7b8023792457
parent27ced96c8d4709eeb57aa5dde31acff7e51a8a4a (diff)
downloadgo-bf812b32b0b4105342af981330a4ffd50a2fb28e.tar.gz
go-bf812b32b0b4105342af981330a4ffd50a2fb28e.zip
[release-branch.go1.18] net: fix WriteMsgUDPAddrPort addr handling
WriteMsgUDPAddrPort should accept IPv4 target addresses on IPv6 UDP sockets. An IPv4 target address will be converted to an IPv4-mapped IPv6 address. Include the change in CL 420775 to also skip the test on DragonflyBSD. Updates #52264. Fixes #54074. Change-Id: Ib9ed4c61fa1289ae7bbc8c4c9de1a9951b647ec0 GitHub-Last-Rev: 6776fdb0a76faa71ebde58f5143fb1ffb3112adf GitHub-Pull-Request: golang/go#52265 Reviewed-on: https://go-review.googlesource.com/c/go/+/399454 TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-on: https://go-review.googlesource.com/c/go/+/425488 Reviewed-by: David Chase <drchase@google.com> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
-rw-r--r--src/net/ipsock_posix.go6
-rw-r--r--src/net/udpsock_test.go45
2 files changed, 50 insertions, 1 deletions
diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go
index e433e8a91c7..b3868454e48 100644
--- a/src/net/ipsock_posix.go
+++ b/src/net/ipsock_posix.go
@@ -215,8 +215,12 @@ func addrPortToSockaddrInet4(ap netip.AddrPort) (syscall.SockaddrInet4, error) {
func addrPortToSockaddrInet6(ap netip.AddrPort) (syscall.SockaddrInet6, error) {
// ipToSockaddrInet6 has special handling here for zero length slices.
// We do not, because netip has no concept of a generic zero IP address.
+ //
+ // addr is allowed to be an IPv4 address, because As16 will convert it
+ // to an IPv4-mapped IPv6 address.
+ // The error message is kept consistent with ipToSockaddrInet6.
addr := ap.Addr()
- if !addr.Is6() {
+ if !addr.IsValid() {
return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: addr.String()}
}
sa := syscall.SockaddrInet6{
diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go
index f8acf6a028a..4ceacde10e4 100644
--- a/src/net/udpsock_test.go
+++ b/src/net/udpsock_test.go
@@ -9,6 +9,7 @@ package net
import (
"errors"
"internal/testenv"
+ "net/netip"
"os"
"reflect"
"runtime"
@@ -622,3 +623,47 @@ func TestUDPIPVersionReadMsg(t *testing.T) {
t.Error("returned UDPAddr is not IPv4")
}
}
+
+// TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion verifies that
+// WriteMsgUDPAddrPort accepts IPv4, IPv4-mapped IPv6, and IPv6 target addresses
+// on a UDPConn listening on "::".
+func TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) {
+ if !supportsIPv6() {
+ t.Skip("IPv6 is not supported")
+ }
+
+ switch runtime.GOOS {
+ case "dragonfly", "openbsd":
+ // DragonflyBSD's IPv6 sockets are always IPv6-only, according to the man page:
+ // https://www.dragonflybsd.org/cgi/web-man?command=ip6 (search for IPV6_V6ONLY).
+ // OpenBSD's IPv6 sockets are always IPv6-only, according to the man page:
+ // https://man.openbsd.org/ip6#IPV6_V6ONLY
+ t.Skipf("skipping on %v", runtime.GOOS)
+ }
+
+ conn, err := ListenUDP("udp", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer conn.Close()
+
+ daddr4 := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), 12345)
+ daddr4in6 := netip.AddrPortFrom(netip.MustParseAddr("::ffff:127.0.0.1"), 12345)
+ daddr6 := netip.AddrPortFrom(netip.MustParseAddr("::1"), 12345)
+ buf := make([]byte, 8)
+
+ _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr6)
+ if err != nil {
+ t.Fatal(err)
+ }
+}