try()
}
}
+
+// Issue 18806: it should always be possible to net.Dial a
+// net.Listener().Addr().String when the listen address was ":n", even
+// if the machine has halfway configured IPv6 such that it can bind on
+// "::" not connect back to that same address.
+func TestDialListenerAddr(t *testing.T) {
+ ln, err := Listen("tcp", ":0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+ addr := ln.Addr().String()
+ c, err := Dial("tcp", addr)
+ if err != nil {
+ t.Fatalf("for addr %q, dial error: %v", addr, err)
+ }
+ c.Close()
+}
ips = []IPAddr{{IP: ip}}
} else if ip, zone := parseIPv6(host, true); ip != nil {
ips = []IPAddr{{IP: ip, Zone: zone}}
+ // Issue 18806: if the machine has halfway configured
+ // IPv6 such that it can bind on "::" (IPv6unspecified)
+ // but not connect back to that same address, fall
+ // back to dialing 0.0.0.0.
+ if ip.Equal(IPv6unspecified) {
+ ips = append(ips, IPAddr{IP: IPv4zero})
+ }
} else {
// Try as a DNS name.
ips, err = r.LookupIPAddr(ctx, host)
func (sa *SockaddrInet4) key() interface{} { return *sa }
+func isIPv4Localhost(sa Sockaddr) bool {
+ sa4, ok := sa.(*SockaddrInet4)
+ return ok && sa4.Addr == [4]byte{127, 0, 0, 1}
+}
+
type SockaddrInet6 struct {
Port int
ZoneId uint32
return EISCONN
}
l, ok := net.listener[netAddr{f.proto, f.sotype, sa.key()}]
+ if !ok {
+ // If we're dialing 127.0.0.1 but found nothing, try
+ // 0.0.0.0 also. (Issue 20611)
+ if isIPv4Localhost(sa) {
+ sa = &SockaddrInet4{Port: sa.(*SockaddrInet4).Port}
+ l, ok = net.listener[netAddr{f.proto, f.sotype, sa.key()}]
+ }
+ }
if !ok || l.listenerClosed() {
net.Unlock()
return ECONNREFUSED