]> Cypherpunks repositories - gostls13.git/commitdiff
net: fix Dial(":80") on Windows
authorRuss Cox <rsc@golang.org>
Thu, 27 Oct 2016 01:07:52 +0000 (21:07 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 2 Nov 2016 19:15:11 +0000 (19:15 +0000)
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: Mikio Hara <mikioh.mikioh@gmail.com>
src/net/dial_test.go
src/net/iprawsock_posix.go
src/net/ipsock.go
src/net/ipsock_posix.go
src/net/sock_posix.go
src/net/tcpsock_posix.go
src/net/udpsock_posix.go
src/net/unixsock_posix.go

index 8b21e6b0886e0010201811b37f0820fc9137d81e..6ba8e950b8c1b5b9211b18f76a933eb1519efe8b 100644 (file)
@@ -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":
index 3e0b060a8a4a177dca2d0982ad245057111de575..d5e229fb9cf6dd910108c906df97a5f12ad80a49 100644 (file)
@@ -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
index c04813fa32f12d3df9de9f3bbdafaba708bac14a..5e6b0a9940482ac4cee2790d287c07200a467b79 100644 (file)
@@ -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}
+}
index abe90ac0e61792d9e20f29dbfb0ba318d53512e6..f4fab3f9aa3436889dd2136674e42c63840f93ed 100644 (file)
@@ -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)
 }
index c3af27b596fd7f8b51049671f12afadcd753bbc4..16351e1f14ed8d7ee51295b75ef4f6a2ea5b970a 100644 (file)
@@ -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
index c9a8b6808ea8da13612dc221952074510741a3f3..9641e5c028323e508267cb66250b5deaabeff467 100644 (file)
@@ -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
index 4924801ebb258dd20454e326b1e5a4014b52f43f..72aadca5dc9637a518ba0c351bb0c7d343e8b625 100644 (file)
@@ -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)
index 1ab7cbe2225c05c1a02aec2f8c1bda32f6dd2bff..a8f892e6c46590153f936ea3d1e8f44423261caa 100644 (file)
@@ -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)