Skip to content

Commit bf812b3

Browse files
database64128dmitshur
authored andcommitted
[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: 6776fdb GitHub-Pull-Request: #52265 Reviewed-on: https://go-review.googlesource.com/c/go/+/399454 TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Damien Neil <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]> Reviewed-on: https://go-review.googlesource.com/c/go/+/425488 Reviewed-by: David Chase <[email protected]> Run-TryBot: Dmitri Shuralyov <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
1 parent 27ced96 commit bf812b3

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/net/ipsock_posix.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,12 @@ func addrPortToSockaddrInet4(ap netip.AddrPort) (syscall.SockaddrInet4, error) {
215215
func addrPortToSockaddrInet6(ap netip.AddrPort) (syscall.SockaddrInet6, error) {
216216
// ipToSockaddrInet6 has special handling here for zero length slices.
217217
// We do not, because netip has no concept of a generic zero IP address.
218+
//
219+
// addr is allowed to be an IPv4 address, because As16 will convert it
220+
// to an IPv4-mapped IPv6 address.
221+
// The error message is kept consistent with ipToSockaddrInet6.
218222
addr := ap.Addr()
219-
if !addr.Is6() {
223+
if !addr.IsValid() {
220224
return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: addr.String()}
221225
}
222226
sa := syscall.SockaddrInet6{

src/net/udpsock_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package net
99
import (
1010
"errors"
1111
"internal/testenv"
12+
"net/netip"
1213
"os"
1314
"reflect"
1415
"runtime"
@@ -622,3 +623,47 @@ func TestUDPIPVersionReadMsg(t *testing.T) {
622623
t.Error("returned UDPAddr is not IPv4")
623624
}
624625
}
626+
627+
// TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion verifies that
628+
// WriteMsgUDPAddrPort accepts IPv4, IPv4-mapped IPv6, and IPv6 target addresses
629+
// on a UDPConn listening on "::".
630+
func TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) {
631+
if !supportsIPv6() {
632+
t.Skip("IPv6 is not supported")
633+
}
634+
635+
switch runtime.GOOS {
636+
case "dragonfly", "openbsd":
637+
// DragonflyBSD's IPv6 sockets are always IPv6-only, according to the man page:
638+
// https://www.dragonflybsd.org/cgi/web-man?command=ip6 (search for IPV6_V6ONLY).
639+
// OpenBSD's IPv6 sockets are always IPv6-only, according to the man page:
640+
// https://man.openbsd.org/ip6#IPV6_V6ONLY
641+
t.Skipf("skipping on %v", runtime.GOOS)
642+
}
643+
644+
conn, err := ListenUDP("udp", nil)
645+
if err != nil {
646+
t.Fatal(err)
647+
}
648+
defer conn.Close()
649+
650+
daddr4 := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), 12345)
651+
daddr4in6 := netip.AddrPortFrom(netip.MustParseAddr("::ffff:127.0.0.1"), 12345)
652+
daddr6 := netip.AddrPortFrom(netip.MustParseAddr("::1"), 12345)
653+
buf := make([]byte, 8)
654+
655+
_, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4)
656+
if err != nil {
657+
t.Fatal(err)
658+
}
659+
660+
_, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6)
661+
if err != nil {
662+
t.Fatal(err)
663+
}
664+
665+
_, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr6)
666+
if err != nil {
667+
t.Fatal(err)
668+
}
669+
}

0 commit comments

Comments
 (0)