diff --git a/src/net/cgo_socknew.go b/src/net/cgo_socknew.go index b5082840fba8d358fabc7a4c4ac0daa790338b8d..3b13926107ac7c141b09cd3af12367be5582f346 100644 --- a/src/net/cgo_socknew.go +++ b/src/net/cgo_socknew.go @@ -26,8 +26,8 @@ func cgoSockaddrInet4(ip IP) *C.struct_sockaddr { return (*C.struct_sockaddr)(unsafe.Pointer(&sa)) } -func cgoSockaddrInet6(ip IP) *C.struct_sockaddr { - sa := syscall.RawSockaddrInet6{Family: syscall.AF_INET6} +func cgoSockaddrInet6(ip IP, zone int) *C.struct_sockaddr { + sa := syscall.RawSockaddrInet6{Family: syscall.AF_INET6, Scope_id: uint32(zone)} copy(sa.Addr[:], ip) return (*C.struct_sockaddr)(unsafe.Pointer(&sa)) } diff --git a/src/net/cgo_sockold.go b/src/net/cgo_sockold.go index 522e8e588017763cdcc4a03d364882fa663e1552..e629a09f9cd5f8d7dd2b091310ba4ab3a6a695b8 100644 --- a/src/net/cgo_sockold.go +++ b/src/net/cgo_sockold.go @@ -26,8 +26,8 @@ func cgoSockaddrInet4(ip IP) *C.struct_sockaddr { return (*C.struct_sockaddr)(unsafe.Pointer(&sa)) } -func cgoSockaddrInet6(ip IP) *C.struct_sockaddr { - sa := syscall.RawSockaddrInet6{Len: syscall.SizeofSockaddrInet6, Family: syscall.AF_INET6} +func cgoSockaddrInet6(ip IP, zone int) *C.struct_sockaddr { + sa := syscall.RawSockaddrInet6{Len: syscall.SizeofSockaddrInet6, Family: syscall.AF_INET6, Scope_id: uint32(zone)} copy(sa.Addr[:], ip) return (*C.struct_sockaddr)(unsafe.Pointer(&sa)) } diff --git a/src/net/cgo_unix.go b/src/net/cgo_unix.go index d53c00308e7834bd6e47c57f8611429b211c4be2..c14f08547a4f51c933c21c6e9231f0d71b2090f2 100644 --- a/src/net/cgo_unix.go +++ b/src/net/cgo_unix.go @@ -186,11 +186,15 @@ func cgoLookupPTR(addr string) ([]string, error, bool) { acquireThread() defer releaseThread() - ip := ParseIP(addr) + var zone string + ip := parseIPv4(addr) + if ip == nil { + ip, zone = parseIPv6(addr, true) + } if ip == nil { return nil, &DNSError{Err: "invalid address", Name: addr}, true } - sa, salen := cgoSockaddr(ip) + sa, salen := cgoSockaddr(ip, zone) if sa == nil { return nil, &DNSError{Err: "invalid address " + ip.String(), Name: addr}, true } @@ -225,12 +229,12 @@ func cgoLookupPTR(addr string) ([]string, error, bool) { return []string{absDomainName(b)}, nil, true } -func cgoSockaddr(ip IP) (*C.struct_sockaddr, C.socklen_t) { +func cgoSockaddr(ip IP, zone string) (*C.struct_sockaddr, C.socklen_t) { if ip4 := ip.To4(); ip4 != nil { return cgoSockaddrInet4(ip4), C.socklen_t(syscall.SizeofSockaddrInet4) } if ip6 := ip.To16(); ip6 != nil { - return cgoSockaddrInet6(ip6), C.socklen_t(syscall.SizeofSockaddrInet6) + return cgoSockaddrInet6(ip6, zoneToInt(zone)), C.socklen_t(syscall.SizeofSockaddrInet6) } return nil, 0 } diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go index 630c8a417faa9defb13fcdff37382dcbea610525..4a8e631027e65046d97b6199e66cdbe0c3f0d131 100644 --- a/src/net/lookup_test.go +++ b/src/net/lookup_test.go @@ -209,6 +209,30 @@ func TestLookupGooglePublicDNSAddr(t *testing.T) { } } +func TestLookupIPv6LinkLocalAddr(t *testing.T) { + if !supportsIPv6 { + t.Skip("IPv6 is required") + } + + addrs, err := LookupHost("localhost") + if err != nil { + t.Fatal(err) + } + found := false + for _, addr := range addrs { + if addr == "fe80::1%lo0" { + found = true + break + } + } + if !found { + t.Skipf("not supported on %s", runtime.GOOS) + } + if _, err := LookupAddr("fe80::1%lo0"); err != nil { + t.Error(err) + } +} + var lookupIANACNAMETests = []struct { name, cname string }{ diff --git a/src/net/testdata/hosts b/src/net/testdata/hosts index b601763898b7e27ded621cc207effa4a403cecc0..3ed83ff8a83ea2e2eebbf7f03bdd0a49b4aed374 100644 --- a/src/net/testdata/hosts +++ b/src/net/testdata/hosts @@ -5,8 +5,7 @@ 127.1.1.1 thor # aliases 127.1.1.2 ullr ullrhost +fe80::1%lo0 localhost # Bogus entries that must be ignored. 123.123.123 loki 321.321.321.321 -# TODO(yvesj): Should we be able to parse this? From a Darwin system. -fe80::1%lo0 localhost