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. 4 5 package net 6 7 import ( 8 "context" 9 "internal/nettrace" 10 "internal/singleflight" 11 "sync" 12 ) 13 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. 17 // 18 // See http://www.iana.org/assignments/protocol-numbers 19 // 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, 27 } 28 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). 32 // 33 // See https://www.iana.org/assignments/service-names-port-numbers 34 // 35 // On Unix, this map is augmented by readServices via goLookupPort. 36 var services = map[string]map[string]int{ 37 "udp": { 38 "domain": 53, 39 }, 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, 54 }, 55 } 56 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 60 61 const maxProtoLength = len("RSVP-E2E-IGNORE") + 10 // with room to grow 62 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} 70 } 71 return proto, nil 72 } 73 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 80 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" 87 } 88 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 95 } 96 } 97 return 0, &AddrError{Err: "unknown port", Addr: network + "/" + service} 98 } 99 100 // DefaultResolver is the resolver used by the package-level Lookup 101 // functions and by Dialers without a specified Resolver. 102 var DefaultResolver = &Resolver{} 103 104 // A Resolver looks up names and numbers. 105 // 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 112 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 122 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) 135 136 // TODO(bradfitz): optional interface impl override hook 137 // TODO(bradfitz): Timeout time.Duration? 138 } 139 140 // LookupHost looks up the given host using the local resolver. 141 // It returns a slice of that host's addresses. 142 func LookupHost(host string) (addrs []string, err error) { 143 return DefaultResolver.LookupHost(context.Background(), host) 144 } 145 146 // LookupHost looks up the given host using the local resolver. 147 // It returns a slice of that host's addresses. 148 func (r *Resolver) LookupHost(ctx context.Context, host string) (addrs []string, err error) { 149 // Make sure that no matter what we do later, host=="" is rejected. 150 // ParseIP, for example, does accept empty strings. 151 if host == "" { 152 return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host} 153 } 154 if ip := ParseIP(host); ip != nil { 155 return []string{host}, nil 156 } 157 return r.lookupHost(ctx, host) 158 } 159 160 // LookupIP looks up host using the local resolver. 161 // It returns a slice of that host's IPv4 and IPv6 addresses. 162 func LookupIP(host string) ([]IP, error) { 163 addrs, err := DefaultResolver.LookupIPAddr(context.Background(), host) 164 if err != nil { 165 return nil, err 166 } 167 ips := make([]IP, len(addrs)) 168 for i, ia := range addrs { 169 ips[i] = ia.IP 170 } 171 return ips, nil 172 } 173 174 // LookupIPAddr looks up host using the local resolver. 175 // It returns a slice of that host's IPv4 and IPv6 addresses. 176 func (r *Resolver) LookupIPAddr(ctx context.Context, host string) ([]IPAddr, error) { 177 // Make sure that no matter what we do later, host=="" is rejected. 178 // ParseIP, for example, does accept empty strings. 179 if host == "" { 180 return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host} 181 } 182 if ip := ParseIP(host); ip != nil { 183 return []IPAddr{{IP: ip}}, nil 184 } 185 trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace) 186 if trace != nil && trace.DNSStart != nil { 187 trace.DNSStart(host) 188 } 189 // The underlying resolver func is lookupIP by default but it 190 // can be overridden by tests. This is needed by net/http, so it 191 // uses a context key instead of unexported variables. 192 resolverFunc := r.lookupIP 193 if alt, _ := ctx.Value(nettrace.LookupIPAltResolverKey{}).(func(context.Context, string) ([]IPAddr, error)); alt != nil { 194 resolverFunc = alt 195 } 196 197 dnsWaitGroup.Add(1) 198 ch, called := lookupGroup.DoChan(host, func() (interface{}, error) { 199 defer dnsWaitGroup.Done() 200 return testHookLookupIP(ctx, resolverFunc, host) 201 }) 202 if !called { 203 dnsWaitGroup.Done() 204 } 205 206 select { 207 case <-ctx.Done(): 208 // If the DNS lookup timed out for some reason, force 209 // future requests to start the DNS lookup again 210 // rather than waiting for the current lookup to 211 // complete. See issue 8602. 212 ctxErr := ctx.Err() 213 if ctxErr == context.DeadlineExceeded { 214 lookupGroup.Forget(host) 215 } 216 err := mapErr(ctxErr) 217 if trace != nil && trace.DNSDone != nil { 218 trace.DNSDone(nil, false, err) 219 } 220 return nil, err 221 case r := <-ch: 222 if trace != nil && trace.DNSDone != nil { 223 addrs, _ := r.Val.([]IPAddr) 224 trace.DNSDone(ipAddrsEface(addrs), r.Shared, r.Err) 225 } 226 return lookupIPReturn(r.Val, r.Err, r.Shared) 227 } 228 } 229 230 // lookupGroup merges LookupIPAddr calls together for lookups 231 // for the same host. The lookupGroup key is is the LookupIPAddr.host 232 // argument. 233 // The return values are ([]IPAddr, error). 234 var lookupGroup singleflight.Group 235 236 // lookupIPReturn turns the return values from singleflight.Do into 237 // the return values from LookupIP. 238 func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IPAddr, error) { 239 if err != nil { 240 return nil, err 241 } 242 addrs := addrsi.([]IPAddr) 243 if shared { 244 clone := make([]IPAddr, len(addrs)) 245 copy(clone, addrs) 246 addrs = clone 247 } 248 return addrs, nil 249 } 250 251 // ipAddrsEface returns an empty interface slice of addrs. 252 func ipAddrsEface(addrs []IPAddr) []interface{} { 253 s := make([]interface{}, len(addrs)) 254 for i, v := range addrs { 255 s[i] = v 256 } 257 return s 258 } 259 260 // LookupPort looks up the port for the given network and service. 261 func LookupPort(network, service string) (port int, err error) { 262 return DefaultResolver.LookupPort(context.Background(), network, service) 263 } 264 265 // LookupPort looks up the port for the given network and service. 266 func (r *Resolver) LookupPort(ctx context.Context, network, service string) (port int, err error) { 267 port, needsLookup := parsePort(service) 268 if needsLookup { 269 port, err = r.lookupPort(ctx, network, service) 270 if err != nil { 271 return 0, err 272 } 273 } 274 if 0 > port || port > 65535 { 275 return 0, &AddrError{Err: "invalid port", Addr: service} 276 } 277 return port, nil 278 } 279 280 // LookupCNAME returns the canonical name for the given host. 281 // Callers that do not care about the canonical name can call 282 // LookupHost or LookupIP directly; both take care of resolving 283 // the canonical name as part of the lookup. 284 // 285 // A canonical name is the final name after following zero 286 // or more CNAME records. 287 // LookupCNAME does not return an error if host does not 288 // contain DNS "CNAME" records, as long as host resolves to 289 // address records. 290 func LookupCNAME(host string) (cname string, err error) { 291 return DefaultResolver.lookupCNAME(context.Background(), host) 292 } 293 294 // LookupCNAME returns the canonical name for the given host. 295 // Callers that do not care about the canonical name can call 296 // LookupHost or LookupIP directly; both take care of resolving 297 // the canonical name as part of the lookup. 298 // 299 // A canonical name is the final name after following zero 300 // or more CNAME records. 301 // LookupCNAME does not return an error if host does not 302 // contain DNS "CNAME" records, as long as host resolves to 303 // address records. 304 func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string, err error) { 305 return r.lookupCNAME(ctx, host) 306 } 307 308 // LookupSRV tries to resolve an SRV query of the given service, 309 // protocol, and domain name. The proto is "tcp" or "udp". 310 // The returned records are sorted by priority and randomized 311 // by weight within a priority. 312 // 313 // LookupSRV constructs the DNS name to look up following RFC 2782. 314 // That is, it looks up _service._proto.name. To accommodate services 315 // publishing SRV records under non-standard names, if both service 316 // and proto are empty strings, LookupSRV looks up name directly. 317 func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) { 318 return DefaultResolver.lookupSRV(context.Background(), service, proto, name) 319 } 320 321 // LookupSRV tries to resolve an SRV query of the given service, 322 // protocol, and domain name. The proto is "tcp" or "udp". 323 // The returned records are sorted by priority and randomized 324 // by weight within a priority. 325 // 326 // LookupSRV constructs the DNS name to look up following RFC 2782. 327 // That is, it looks up _service._proto.name. To accommodate services 328 // publishing SRV records under non-standard names, if both service 329 // and proto are empty strings, LookupSRV looks up name directly. 330 func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) { 331 return r.lookupSRV(ctx, service, proto, name) 332 } 333 334 // LookupMX returns the DNS MX records for the given domain name sorted by preference. 335 func LookupMX(name string) ([]*MX, error) { 336 return DefaultResolver.lookupMX(context.Background(), name) 337 } 338 339 // LookupMX returns the DNS MX records for the given domain name sorted by preference. 340 func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) { 341 return r.lookupMX(ctx, name) 342 } 343 344 // LookupNS returns the DNS NS records for the given domain name. 345 func LookupNS(name string) ([]*NS, error) { 346 return DefaultResolver.lookupNS(context.Background(), name) 347 } 348 349 // LookupNS returns the DNS NS records for the given domain name. 350 func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) { 351 return r.lookupNS(ctx, name) 352 } 353 354 // LookupTXT returns the DNS TXT records for the given domain name. 355 func LookupTXT(name string) ([]string, error) { 356 return DefaultResolver.lookupTXT(context.Background(), name) 357 } 358 359 // LookupTXT returns the DNS TXT records for the given domain name. 360 func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error) { 361 return r.lookupTXT(ctx, name) 362 } 363 364 // LookupAddr performs a reverse lookup for the given address, returning a list 365 // of names mapping to that address. 366 // 367 // When using the host C library resolver, at most one result will be 368 // returned. To bypass the host resolver, use a custom Resolver. 369 func LookupAddr(addr string) (names []string, err error) { 370 return DefaultResolver.lookupAddr(context.Background(), addr) 371 } 372 373 // LookupAddr performs a reverse lookup for the given address, returning a list 374 // of names mapping to that address. 375 func (r *Resolver) LookupAddr(ctx context.Context, addr string) (names []string, err error) { 376 return r.lookupAddr(ctx, addr) 377 } 378