Skip to content

Commit bdb2d50

Browse files
database64128seankhliao
authored andcommitted
net: fix WriteMsgUDPAddrPort addr handling on IPv4 sockets
Accept IPv4-mapped IPv6 destination addresses on IPv4 UDP sockets. Fixes #74737. Change-Id: I4624b9b8f861aedcae29e51d5298d23ce1c0f2c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/689976 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Mark Freeman <[email protected]> Reviewed-by: Damien Neil <[email protected]>
1 parent 768c51e commit bdb2d50

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

src/net/ipsock_posix.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,12 @@ func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, e
237237
func addrPortToSockaddrInet4(ap netip.AddrPort) (syscall.SockaddrInet4, error) {
238238
// ipToSockaddrInet4 has special handling here for zero length slices.
239239
// We do not, because netip has no concept of a generic zero IP address.
240+
//
241+
// addr is allowed to be an IPv4-mapped IPv6 address.
242+
// As4 will unmap it to an IPv4 address.
243+
// The error message is kept consistent with ipToSockaddrInet4.
240244
addr := ap.Addr()
241-
if !addr.Is4() {
245+
if !addr.Is4() && !addr.Is4In6() {
242246
return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: addr.String()}
243247
}
244248
sa := syscall.SockaddrInet4{

src/net/udpsock_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,3 +705,35 @@ func TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) {
705705
t.Fatal(err)
706706
}
707707
}
708+
709+
// TestIPv4WriteMsgUDPAddrPortTargetAddrIPVersion verifies that
710+
// WriteMsgUDPAddrPort accepts IPv4 and IPv4-mapped IPv6 destination addresses,
711+
// and rejects IPv6 destination addresses on a "udp4" connection.
712+
func TestIPv4WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) {
713+
if !testableNetwork("udp4") {
714+
t.Skipf("skipping: udp4 not available")
715+
}
716+
717+
conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
718+
if err != nil {
719+
t.Fatal(err)
720+
}
721+
defer conn.Close()
722+
723+
daddr4 := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), 12345)
724+
daddr4in6 := netip.AddrPortFrom(netip.MustParseAddr("::ffff:127.0.0.1"), 12345)
725+
daddr6 := netip.AddrPortFrom(netip.MustParseAddr("::1"), 12345)
726+
buf := make([]byte, 8)
727+
728+
if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4); err != nil {
729+
t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr4) failed: %v", err)
730+
}
731+
732+
if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6); err != nil {
733+
t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6) failed: %v", err)
734+
}
735+
736+
if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr6); err == nil {
737+
t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr6) should have failed, but got no error")
738+
}
739+
}

0 commit comments

Comments
 (0)