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.
10 "internal/singleflight"
13 // protocols contains minimal mappings between internet protocol
14 // names and numbers for platforms that don't have a complete list of
17 // See http://www.iana.org/assignments/protocol-numbers
19 // On Unix, this map is augmented by readProtocols via lookupProtocol.
20 var protocols
= map[string]int{
28 // services contains minimal mappings between services names and port
29 // numbers for platforms that don't have a complete list of port numbers
30 // (some Solaris distros, nacl, etc).
32 // See https://www.iana.org/assignments/service-names-port-numbers
34 // On Unix, this map is augmented by readServices via goLookupPort.
35 var services
= map[string]map[string]int{
42 "gopher": 70, // ʕ◔ϖ◔ʔ
56 const maxProtoLength
= len("RSVP-E2E-IGNORE") + 10 // with room to grow
58 func lookupProtocolMap(name
string) (int, error
) {
59 var lowerProtocol
[maxProtoLength
]byte
60 n
:= copy(lowerProtocol
[:], name
)
61 lowerASCIIBytes(lowerProtocol
[:n
])
62 proto
, found
:= protocols
[string(lowerProtocol
[:n
])]
63 if !found || n
!= len(name
) {
64 return 0, &AddrError
{Err
: "unknown IP protocol specified", Addr
: name
}
69 // maxPortBufSize is the longest reasonable name of a service
70 // (non-numeric port).
71 // Currently the longest known IANA-unregistered name is
72 // "mobility-header", so we use that length, plus some slop in case
73 // something longer is added in the future.
74 const maxPortBufSize
= len("mobility-header") + 10
76 func lookupPortMap(network
, service
string) (port
int, error error
) {
84 if m
, ok
:= services
[network
]; ok
{
85 var lowerService
[maxPortBufSize
]byte
86 n
:= copy(lowerService
[:], service
)
87 lowerASCIIBytes(lowerService
[:n
])
88 if port
, ok
:= m
[string(lowerService
[:n
])]; ok
&& n
== len(service
) {
92 return 0, &AddrError
{Err
: "unknown port", Addr
: network
+ "/" + service
}
95 // DefaultResolver is the resolver used by the package-level Lookup
96 // functions and by Dialers without a specified Resolver.
97 var DefaultResolver
= &Resolver
{}
99 // A Resolver looks up names and numbers.
101 // A nil *Resolver is equivalent to a zero Resolver.
102 type Resolver
struct {
103 // PreferGo controls whether Go's built-in DNS resolver is preferred
104 // on platforms where it's available. It is equivalent to setting
105 // GODEBUG=netdns=go, but scoped to just this resolver.
108 // StrictErrors controls the behavior of temporary errors
109 // (including timeout, socket errors, and SERVFAIL) when using
110 // Go's built-in resolver. For a query composed of multiple
111 // sub-queries (such as an A+AAAA address lookup, or walking the
112 // DNS search list), this option causes such errors to abort the
113 // whole query instead of returning a partial result. This is
114 // not enabled by default because it may affect compatibility
115 // with resolvers that process AAAA queries incorrectly.
118 // Dial optionally specifies an alternate dialer for use by
119 // Go's built-in DNS resolver to make TCP and UDP connections
120 // to DNS services. The host in the address parameter will
121 // always be a literal IP address and not a host name, and the
122 // port in the address parameter will be a literal port number
123 // and not a service name.
124 // If the Conn returned is also a PacketConn, sent and received DNS
125 // messages must adhere to RFC 1035 section 4.2.1, "UDP usage".
126 // Otherwise, DNS messages transmitted over Conn must adhere
127 // to RFC 7766 section 5, "Transport Protocol Selection".
128 // If nil, the default dialer is used.
129 Dial
func(ctx context
.Context
, network
, address
string) (Conn
, error
)
131 // TODO(bradfitz): optional interface impl override hook
132 // TODO(bradfitz): Timeout time.Duration?
135 // LookupHost looks up the given host using the local resolver.
136 // It returns a slice of that host's addresses.
137 func LookupHost(host
string) (addrs
[]string, err error
) {
138 return DefaultResolver
.LookupHost(context
.Background(), host
)
141 // LookupHost looks up the given host using the local resolver.
142 // It returns a slice of that host's addresses.
143 func (r
*Resolver
) LookupHost(ctx context
.Context
, host
string) (addrs
[]string, err error
) {
144 // Make sure that no matter what we do later, host=="" is rejected.
145 // ParseIP, for example, does accept empty strings.
147 return nil, &DNSError
{Err
: errNoSuchHost
.Error(), Name
: host
}
149 if ip
:= ParseIP(host
); ip
!= nil {
150 return []string{host
}, nil
152 return r
.lookupHost(ctx
, host
)
155 // LookupIP looks up host using the local resolver.
156 // It returns a slice of that host's IPv4 and IPv6 addresses.
157 func LookupIP(host
string) ([]IP
, error
) {
158 addrs
, err
:= DefaultResolver
.LookupIPAddr(context
.Background(), host
)
162 ips
:= make([]IP
, len(addrs
))
163 for i
, ia
:= range addrs
{
169 // LookupIPAddr looks up host using the local resolver.
170 // It returns a slice of that host's IPv4 and IPv6 addresses.
171 func (r
*Resolver
) LookupIPAddr(ctx context
.Context
, host
string) ([]IPAddr
, error
) {
172 // Make sure that no matter what we do later, host=="" is rejected.
173 // ParseIP, for example, does accept empty strings.
175 return nil, &DNSError
{Err
: errNoSuchHost
.Error(), Name
: host
}
177 if ip
:= ParseIP(host
); ip
!= nil {
178 return []IPAddr
{{IP
: ip
}}, nil
180 trace
, _
:= ctx
.Value(nettrace
.TraceKey
{}).(*nettrace
.Trace
)
181 if trace
!= nil && trace
.DNSStart
!= nil {
184 // The underlying resolver func is lookupIP by default but it
185 // can be overridden by tests. This is needed by net/http, so it
186 // uses a context key instead of unexported variables.
187 resolverFunc
:= r
.lookupIP
188 if alt
, _
:= ctx
.Value(nettrace
.LookupIPAltResolverKey
{}).(func(context
.Context
, string) ([]IPAddr
, error
)); alt
!= nil {
192 ch
:= lookupGroup
.DoChan(host
, func() (interface{}, error
) {
193 return testHookLookupIP(ctx
, resolverFunc
, host
)
198 // If the DNS lookup timed out for some reason, force
199 // future requests to start the DNS lookup again
200 // rather than waiting for the current lookup to
201 // complete. See issue 8602.
203 if ctxErr
== context
.DeadlineExceeded
{
204 lookupGroup
.Forget(host
)
206 err
:= mapErr(ctxErr
)
207 if trace
!= nil && trace
.DNSDone
!= nil {
208 trace
.DNSDone(nil, false, err
)
212 if trace
!= nil && trace
.DNSDone
!= nil {
213 addrs
, _
:= r
.Val
.([]IPAddr
)
214 trace
.DNSDone(ipAddrsEface(addrs
), r
.Shared
, r
.Err
)
216 return lookupIPReturn(r
.Val
, r
.Err
, r
.Shared
)
220 // lookupGroup merges LookupIPAddr calls together for lookups
221 // for the same host. The lookupGroup key is is the LookupIPAddr.host
223 // The return values are ([]IPAddr, error).
224 var lookupGroup singleflight
.Group
226 // lookupIPReturn turns the return values from singleflight.Do into
227 // the return values from LookupIP.
228 func lookupIPReturn(addrsi
interface{}, err error
, shared
bool) ([]IPAddr
, error
) {
232 addrs
:= addrsi
.([]IPAddr
)
234 clone
:= make([]IPAddr
, len(addrs
))
241 // ipAddrsEface returns an empty interface slice of addrs.
242 func ipAddrsEface(addrs
[]IPAddr
) []interface{} {
243 s
:= make([]interface{}, len(addrs
))
244 for i
, v
:= range addrs
{
250 // LookupPort looks up the port for the given network and service.
251 func LookupPort(network
, service
string) (port
int, err error
) {
252 return DefaultResolver
.LookupPort(context
.Background(), network
, service
)
255 // LookupPort looks up the port for the given network and service.
256 func (r
*Resolver
) LookupPort(ctx context
.Context
, network
, service
string) (port
int, err error
) {
257 port
, needsLookup
:= parsePort(service
)
259 port
, err
= r
.lookupPort(ctx
, network
, service
)
264 if 0 > port || port
> 65535 {
265 return 0, &AddrError
{Err
: "invalid port", Addr
: service
}
270 // LookupCNAME returns the canonical name for the given host.
271 // Callers that do not care about the canonical name can call
272 // LookupHost or LookupIP directly; both take care of resolving
273 // the canonical name as part of the lookup.
275 // A canonical name is the final name after following zero
276 // or more CNAME records.
277 // LookupCNAME does not return an error if host does not
278 // contain DNS "CNAME" records, as long as host resolves to
280 func LookupCNAME(host
string) (cname
string, err error
) {
281 return DefaultResolver
.lookupCNAME(context
.Background(), host
)
284 // LookupCNAME returns the canonical name for the given host.
285 // Callers that do not care about the canonical name can call
286 // LookupHost or LookupIP directly; both take care of resolving
287 // the canonical name as part of the lookup.
289 // A canonical name is the final name after following zero
290 // or more CNAME records.
291 // LookupCNAME does not return an error if host does not
292 // contain DNS "CNAME" records, as long as host resolves to
294 func (r
*Resolver
) LookupCNAME(ctx context
.Context
, host
string) (cname
string, err error
) {
295 return r
.lookupCNAME(ctx
, host
)
298 // LookupSRV tries to resolve an SRV query of the given service,
299 // protocol, and domain name. The proto is "tcp" or "udp".
300 // The returned records are sorted by priority and randomized
301 // by weight within a priority.
303 // LookupSRV constructs the DNS name to look up following RFC 2782.
304 // That is, it looks up _service._proto.name. To accommodate services
305 // publishing SRV records under non-standard names, if both service
306 // and proto are empty strings, LookupSRV looks up name directly.
307 func LookupSRV(service
, proto
, name
string) (cname
string, addrs
[]*SRV
, err error
) {
308 return DefaultResolver
.lookupSRV(context
.Background(), service
, proto
, name
)
311 // LookupSRV tries to resolve an SRV query of the given service,
312 // protocol, and domain name. The proto is "tcp" or "udp".
313 // The returned records are sorted by priority and randomized
314 // by weight within a priority.
316 // LookupSRV constructs the DNS name to look up following RFC 2782.
317 // That is, it looks up _service._proto.name. To accommodate services
318 // publishing SRV records under non-standard names, if both service
319 // and proto are empty strings, LookupSRV looks up name directly.
320 func (r
*Resolver
) LookupSRV(ctx context
.Context
, service
, proto
, name
string) (cname
string, addrs
[]*SRV
, err error
) {
321 return r
.lookupSRV(ctx
, service
, proto
, name
)
324 // LookupMX returns the DNS MX records for the given domain name sorted by preference.
325 func LookupMX(name
string) ([]*MX
, error
) {
326 return DefaultResolver
.lookupMX(context
.Background(), name
)
329 // LookupMX returns the DNS MX records for the given domain name sorted by preference.
330 func (r
*Resolver
) LookupMX(ctx context
.Context
, name
string) ([]*MX
, error
) {
331 return r
.lookupMX(ctx
, name
)
334 // LookupNS returns the DNS NS records for the given domain name.
335 func LookupNS(name
string) ([]*NS
, error
) {
336 return DefaultResolver
.lookupNS(context
.Background(), name
)
339 // LookupNS returns the DNS NS records for the given domain name.
340 func (r
*Resolver
) LookupNS(ctx context
.Context
, name
string) ([]*NS
, error
) {
341 return r
.lookupNS(ctx
, name
)
344 // LookupTXT returns the DNS TXT records for the given domain name.
345 func LookupTXT(name
string) ([]string, error
) {
346 return DefaultResolver
.lookupTXT(context
.Background(), name
)
349 // LookupTXT returns the DNS TXT records for the given domain name.
350 func (r
*Resolver
) LookupTXT(ctx context
.Context
, name
string) ([]string, error
) {
351 return r
.lookupTXT(ctx
, name
)
354 // LookupAddr performs a reverse lookup for the given address, returning a list
355 // of names mapping to that address.
357 // When using the host C library resolver, at most one result will be
358 // returned. To bypass the host resolver, use a custom Resolver.
359 func LookupAddr(addr
string) (names
[]string, err error
) {
360 return DefaultResolver
.lookupAddr(context
.Background(), addr
)
363 // LookupAddr performs a reverse lookup for the given address, returning a list
364 // of names mapping to that address.
365 func (r
*Resolver
) LookupAddr(ctx context
.Context
, addr
string) (names
[]string, err error
) {
366 return r
.lookupAddr(ctx
, addr
)