Skip to content

Commit

Permalink
net: fix WriteMsgUDPAddrPort addr handling
Browse files Browse the repository at this point in the history
WriteMsgUDPAddrPort should accept IPv4 target addresses on IPv6 UDP sockets.
An IPv4 target address will be converted to an IPv4-mapped IPv6 address.

Fixes golang#52264.
  • Loading branch information
database64128 committed Apr 29, 2022
1 parent e7c56fe commit 6776fdb
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/net/ipsock_posix.go
Expand Up @@ -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{
Expand Down
43 changes: 43 additions & 0 deletions src/net/udpsock_test.go
Expand Up @@ -9,6 +9,7 @@ package net
import (
"errors"
"internal/testenv"
"net/netip"
"os"
"reflect"
"runtime"
Expand Down Expand Up @@ -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)
}
}

0 comments on commit 6776fdb

Please sign in to comment.