diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go index 2aeabd44873f22..2dc96e74460174 100644 --- a/src/net/ipsock_posix.go +++ b/src/net/ipsock_posix.go @@ -238,7 +238,7 @@ 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 := ap.Addr() - if !addr.Is4() { + if addr.IsValid() && !addr.Is4() { return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: addr.String()} } sa := syscall.SockaddrInet4{ @@ -256,7 +256,7 @@ func addrPortToSockaddrInet6(ap netip.AddrPort) (syscall.SockaddrInet6, error) { // to an IPv4-mapped IPv6 address. // The error message is kept consistent with ipToSockaddrInet6. addr := ap.Addr() - if !addr.IsValid() { + if addr.IsValid() && !addr.Is6() { return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: addr.String()} } sa := syscall.SockaddrInet6{ diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index 3cd1d0a7624165..1270c029ffea94 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -186,17 +186,29 @@ func (c *UDPConn) writeMsgAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn switch c.fd.family { case syscall.AF_INET: - sa, err := addrPortToSockaddrInet4(addr) - if err != nil { - return 0, 0, err + saPtr := &syscall.SockaddrInet4{} + if addr.IsValid() { + sa, err := addrPortToSockaddrInet4(addr) + if err != nil { + return 0, 0, err + } + saPtr = &sa + } else { + saPtr = nil } - return c.fd.writeMsgInet4(b, oob, &sa) + return c.fd.writeMsgInet4(b, oob, saPtr) case syscall.AF_INET6: - sa, err := addrPortToSockaddrInet6(addr) - if err != nil { - return 0, 0, err + saPtr := &syscall.SockaddrInet6{} + if addr.IsValid() { + sa, err := addrPortToSockaddrInet6(addr) + if err != nil { + return 0, 0, err + } + saPtr = &sa + } else { + saPtr = nil } - return c.fd.writeMsgInet6(b, oob, &sa) + return c.fd.writeMsgInet6(b, oob, saPtr) default: return 0, 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()} } diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 6dacc81df6e059..dc8fc48bb75777 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -705,3 +705,31 @@ func TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) { t.Fatal(err) } } + +func TestWriteToUDPAddrPort(t *testing.T) { + dialer := Dialer{} + c, err := dialer.Dial("udp", "[::1]:12345") + if err != nil { + t.Fatal(err) + } + defer c.Close() + + ra, err := ResolveUDPAddr("udp", "[::1]:12345") + if err != nil { + t.Fatal(err) + } + + b := []byte("CONNECTED-MODE SOCKET") + + _, _, err = c.(*UDPConn).WriteMsgUDPAddrPort(b, nil, ra.AddrPort()) + if err == nil { + t.Fatal("should fail") + } + if err != nil && err.(*OpError).Err != ErrWriteToConnected { + t.Fatalf("should fail as ErrWriteToConnected: %v", err) + } + _, _, err = c.(*UDPConn).WriteMsgUDPAddrPort(b, nil, netip.AddrPort{}) + if err != nil { + t.Fatal(err) + } +} diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index ecd5952975a73d..7de2272b591b95 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -410,17 +410,25 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) } func sendmsgNInet4(fd int, p, oob []byte, to *SockaddrInet4, flags int) (n int, err error) { - ptr, salen, err := to.sockaddr() - if err != nil { - return 0, err + var ptr unsafe.Pointer + var salen _Socklen + if to != nil { + ptr, salen, err = to.sockaddr() + if err != nil { + return 0, err + } } return sendmsgN(fd, p, oob, ptr, salen, flags) } func sendmsgNInet6(fd int, p, oob []byte, to *SockaddrInet6, flags int) (n int, err error) { - ptr, salen, err := to.sockaddr() - if err != nil { - return 0, err + var ptr unsafe.Pointer + var salen _Socklen + if to != nil { + ptr, salen, err = to.sockaddr() + if err != nil { + return 0, err + } } return sendmsgN(fd, p, oob, ptr, salen, flags) }