1 // Copyright 2012 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.
8 "internal/singleflight"
12 // protocols contains minimal mappings between internet protocol
13 // names and numbers for platforms that don't have a complete list of
16 // See http://www.iana.org/assignments/protocol-numbers
17 var protocols
= map[string]int{
22 "ipv6-icmp": 58, "IPV6-ICMP": 58, "IPv6-ICMP": 58,
25 // LookupHost looks up the given host using the local resolver.
26 // It returns an array of that host's addresses.
27 func LookupHost(host
string) (addrs
[]string, err error
) {
28 // Make sure that no matter what we do later, host=="" is rejected.
29 // ParseIP, for example, does accept empty strings.
31 return nil, &DNSError
{Err
: errNoSuchHost
.Error(), Name
: host
}
33 if ip
:= ParseIP(host
); ip
!= nil {
34 return []string{host
}, nil
36 return lookupHost(host
)
39 // LookupIP looks up host using the local resolver.
40 // It returns an array of that host's IPv4 and IPv6 addresses.
41 func LookupIP(host
string) (ips
[]IP
, err error
) {
42 // Make sure that no matter what we do later, host=="" is rejected.
43 // ParseIP, for example, does accept empty strings.
45 return nil, &DNSError
{Err
: errNoSuchHost
.Error(), Name
: host
}
47 if ip
:= ParseIP(host
); ip
!= nil {
50 addrs
, err
:= lookupIPMerge(host
)
54 ips
= make([]IP
, len(addrs
))
55 for i
, addr
:= range addrs
{
61 var lookupGroup singleflight
.Group
63 // lookupIPMerge wraps lookupIP, but makes sure that for any given
64 // host, only one lookup is in-flight at a time. The returned memory
65 // is always owned by the caller.
66 func lookupIPMerge(host
string) (addrs
[]IPAddr
, err error
) {
67 addrsi
, err
, shared
:= lookupGroup
.Do(host
, func() (interface{}, error
) {
68 return testHookLookupIP(lookupIP
, host
)
70 return lookupIPReturn(addrsi
, err
, shared
)
73 // lookupIPReturn turns the return values from singleflight.Do into
74 // the return values from LookupIP.
75 func lookupIPReturn(addrsi
interface{}, err error
, shared
bool) ([]IPAddr
, error
) {
79 addrs
:= addrsi
.([]IPAddr
)
81 clone
:= make([]IPAddr
, len(addrs
))
88 // lookupIPDeadline looks up a hostname with a deadline.
89 func lookupIPDeadline(host
string, deadline time
.Time
) (addrs
[]IPAddr
, err error
) {
90 if deadline
.IsZero() {
91 return lookupIPMerge(host
)
94 // We could push the deadline down into the name resolution
95 // functions. However, the most commonly used implementation
96 // calls getaddrinfo, which has no timeout.
98 timeout
:= deadline
.Sub(time
.Now())
100 return nil, errTimeout
102 t
:= time
.NewTimer(timeout
)
105 ch
:= lookupGroup
.DoChan(host
, func() (interface{}, error
) {
106 return testHookLookupIP(lookupIP
, host
)
111 // The DNS lookup timed out for some reason. Force
112 // future requests to start the DNS lookup again
113 // rather than waiting for the current lookup to
114 // complete. See issue 8602.
115 lookupGroup
.Forget(host
)
117 return nil, errTimeout
120 return lookupIPReturn(r
.Val
, r
.Err
, r
.Shared
)
124 // LookupPort looks up the port for the given network and service.
125 func LookupPort(network
, service
string) (port
int, err error
) {
127 // Lock in the legacy behavior that an empty string
128 // means port 0. See Issue 13610.
131 port
, _
, ok
:= dtoi(service
, 0)
132 if !ok
&& port
!= big
&& port
!= -big
{
133 port
, err
= lookupPort(network
, service
)
138 if 0 > port || port
> 65535 {
139 return 0, &AddrError
{Err
: "invalid port", Addr
: service
}
144 // LookupCNAME returns the canonical DNS host for the given name.
145 // Callers that do not care about the canonical name can call
146 // LookupHost or LookupIP directly; both take care of resolving
147 // the canonical name as part of the lookup.
148 func LookupCNAME(name
string) (cname
string, err error
) {
149 return lookupCNAME(name
)
152 // LookupSRV tries to resolve an SRV query of the given service,
153 // protocol, and domain name. The proto is "tcp" or "udp".
154 // The returned records are sorted by priority and randomized
155 // by weight within a priority.
157 // LookupSRV constructs the DNS name to look up following RFC 2782.
158 // That is, it looks up _service._proto.name. To accommodate services
159 // publishing SRV records under non-standard names, if both service
160 // and proto are empty strings, LookupSRV looks up name directly.
161 func LookupSRV(service
, proto
, name
string) (cname
string, addrs
[]*SRV
, err error
) {
162 return lookupSRV(service
, proto
, name
)
165 // LookupMX returns the DNS MX records for the given domain name sorted by preference.
166 func LookupMX(name
string) (mxs
[]*MX
, err error
) {
167 return lookupMX(name
)
170 // LookupNS returns the DNS NS records for the given domain name.
171 func LookupNS(name
string) (nss
[]*NS
, err error
) {
172 return lookupNS(name
)
175 // LookupTXT returns the DNS TXT records for the given domain name.
176 func LookupTXT(name
string) (txts
[]string, err error
) {
177 return lookupTXT(name
)
180 // LookupAddr performs a reverse lookup for the given address, returning a list
181 // of names mapping to that address.
182 func LookupAddr(addr
string) (names
[]string, err error
) {
183 return lookupAddr(addr
)