1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
13 const cacheMaxAge
= 5 * time
.Second
15 func parseLiteralIP(addr
string) string {
20 ip
, zone
= parseIPv6Zone(addr
)
28 return ip
.String() + "%" + zone
31 // hosts contains known host entries.
35 // Key for the list of literal IP addresses must be a host
36 // name. It would be part of DNS labels, a FQDN or an absolute
38 // For now the key is converted to lower case for convenience.
39 byName
map[string][]string
41 // Key for the list of host names must be a literal IP address
42 // including IPv6 address with zone identifier.
43 // We don't support old-classful IP address notation.
44 byAddr
map[string][]string
54 hp
:= testHookHostsPath
56 if now
.Before(hosts
.expire
) && hosts
.path
== hp
&& len(hosts
.byName
) > 0 {
59 mtime
, size
, err
:= stat(hp
)
60 if err
== nil && hosts
.path
== hp
&& hosts
.mtime
.Equal(mtime
) && hosts
.size
== size
{
61 hosts
.expire
= now
.Add(cacheMaxAge
)
65 hs
:= make(map[string][]string)
66 is
:= make(map[string][]string)
68 if file
, _
= open(hp
); file
== nil {
71 for line
, ok
:= file
.readLine(); ok
; line
, ok
= file
.readLine() {
72 if i
:= bytealg
.IndexByteString(line
, '#'); i
>= 0 {
80 addr
:= parseLiteralIP(f
[0])
84 for i
:= 1; i
< len(f
); i
++ {
85 name
:= absDomainName([]byte(f
[i
]))
88 key
:= absDomainName(h
)
89 hs
[key
] = append(hs
[key
], addr
)
90 is
[addr
] = append(is
[addr
], name
)
93 // Update the data cache.
94 hosts
.expire
= now
.Add(cacheMaxAge
)
103 // lookupStaticHost looks up the addresses for the given host from /etc/hosts.
104 func lookupStaticHost(host
string) []string {
108 if len(hosts
.byName
) != 0 {
109 // TODO(jbd,bradfitz): avoid this alloc if host is already all lowercase?
110 // or linear scan the byName map if it's small enough?
111 lowerHost
:= []byte(host
)
112 lowerASCIIBytes(lowerHost
)
113 if ips
, ok
:= hosts
.byName
[absDomainName(lowerHost
)]; ok
{
114 ipsCp
:= make([]string, len(ips
))
122 // lookupStaticAddr looks up the hosts for the given address from /etc/hosts.
123 func lookupStaticAddr(addr
string) []string {
127 addr
= parseLiteralIP(addr
)
131 if len(hosts
.byAddr
) != 0 {
132 if hosts
, ok
:= hosts
.byAddr
[addr
]; ok
{
133 hostsCp
:= make([]string, len(hosts
))