Commit 1a0b1cca authored by Russ Cox's avatar Russ Cox

net: fix Dial(":80") on Windows

Windows sockets allow bind to 0.0.0.0:80 but not connect to it.
To make Listen(":80") / Dial(":80") work as documented on Windows,
connect to 127.0.0.1 or ::1 (depending on network) in place of 0.0.0.0.

Fixes #6290.

Change-Id: Ia27537067276871648546678fbe0f1b8478329fe
Reviewed-on: https://go-review.googlesource.com/32101
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarMikio Hara <mikioh.mikioh@gmail.com>
parent c56cc9b3
......@@ -55,6 +55,23 @@ func TestProhibitionaryDialArg(t *testing.T) {
}
}
func TestDialLocal(t *testing.T) {
ln, err := newLocalListener("tcp")
if err != nil {
t.Fatal(err)
}
defer ln.Close()
_, port, err := SplitHostPort(ln.Addr().String())
if err != nil {
t.Fatal(err)
}
c, err := Dial("tcp", JoinHostPort("", port))
if err != nil {
t.Fatal(err)
}
c.Close()
}
func TestDialTimeoutFDLeak(t *testing.T) {
switch runtime.GOOS {
case "plan9":
......
......@@ -50,6 +50,10 @@ func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return ipToSockaddr(family, a.IP, 0, a.Zone)
}
func (a *IPAddr) toLocal(net string) sockaddr {
return &IPAddr{loopbackIP(net), a.Zone}
}
func (c *IPConn) readFrom(b []byte) (int, *IPAddr, error) {
// TODO(cw,rsc): consider using readv if we know the family
// type to avoid the header trim/copy
......
......@@ -251,3 +251,10 @@ func (r *Resolver) internetAddrList(ctx context.Context, net, addr string) (addr
}
return filterAddrList(filter, ips, inetaddr)
}
func loopbackIP(net string) IP {
if net != "" && net[len(net)-1] == '6' {
return IPv6loopback
}
return IP{127, 0, 0, 1}
}
......@@ -154,6 +154,9 @@ func favoriteAddrFamily(net string, laddr, raddr sockaddr, mode string) (family
// Internet sockets (TCP, UDP, IP)
func internetSocket(ctx context.Context, net string, laddr, raddr sockaddr, sotype, proto int, mode string) (fd *netFD, err error) {
if (runtime.GOOS == "windows" || runtime.GOOS == "openbsd" || runtime.GOOS == "nacl") && mode == "dial" && raddr.isWildcard() {
raddr = raddr.toLocal(net)
}
family, ipv6only := favoriteAddrFamily(net, laddr, raddr, mode)
return socket(ctx, net, family, sotype, proto, ipv6only, laddr, raddr)
}
......
......@@ -30,6 +30,9 @@ type sockaddr interface {
// interface. It returns a nil interface when the address is
// nil.
sockaddr(family int) (syscall.Sockaddr, error)
// toLocal maps the zero address to a local system address (127.0.0.1 or ::1)
toLocal(net string) sockaddr
}
// socket returns a network file descriptor that is ready for
......
......@@ -40,6 +40,10 @@ func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return ipToSockaddr(family, a.IP, a.Port, a.Zone)
}
func (a *TCPAddr) toLocal(net string) sockaddr {
return &TCPAddr{loopbackIP(net), a.Port, a.Zone}
}
func (c *TCPConn) readFrom(r io.Reader) (int64, error) {
if n, err, handled := sendFile(c.fd, r); handled {
return n, err
......
......@@ -38,6 +38,10 @@ func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return ipToSockaddr(family, a.IP, a.Port, a.Zone)
}
func (a *UDPAddr) toLocal(net string) sockaddr {
return &UDPAddr{loopbackIP(net), a.Port, a.Zone}
}
func (c *UDPConn) readFrom(b []byte) (int, *UDPAddr, error) {
var addr *UDPAddr
n, sa, err := c.fd.readFrom(b)
......
......@@ -94,6 +94,10 @@ func (a *UnixAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return &syscall.SockaddrUnix{Name: a.Name}, nil
}
func (a *UnixAddr) toLocal(net string) sockaddr {
return a
}
func (c *UnixConn) readFrom(b []byte) (int, *UnixAddr, error) {
var addr *UnixAddr
n, sa, err := c.fd.readFrom(b)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment