]> Cypherpunks repositories - gostls13.git/commitdiff
net: fix WriteMsgUDPAddrPort addr handling
authordatabase64128 <free122448@hotmail.com>
Fri, 29 Apr 2022 17:29:58 +0000 (17:29 +0000)
committerIan Lance Taylor <iant@google.com>
Tue, 26 Jul 2022 20:27:23 +0000 (20:27 +0000)
WriteMsgUDPAddrPort should accept IPv4 target addresses on IPv6 UDP sockets.
An IPv4 target address will be converted to an IPv4-mapped IPv6 address.

Fixes #52264.

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>
src/net/ipsock_posix.go
src/net/udpsock_test.go

index 9a961b96ab252407f724490d4a5ebd969cd7503f..7bb66f2d6cce3d814c9a840f813c978b3597733e 100644 (file)
@@ -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{
index f8acf6a028a04fe757ebcbb9c2a91653faa9b07b..4fa74752b946dbf0d8bf2ceeb400444d2572673e 100644 (file)
@@ -9,6 +9,7 @@ package net
 import (
        "errors"
        "internal/testenv"
+       "net/netip"
        "os"
        "reflect"
        "runtime"
@@ -622,3 +623,45 @@ 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 "openbsd":
+               // 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)
+       }
+}