Copyright 2012 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package net

import (
	
	
	
	
)
protocols contains minimal mappings between internet protocol names and numbers for platforms that don't have a complete list of protocol numbers. See https://www.iana.org/assignments/protocol-numbers On Unix, this map is augmented by readProtocols via lookupProtocol.
var protocols = map[string]int{
	"icmp":      1,
	"igmp":      2,
	"tcp":       6,
	"udp":       17,
	"ipv6-icmp": 58,
}
services contains minimal mappings between services names and port numbers for platforms that don't have a complete list of port numbers. See https://www.iana.org/assignments/service-names-port-numbers On Unix, this map is augmented by readServices via goLookupPort.
var services = map[string]map[string]int{
	"udp": {
		"domain": 53,
	},
	"tcp": {
		"ftp":    21,
		"ftps":   990,
		"gopher": 70, // ʕ◔ϖ◔ʔ
		"http":   80,
		"https":  443,
		"imap2":  143,
		"imap3":  220,
		"imaps":  993,
		"pop3":   110,
		"pop3s":  995,
		"smtp":   25,
		"ssh":    22,
		"telnet": 23,
	},
}
dnsWaitGroup can be used by tests to wait for all DNS goroutines to complete. This avoids races on the test hooks.
var dnsWaitGroup sync.WaitGroup

const maxProtoLength = len("RSVP-E2E-IGNORE") + 10 // with room to grow

func ( string) (int, error) {
	var  [maxProtoLength]byte
	 := copy([:], )
	lowerASCIIBytes([:])
	,  := protocols[string([:])]
	if ! ||  != len() {
		return 0, &AddrError{Err: "unknown IP protocol specified", Addr: }
	}
	return , nil
}
maxPortBufSize is the longest reasonable name of a service (non-numeric port). Currently the longest known IANA-unregistered name is "mobility-header", so we use that length, plus some slop in case something longer is added in the future.
const maxPortBufSize = len("mobility-header") + 10

func (,  string) ( int,  error) {
	switch  {
	case "tcp4", "tcp6":
		 = "tcp"
	case "udp4", "udp6":
		 = "udp"
	}

	if ,  := services[];  {
		var  [maxPortBufSize]byte
		 := copy([:], )
		lowerASCIIBytes([:])
		if ,  := [string([:])];  &&  == len() {
			return , nil
		}
	}
	return 0, &AddrError{Err: "unknown port", Addr:  + "/" + }
}
ipVersion returns the provided network's IP version: '4', '6' or 0 if network does not end in a '4' or '6' byte.
func ( string) byte {
	if  == "" {
		return 0
	}
	 := [len()-1]
	if  != '4' &&  != '6' {
		 = 0
	}
	return 
}
DefaultResolver is the resolver used by the package-level Lookup functions and by Dialers without a specified Resolver.
A Resolver looks up names and numbers. A nil *Resolver is equivalent to a zero Resolver.
PreferGo controls whether Go's built-in DNS resolver is preferred on platforms where it's available. It is equivalent to setting GODEBUG=netdns=go, but scoped to just this resolver.
StrictErrors controls the behavior of temporary errors (including timeout, socket errors, and SERVFAIL) when using Go's built-in resolver. For a query composed of multiple sub-queries (such as an A+AAAA address lookup, or walking the DNS search list), this option causes such errors to abort the whole query instead of returning a partial result. This is not enabled by default because it may affect compatibility with resolvers that process AAAA queries incorrectly.
Dial optionally specifies an alternate dialer for use by Go's built-in DNS resolver to make TCP and UDP connections to DNS services. The host in the address parameter will always be a literal IP address and not a host name, and the port in the address parameter will be a literal port number and not a service name. If the Conn returned is also a PacketConn, sent and received DNS messages must adhere to RFC 1035 section 4.2.1, "UDP usage". Otherwise, DNS messages transmitted over Conn must adhere to RFC 7766 section 5, "Transport Protocol Selection". If nil, the default dialer is used.
	Dial func(ctx context.Context, network, address string) (Conn, error)
lookupGroup merges LookupIPAddr calls together for lookups for the same host. The lookupGroup key is the LookupIPAddr.host argument. The return values are ([]IPAddr, error).
TODO(bradfitz): optional interface impl override hook TODO(bradfitz): Timeout time.Duration?
}

func ( *Resolver) () bool     { return  != nil && .PreferGo }
func ( *Resolver) () bool { return  != nil && .StrictErrors }

func ( *Resolver) () *singleflight.Group {
	if  == nil {
		return &DefaultResolver.lookupGroup
	}
	return &.lookupGroup
}
LookupHost looks up the given host using the local resolver. It returns a slice of that host's addresses.
func ( string) ( []string,  error) {
	return DefaultResolver.LookupHost(context.Background(), )
}
LookupHost looks up the given host using the local resolver. It returns a slice of that host's addresses.
Make sure that no matter what we do later, host=="" is rejected. parseIP, for example, does accept empty strings.
	if  == "" {
		return nil, &DNSError{Err: errNoSuchHost.Error(), Name: , IsNotFound: true}
	}
	if ,  := parseIPZone();  != nil {
		return []string{}, nil
	}
	return .lookupHost(, )
}
LookupIP looks up host using the local resolver. It returns a slice of that host's IPv4 and IPv6 addresses.
func ( string) ([]IP, error) {
	,  := DefaultResolver.LookupIPAddr(context.Background(), )
	if  != nil {
		return nil, 
	}
	 := make([]IP, len())
	for ,  := range  {
		[] = .IP
	}
	return , nil
}
LookupIPAddr looks up host using the local resolver. It returns a slice of that host's IPv4 and IPv6 addresses.
func ( *Resolver) ( context.Context,  string) ([]IPAddr, error) {
	return .lookupIPAddr(, "ip", )
}
LookupIP looks up host for the given network using the local resolver. It returns a slice of that host's IP addresses of the type specified by network. network must be one of "ip", "ip4" or "ip6".
func ( *Resolver) ( context.Context, ,  string) ([]IP, error) {
	, ,  := parseNetwork(, , false)
	if  != nil {
		return nil, 
	}
	switch  {
	case "ip", "ip4", "ip6":
	default:
		return nil, UnknownNetworkError()
	}
	,  := .internetAddrList(, , )
	if  != nil {
		return nil, 
	}
	 := make([]IP, 0, len())
	for ,  := range  {
		 = append(, .(*IPAddr).IP)
	}
	return , nil
}
onlyValuesCtx is a context that uses an underlying context for value lookup if the underlying context hasn't yet expired.
Value performs a lookup if the original context hasn't expired.
func ( *onlyValuesCtx) ( interface{}) interface{} {
	select {
	case <-.lookupValues.Done():
		return nil
	default:
		return .lookupValues.Value()
	}
}
withUnexpiredValuesPreserved returns a context.Context that only uses lookupCtx for its values, otherwise it is never canceled and has no deadline. If the lookup context expires, any looked up values will return nil. See Issue 28600.
lookupIPAddr looks up host using the local resolver and particular network. It returns a slice of that host's IPv4 and IPv6 addresses.
Make sure that no matter what we do later, host=="" is rejected. parseIP, for example, does accept empty strings.
	if  == "" {
		return nil, &DNSError{Err: errNoSuchHost.Error(), Name: , IsNotFound: true}
	}
	if ,  := parseIPZone();  != nil {
		return []IPAddr{{IP: , Zone: }}, nil
	}
	,  := .Value(nettrace.TraceKey{}).(*nettrace.Trace)
	if  != nil && .DNSStart != nil {
		.DNSStart()
The underlying resolver func is lookupIP by default but it can be overridden by tests. This is needed by net/http, so it uses a context key instead of unexported variables.
	 := .lookupIP
	if ,  := .Value(nettrace.LookupIPAltResolverKey{}).(func(context.Context, string, string) ([]IPAddr, error));  != nil {
		 = 
	}
We don't want a cancellation of ctx to affect the lookupGroup operation. Otherwise if our context gets canceled it might cause an error to be returned to a lookup using a completely different context. However we need to preserve only the values in context. See Issue 28600.
	,  := context.WithCancel(withUnexpiredValuesPreserved())

	 :=  + "\000" + 
	dnsWaitGroup.Add(1)
	,  := .getLookupGroup().DoChan(, func() (interface{}, error) {
		defer dnsWaitGroup.Done()
		return testHookLookupIP(, , , )
	})
	if ! {
		dnsWaitGroup.Done()
	}

	select {
Our context was canceled. If we are the only goroutine looking up this key, then drop the key from the lookupGroup and cancel the lookup. If there are other goroutines looking up this key, let the lookup continue uncanceled, and let later lookups with the same key share the result. See issues 8602, 20703, 22724.
		if .getLookupGroup().ForgetUnshared() {
			()
		} else {
			go func() {
				<-
				()
			}()
		}
		 := mapErr(.Err())
		if  != nil && .DNSDone != nil {
			.DNSDone(nil, false, )
		}
		return nil, 
	case  := <-:
		()
		if  != nil && .DNSDone != nil {
			,  := .Val.([]IPAddr)
			.DNSDone(ipAddrsEface(), .Shared, .Err)
		}
		return lookupIPReturn(.Val, .Err, .Shared)
	}
}
lookupIPReturn turns the return values from singleflight.Do into the return values from LookupIP.
func ( interface{},  error,  bool) ([]IPAddr, error) {
	if  != nil {
		return nil, 
	}
	 := .([]IPAddr)
	if  {
		 := make([]IPAddr, len())
		copy(, )
		 = 
	}
	return , nil
}
ipAddrsEface returns an empty interface slice of addrs.
func ( []IPAddr) []interface{} {
	 := make([]interface{}, len())
	for ,  := range  {
		[] = 
	}
	return 
}
LookupPort looks up the port for the given network and service.
func (,  string) ( int,  error) {
	return DefaultResolver.LookupPort(context.Background(), , )
}
LookupPort looks up the port for the given network and service.
func ( *Resolver) ( context.Context, ,  string) ( int,  error) {
	,  := parsePort()
	if  {
		switch  {
		case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
		case "": // a hint wildcard for Go 1.0 undocumented behavior
			 = "ip"
		default:
			return 0, &AddrError{Err: "unknown network", Addr: }
		}
		,  = .lookupPort(, , )
		if  != nil {
			return 0, 
		}
	}
	if 0 >  ||  > 65535 {
		return 0, &AddrError{Err: "invalid port", Addr: }
	}
	return , nil
}
LookupCNAME returns the canonical name for the given host. Callers that do not care about the canonical name can call LookupHost or LookupIP directly; both take care of resolving the canonical name as part of the lookup. A canonical name is the final name after following zero or more CNAME records. LookupCNAME does not return an error if host does not contain DNS "CNAME" records, as long as host resolves to address records.
func ( string) ( string,  error) {
	return DefaultResolver.lookupCNAME(context.Background(), )
}
LookupCNAME returns the canonical name for the given host. Callers that do not care about the canonical name can call LookupHost or LookupIP directly; both take care of resolving the canonical name as part of the lookup. A canonical name is the final name after following zero or more CNAME records. LookupCNAME does not return an error if host does not contain DNS "CNAME" records, as long as host resolves to address records.
func ( *Resolver) ( context.Context,  string) ( string,  error) {
	return .lookupCNAME(, )
}
LookupSRV tries to resolve an SRV query of the given service, protocol, and domain name. The proto is "tcp" or "udp". The returned records are sorted by priority and randomized by weight within a priority. LookupSRV constructs the DNS name to look up following RFC 2782. That is, it looks up _service._proto.name. To accommodate services publishing SRV records under non-standard names, if both service and proto are empty strings, LookupSRV looks up name directly.
func (, ,  string) ( string,  []*SRV,  error) {
	return DefaultResolver.lookupSRV(context.Background(), , , )
}
LookupSRV tries to resolve an SRV query of the given service, protocol, and domain name. The proto is "tcp" or "udp". The returned records are sorted by priority and randomized by weight within a priority. LookupSRV constructs the DNS name to look up following RFC 2782. That is, it looks up _service._proto.name. To accommodate services publishing SRV records under non-standard names, if both service and proto are empty strings, LookupSRV looks up name directly.
func ( *Resolver) ( context.Context, , ,  string) ( string,  []*SRV,  error) {
	return .lookupSRV(, , , )
}
LookupMX returns the DNS MX records for the given domain name sorted by preference.
func ( string) ([]*MX, error) {
	return DefaultResolver.lookupMX(context.Background(), )
}
LookupMX returns the DNS MX records for the given domain name sorted by preference.
func ( *Resolver) ( context.Context,  string) ([]*MX, error) {
	return .lookupMX(, )
}
LookupNS returns the DNS NS records for the given domain name.
func ( string) ([]*NS, error) {
	return DefaultResolver.lookupNS(context.Background(), )
}
LookupNS returns the DNS NS records for the given domain name.
func ( *Resolver) ( context.Context,  string) ([]*NS, error) {
	return .lookupNS(, )
}
LookupTXT returns the DNS TXT records for the given domain name.
LookupTXT returns the DNS TXT records for the given domain name.
func ( *Resolver) ( context.Context,  string) ([]string, error) {
	return .lookupTXT(, )
}
LookupAddr performs a reverse lookup for the given address, returning a list of names mapping to that address. When using the host C library resolver, at most one result will be returned. To bypass the host resolver, use a custom Resolver.
func ( string) ( []string,  error) {
	return DefaultResolver.lookupAddr(context.Background(), )
}
LookupAddr performs a reverse lookup for the given address, returning a list of names mapping to that address.
func ( *Resolver) ( context.Context,  string) ( []string,  error) {
	return .lookupAddr(, )