libgo: update to go1.9
[official-gcc.git] / libgo / go / net / lookup.go
blobc9f327050afad8a7c6323d63985b5c3fd18d18f5
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"
13 // protocols contains minimal mappings between internet protocol
14 // names and numbers for platforms that don't have a complete list of
15 // protocol numbers.
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{
21 "icmp": 1,
22 "igmp": 2,
23 "tcp": 6,
24 "udp": 17,
25 "ipv6-icmp": 58,
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{
36 "udp": {
37 "domain": 53,
39 "tcp": {
40 "ftp": 21,
41 "ftps": 990,
42 "gopher": 70, // ʕ◔ϖ◔ʔ
43 "http": 80,
44 "https": 443,
45 "imap2": 143,
46 "imap3": 220,
47 "imaps": 993,
48 "pop3": 110,
49 "pop3s": 995,
50 "smtp": 25,
51 "ssh": 22,
52 "telnet": 23,
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}
66 return proto, nil
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) {
77 switch network {
78 case "tcp4", "tcp6":
79 network = "tcp"
80 case "udp4", "udp6":
81 network = "udp"
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) {
89 return port, nil
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.
106 PreferGo bool
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.
116 StrictErrors bool
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.
146 if host == "" {
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)
159 if err != nil {
160 return nil, err
162 ips := make([]IP, len(addrs))
163 for i, ia := range addrs {
164 ips[i] = ia.IP
166 return ips, nil
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.
174 if host == "" {
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 {
182 trace.DNSStart(host)
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 {
189 resolverFunc = alt
192 ch := lookupGroup.DoChan(host, func() (interface{}, error) {
193 return testHookLookupIP(ctx, resolverFunc, host)
196 select {
197 case <-ctx.Done():
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.
202 ctxErr := ctx.Err()
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)
210 return nil, err
211 case r := <-ch:
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
222 // argument.
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) {
229 if err != nil {
230 return nil, err
232 addrs := addrsi.([]IPAddr)
233 if shared {
234 clone := make([]IPAddr, len(addrs))
235 copy(clone, addrs)
236 addrs = clone
238 return addrs, nil
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 {
245 s[i] = v
247 return s
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)
258 if needsLookup {
259 port, err = r.lookupPort(ctx, network, service)
260 if err != nil {
261 return 0, err
264 if 0 > port || port > 65535 {
265 return 0, &AddrError{Err: "invalid port", Addr: service}
267 return port, nil
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
279 // address records.
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
293 // address records.
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)