libgo: update to Go 1.11
[official-gcc.git] / libgo / go / net / lookup.go
blobe0f21fa9a8d3fd580e6da1d37e16dd75c31b5a97
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.
5 package net
7 import (
8 "context"
9 "internal/nettrace"
10 "internal/singleflight"
11 "sync"
14 // protocols contains minimal mappings between internet protocol
15 // names and numbers for platforms that don't have a complete list of
16 // protocol numbers.
18 // See https://www.iana.org/assignments/protocol-numbers
20 // On Unix, this map is augmented by readProtocols via lookupProtocol.
21 var protocols = map[string]int{
22 "icmp": 1,
23 "igmp": 2,
24 "tcp": 6,
25 "udp": 17,
26 "ipv6-icmp": 58,
29 // services contains minimal mappings between services names and port
30 // numbers for platforms that don't have a complete list of port numbers
31 // (some Solaris distros, nacl, etc).
33 // See https://www.iana.org/assignments/service-names-port-numbers
35 // On Unix, this map is augmented by readServices via goLookupPort.
36 var services = map[string]map[string]int{
37 "udp": {
38 "domain": 53,
40 "tcp": {
41 "ftp": 21,
42 "ftps": 990,
43 "gopher": 70, // ʕ◔ϖ◔ʔ
44 "http": 80,
45 "https": 443,
46 "imap2": 143,
47 "imap3": 220,
48 "imaps": 993,
49 "pop3": 110,
50 "pop3s": 995,
51 "smtp": 25,
52 "ssh": 22,
53 "telnet": 23,
57 // dnsWaitGroup can be used by tests to wait for all DNS goroutines to
58 // complete. This avoids races on the test hooks.
59 var dnsWaitGroup sync.WaitGroup
61 const maxProtoLength = len("RSVP-E2E-IGNORE") + 10 // with room to grow
63 func lookupProtocolMap(name string) (int, error) {
64 var lowerProtocol [maxProtoLength]byte
65 n := copy(lowerProtocol[:], name)
66 lowerASCIIBytes(lowerProtocol[:n])
67 proto, found := protocols[string(lowerProtocol[:n])]
68 if !found || n != len(name) {
69 return 0, &AddrError{Err: "unknown IP protocol specified", Addr: name}
71 return proto, nil
74 // maxPortBufSize is the longest reasonable name of a service
75 // (non-numeric port).
76 // Currently the longest known IANA-unregistered name is
77 // "mobility-header", so we use that length, plus some slop in case
78 // something longer is added in the future.
79 const maxPortBufSize = len("mobility-header") + 10
81 func lookupPortMap(network, service string) (port int, error error) {
82 switch network {
83 case "tcp4", "tcp6":
84 network = "tcp"
85 case "udp4", "udp6":
86 network = "udp"
89 if m, ok := services[network]; ok {
90 var lowerService [maxPortBufSize]byte
91 n := copy(lowerService[:], service)
92 lowerASCIIBytes(lowerService[:n])
93 if port, ok := m[string(lowerService[:n])]; ok && n == len(service) {
94 return port, nil
97 return 0, &AddrError{Err: "unknown port", Addr: network + "/" + service}
100 // DefaultResolver is the resolver used by the package-level Lookup
101 // functions and by Dialers without a specified Resolver.
102 var DefaultResolver = &Resolver{}
104 // A Resolver looks up names and numbers.
106 // A nil *Resolver is equivalent to a zero Resolver.
107 type Resolver struct {
108 // PreferGo controls whether Go's built-in DNS resolver is preferred
109 // on platforms where it's available. It is equivalent to setting
110 // GODEBUG=netdns=go, but scoped to just this resolver.
111 PreferGo bool
113 // StrictErrors controls the behavior of temporary errors
114 // (including timeout, socket errors, and SERVFAIL) when using
115 // Go's built-in resolver. For a query composed of multiple
116 // sub-queries (such as an A+AAAA address lookup, or walking the
117 // DNS search list), this option causes such errors to abort the
118 // whole query instead of returning a partial result. This is
119 // not enabled by default because it may affect compatibility
120 // with resolvers that process AAAA queries incorrectly.
121 StrictErrors bool
123 // Dial optionally specifies an alternate dialer for use by
124 // Go's built-in DNS resolver to make TCP and UDP connections
125 // to DNS services. The host in the address parameter will
126 // always be a literal IP address and not a host name, and the
127 // port in the address parameter will be a literal port number
128 // and not a service name.
129 // If the Conn returned is also a PacketConn, sent and received DNS
130 // messages must adhere to RFC 1035 section 4.2.1, "UDP usage".
131 // Otherwise, DNS messages transmitted over Conn must adhere
132 // to RFC 7766 section 5, "Transport Protocol Selection".
133 // If nil, the default dialer is used.
134 Dial func(ctx context.Context, network, address string) (Conn, error)
136 // lookupGroup merges LookupIPAddr calls together for lookups for the same
137 // host. The lookupGroup key is the LookupIPAddr.host argument.
138 // The return values are ([]IPAddr, error).
139 lookupGroup singleflight.Group
141 // TODO(bradfitz): optional interface impl override hook
142 // TODO(bradfitz): Timeout time.Duration?
145 func (r *Resolver) preferGo() bool { return r != nil && r.PreferGo }
146 func (r *Resolver) strictErrors() bool { return r != nil && r.StrictErrors }
148 func (r *Resolver) getLookupGroup() *singleflight.Group {
149 if r == nil {
150 return &DefaultResolver.lookupGroup
152 return &r.lookupGroup
155 // LookupHost looks up the given host using the local resolver.
156 // It returns a slice of that host's addresses.
157 func LookupHost(host string) (addrs []string, err error) {
158 return DefaultResolver.LookupHost(context.Background(), host)
161 // LookupHost looks up the given host using the local resolver.
162 // It returns a slice of that host's addresses.
163 func (r *Resolver) LookupHost(ctx context.Context, host string) (addrs []string, err error) {
164 // Make sure that no matter what we do later, host=="" is rejected.
165 // parseIP, for example, does accept empty strings.
166 if host == "" {
167 return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host}
169 if ip, _ := parseIPZone(host); ip != nil {
170 return []string{host}, nil
172 return r.lookupHost(ctx, host)
175 // LookupIP looks up host using the local resolver.
176 // It returns a slice of that host's IPv4 and IPv6 addresses.
177 func LookupIP(host string) ([]IP, error) {
178 addrs, err := DefaultResolver.LookupIPAddr(context.Background(), host)
179 if err != nil {
180 return nil, err
182 ips := make([]IP, len(addrs))
183 for i, ia := range addrs {
184 ips[i] = ia.IP
186 return ips, nil
189 // LookupIPAddr looks up host using the local resolver.
190 // It returns a slice of that host's IPv4 and IPv6 addresses.
191 func (r *Resolver) LookupIPAddr(ctx context.Context, host string) ([]IPAddr, error) {
192 // Make sure that no matter what we do later, host=="" is rejected.
193 // parseIP, for example, does accept empty strings.
194 if host == "" {
195 return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host}
197 if ip, zone := parseIPZone(host); ip != nil {
198 return []IPAddr{{IP: ip, Zone: zone}}, nil
200 trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace)
201 if trace != nil && trace.DNSStart != nil {
202 trace.DNSStart(host)
204 // The underlying resolver func is lookupIP by default but it
205 // can be overridden by tests. This is needed by net/http, so it
206 // uses a context key instead of unexported variables.
207 resolverFunc := r.lookupIP
208 if alt, _ := ctx.Value(nettrace.LookupIPAltResolverKey{}).(func(context.Context, string) ([]IPAddr, error)); alt != nil {
209 resolverFunc = alt
212 // We don't want a cancelation of ctx to affect the
213 // lookupGroup operation. Otherwise if our context gets
214 // canceled it might cause an error to be returned to a lookup
215 // using a completely different context.
216 lookupGroupCtx, lookupGroupCancel := context.WithCancel(context.Background())
218 dnsWaitGroup.Add(1)
219 ch, called := r.getLookupGroup().DoChan(host, func() (interface{}, error) {
220 defer dnsWaitGroup.Done()
221 return testHookLookupIP(lookupGroupCtx, resolverFunc, host)
223 if !called {
224 dnsWaitGroup.Done()
227 select {
228 case <-ctx.Done():
229 // Our context was canceled. If we are the only
230 // goroutine looking up this key, then drop the key
231 // from the lookupGroup and cancel the lookup.
232 // If there are other goroutines looking up this key,
233 // let the lookup continue uncanceled, and let later
234 // lookups with the same key share the result.
235 // See issues 8602, 20703, 22724.
236 if r.getLookupGroup().ForgetUnshared(host) {
237 lookupGroupCancel()
238 } else {
239 go func() {
240 <-ch
241 lookupGroupCancel()
244 err := mapErr(ctx.Err())
245 if trace != nil && trace.DNSDone != nil {
246 trace.DNSDone(nil, false, err)
248 return nil, err
249 case r := <-ch:
250 lookupGroupCancel()
251 if trace != nil && trace.DNSDone != nil {
252 addrs, _ := r.Val.([]IPAddr)
253 trace.DNSDone(ipAddrsEface(addrs), r.Shared, r.Err)
255 return lookupIPReturn(r.Val, r.Err, r.Shared)
259 // lookupIPReturn turns the return values from singleflight.Do into
260 // the return values from LookupIP.
261 func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IPAddr, error) {
262 if err != nil {
263 return nil, err
265 addrs := addrsi.([]IPAddr)
266 if shared {
267 clone := make([]IPAddr, len(addrs))
268 copy(clone, addrs)
269 addrs = clone
271 return addrs, nil
274 // ipAddrsEface returns an empty interface slice of addrs.
275 func ipAddrsEface(addrs []IPAddr) []interface{} {
276 s := make([]interface{}, len(addrs))
277 for i, v := range addrs {
278 s[i] = v
280 return s
283 // LookupPort looks up the port for the given network and service.
284 func LookupPort(network, service string) (port int, err error) {
285 return DefaultResolver.LookupPort(context.Background(), network, service)
288 // LookupPort looks up the port for the given network and service.
289 func (r *Resolver) LookupPort(ctx context.Context, network, service string) (port int, err error) {
290 port, needsLookup := parsePort(service)
291 if needsLookup {
292 port, err = r.lookupPort(ctx, network, service)
293 if err != nil {
294 return 0, err
297 if 0 > port || port > 65535 {
298 return 0, &AddrError{Err: "invalid port", Addr: service}
300 return port, nil
303 // LookupCNAME returns the canonical name for the given host.
304 // Callers that do not care about the canonical name can call
305 // LookupHost or LookupIP directly; both take care of resolving
306 // the canonical name as part of the lookup.
308 // A canonical name is the final name after following zero
309 // or more CNAME records.
310 // LookupCNAME does not return an error if host does not
311 // contain DNS "CNAME" records, as long as host resolves to
312 // address records.
313 func LookupCNAME(host string) (cname string, err error) {
314 return DefaultResolver.lookupCNAME(context.Background(), host)
317 // LookupCNAME returns the canonical name for the given host.
318 // Callers that do not care about the canonical name can call
319 // LookupHost or LookupIP directly; both take care of resolving
320 // the canonical name as part of the lookup.
322 // A canonical name is the final name after following zero
323 // or more CNAME records.
324 // LookupCNAME does not return an error if host does not
325 // contain DNS "CNAME" records, as long as host resolves to
326 // address records.
327 func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string, err error) {
328 return r.lookupCNAME(ctx, host)
331 // LookupSRV tries to resolve an SRV query of the given service,
332 // protocol, and domain name. The proto is "tcp" or "udp".
333 // The returned records are sorted by priority and randomized
334 // by weight within a priority.
336 // LookupSRV constructs the DNS name to look up following RFC 2782.
337 // That is, it looks up _service._proto.name. To accommodate services
338 // publishing SRV records under non-standard names, if both service
339 // and proto are empty strings, LookupSRV looks up name directly.
340 func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
341 return DefaultResolver.lookupSRV(context.Background(), service, proto, name)
344 // LookupSRV tries to resolve an SRV query of the given service,
345 // protocol, and domain name. The proto is "tcp" or "udp".
346 // The returned records are sorted by priority and randomized
347 // by weight within a priority.
349 // LookupSRV constructs the DNS name to look up following RFC 2782.
350 // That is, it looks up _service._proto.name. To accommodate services
351 // publishing SRV records under non-standard names, if both service
352 // and proto are empty strings, LookupSRV looks up name directly.
353 func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) {
354 return r.lookupSRV(ctx, service, proto, name)
357 // LookupMX returns the DNS MX records for the given domain name sorted by preference.
358 func LookupMX(name string) ([]*MX, error) {
359 return DefaultResolver.lookupMX(context.Background(), name)
362 // LookupMX returns the DNS MX records for the given domain name sorted by preference.
363 func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
364 return r.lookupMX(ctx, name)
367 // LookupNS returns the DNS NS records for the given domain name.
368 func LookupNS(name string) ([]*NS, error) {
369 return DefaultResolver.lookupNS(context.Background(), name)
372 // LookupNS returns the DNS NS records for the given domain name.
373 func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) {
374 return r.lookupNS(ctx, name)
377 // LookupTXT returns the DNS TXT records for the given domain name.
378 func LookupTXT(name string) ([]string, error) {
379 return DefaultResolver.lookupTXT(context.Background(), name)
382 // LookupTXT returns the DNS TXT records for the given domain name.
383 func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error) {
384 return r.lookupTXT(ctx, name)
387 // LookupAddr performs a reverse lookup for the given address, returning a list
388 // of names mapping to that address.
390 // When using the host C library resolver, at most one result will be
391 // returned. To bypass the host resolver, use a custom Resolver.
392 func LookupAddr(addr string) (names []string, err error) {
393 return DefaultResolver.lookupAddr(context.Background(), addr)
396 // LookupAddr performs a reverse lookup for the given address, returning a list
397 // of names mapping to that address.
398 func (r *Resolver) LookupAddr(ctx context.Context, addr string) (names []string, err error) {
399 return r.lookupAddr(ctx, addr)