net: make Dial("tcp", ln.Addr().String()) work even with bad IPv6 config

Some machines can be configured (or came/come configured) in such a
state that IPv6 only half works: you can bind on [::]:n but not
connect back to it.

This implements a fallback such that it's guaranteed that this pattern
works:

   ln, err := Listen("tcp", ":0")
   ...
   addr := ln.Addr().String() // "[::]:n"
   c, err := Dial("tcp", addr)

... which is also now tested. It will first try to dial "[::]:n", as
before, but if that dial fails, it will also try "0.0.0.0:n".

Fixes #18806 (contains more details)
Fixes #20611 (I was going to fix nacl later, but it was easy enough)

Change-Id: I1107eb197e902ae8185c781ad1bc4e2bc61d1f4c
Reviewed-on: https://go-review.googlesource.com/45088
Reviewed-by: Paul Marks <pmarks@google.com>
This commit is contained in:
Brad Fitzpatrick 2017-06-07 21:01:48 +00:00
parent d8a7990ffa
commit 78cf0e56ce
3 changed files with 38 additions and 0 deletions

View file

@ -887,3 +887,21 @@ func TestCancelAfterDial(t *testing.T) {
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()
}