diff options
| author | database64128 <free122448@hotmail.com> | 2025-07-25 15:14:16 +0800 |
|---|---|---|
| committer | Cherry Mui <cherryyz@google.com> | 2025-08-25 19:49:59 -0700 |
| commit | cdd8cf4988c7c0f2bb8eb795f74c4f803c63a70d (patch) | |
| tree | aa811b250ad726d12734cf347c22e8a167793753 | |
| parent | 8995e84ac64dd5d614f851a60d97ba026a9e6fb1 (diff) | |
| download | go-cdd8cf4988c7c0f2bb8eb795f74c4f803c63a70d.tar.xz | |
[release-branch.go1.25] net: fix WriteMsgUDPAddrPort addr handling on IPv4 sockets
Accept IPv4-mapped IPv6 destination addresses on IPv4 UDP sockets.
Fixes #74999.
Change-Id: I4624b9b8f861aedcae29e51d5298d23ce1c0f2c7
Reviewed-on: https://go-review.googlesource.com/c/go/+/689976
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
(cherry picked from commit bdb2d50fdf40706e7d7411f33ade80edac726707)
Reviewed-on: https://go-review.googlesource.com/c/go/+/695875
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
| -rw-r--r-- | src/net/ipsock_posix.go | 6 | ||||
| -rw-r--r-- | src/net/udpsock_test.go | 32 |
2 files changed, 37 insertions, 1 deletions
diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go index 2aeabd4487..52712f932f 100644 --- a/src/net/ipsock_posix.go +++ b/src/net/ipsock_posix.go @@ -237,8 +237,12 @@ func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, e func addrPortToSockaddrInet4(ap netip.AddrPort) (syscall.SockaddrInet4, error) { // ipToSockaddrInet4 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-mapped IPv6 address. + // As4 will unmap it to an IPv4 address. + // The error message is kept consistent with ipToSockaddrInet4. addr := ap.Addr() - if !addr.Is4() { + if !addr.Is4() && !addr.Is4In6() { return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: addr.String()} } sa := syscall.SockaddrInet4{ diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 6dacc81df6..7ad8a585b0 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -705,3 +705,35 @@ func TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) { t.Fatal(err) } } + +// TestIPv4WriteMsgUDPAddrPortTargetAddrIPVersion verifies that +// WriteMsgUDPAddrPort accepts IPv4 and IPv4-mapped IPv6 destination addresses, +// and rejects IPv6 destination addresses on a "udp4" connection. +func TestIPv4WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) { + if !testableNetwork("udp4") { + t.Skipf("skipping: udp4 not available") + } + + conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) + 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) + + if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4); err != nil { + t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr4) failed: %v", err) + } + + if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6); err != nil { + t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6) failed: %v", err) + } + + if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr6); err == nil { + t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr6) should have failed, but got no error") + } +} |
