...

Source file src/net/lookup.go

Documentation: net

		 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 https://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  //
		32  // See https://www.iana.org/assignments/service-names-port-numbers
		33  //
		34  // On Unix, this map is augmented by readServices via goLookupPort.
		35  var services = map[string]map[string]int{
		36  	"udp": {
		37  		"domain": 53,
		38  	},
		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,
		53  	},
		54  }
		55  
		56  // dnsWaitGroup can be used by tests to wait for all DNS goroutines to
		57  // complete. This avoids races on the test hooks.
		58  var dnsWaitGroup sync.WaitGroup
		59  
		60  const maxProtoLength = len("RSVP-E2E-IGNORE") + 10 // with room to grow
		61  
		62  func lookupProtocolMap(name string) (int, error) {
		63  	var lowerProtocol [maxProtoLength]byte
		64  	n := copy(lowerProtocol[:], name)
		65  	lowerASCIIBytes(lowerProtocol[:n])
		66  	proto, found := protocols[string(lowerProtocol[:n])]
		67  	if !found || n != len(name) {
		68  		return 0, &AddrError{Err: "unknown IP protocol specified", Addr: name}
		69  	}
		70  	return proto, nil
		71  }
		72  
		73  // maxPortBufSize is the longest reasonable name of a service
		74  // (non-numeric port).
		75  // Currently the longest known IANA-unregistered name is
		76  // "mobility-header", so we use that length, plus some slop in case
		77  // something longer is added in the future.
		78  const maxPortBufSize = len("mobility-header") + 10
		79  
		80  func lookupPortMap(network, service string) (port int, error error) {
		81  	switch network {
		82  	case "tcp4", "tcp6":
		83  		network = "tcp"
		84  	case "udp4", "udp6":
		85  		network = "udp"
		86  	}
		87  
		88  	if m, ok := services[network]; ok {
		89  		var lowerService [maxPortBufSize]byte
		90  		n := copy(lowerService[:], service)
		91  		lowerASCIIBytes(lowerService[:n])
		92  		if port, ok := m[string(lowerService[:n])]; ok && n == len(service) {
		93  			return port, nil
		94  		}
		95  	}
		96  	return 0, &AddrError{Err: "unknown port", Addr: network + "/" + service}
		97  }
		98  
		99  // ipVersion returns the provided network's IP version: '4', '6' or 0
	 100  // if network does not end in a '4' or '6' byte.
	 101  func ipVersion(network string) byte {
	 102  	if network == "" {
	 103  		return 0
	 104  	}
	 105  	n := network[len(network)-1]
	 106  	if n != '4' && n != '6' {
	 107  		n = 0
	 108  	}
	 109  	return n
	 110  }
	 111  
	 112  // DefaultResolver is the resolver used by the package-level Lookup
	 113  // functions and by Dialers without a specified Resolver.
	 114  var DefaultResolver = &Resolver{}
	 115  
	 116  // A Resolver looks up names and numbers.
	 117  //
	 118  // A nil *Resolver is equivalent to a zero Resolver.
	 119  type Resolver struct {
	 120  	// PreferGo controls whether Go's built-in DNS resolver is preferred
	 121  	// on platforms where it's available. It is equivalent to setting
	 122  	// GODEBUG=netdns=go, but scoped to just this resolver.
	 123  	PreferGo bool
	 124  
	 125  	// StrictErrors controls the behavior of temporary errors
	 126  	// (including timeout, socket errors, and SERVFAIL) when using
	 127  	// Go's built-in resolver. For a query composed of multiple
	 128  	// sub-queries (such as an A+AAAA address lookup, or walking the
	 129  	// DNS search list), this option causes such errors to abort the
	 130  	// whole query instead of returning a partial result. This is
	 131  	// not enabled by default because it may affect compatibility
	 132  	// with resolvers that process AAAA queries incorrectly.
	 133  	StrictErrors bool
	 134  
	 135  	// Dial optionally specifies an alternate dialer for use by
	 136  	// Go's built-in DNS resolver to make TCP and UDP connections
	 137  	// to DNS services. The host in the address parameter will
	 138  	// always be a literal IP address and not a host name, and the
	 139  	// port in the address parameter will be a literal port number
	 140  	// and not a service name.
	 141  	// If the Conn returned is also a PacketConn, sent and received DNS
	 142  	// messages must adhere to RFC 1035 section 4.2.1, "UDP usage".
	 143  	// Otherwise, DNS messages transmitted over Conn must adhere
	 144  	// to RFC 7766 section 5, "Transport Protocol Selection".
	 145  	// If nil, the default dialer is used.
	 146  	Dial func(ctx context.Context, network, address string) (Conn, error)
	 147  
	 148  	// lookupGroup merges LookupIPAddr calls together for lookups for the same
	 149  	// host. The lookupGroup key is the LookupIPAddr.host argument.
	 150  	// The return values are ([]IPAddr, error).
	 151  	lookupGroup singleflight.Group
	 152  
	 153  	// TODO(bradfitz): optional interface impl override hook
	 154  	// TODO(bradfitz): Timeout time.Duration?
	 155  }
	 156  
	 157  func (r *Resolver) preferGo() bool		 { return r != nil && r.PreferGo }
	 158  func (r *Resolver) strictErrors() bool { return r != nil && r.StrictErrors }
	 159  
	 160  func (r *Resolver) getLookupGroup() *singleflight.Group {
	 161  	if r == nil {
	 162  		return &DefaultResolver.lookupGroup
	 163  	}
	 164  	return &r.lookupGroup
	 165  }
	 166  
	 167  // LookupHost looks up the given host using the local resolver.
	 168  // It returns a slice of that host's addresses.
	 169  //
	 170  // LookupHost uses context.Background internally; to specify the context, use
	 171  // Resolver.LookupHost.
	 172  func LookupHost(host string) (addrs []string, err error) {
	 173  	return DefaultResolver.LookupHost(context.Background(), host)
	 174  }
	 175  
	 176  // LookupHost looks up the given host using the local resolver.
	 177  // It returns a slice of that host's addresses.
	 178  func (r *Resolver) LookupHost(ctx context.Context, host string) (addrs []string, err error) {
	 179  	// Make sure that no matter what we do later, host=="" is rejected.
	 180  	// parseIP, for example, does accept empty strings.
	 181  	if host == "" {
	 182  		return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
	 183  	}
	 184  	if ip, _ := parseIPZone(host); ip != nil {
	 185  		return []string{host}, nil
	 186  	}
	 187  	return r.lookupHost(ctx, host)
	 188  }
	 189  
	 190  // LookupIP looks up host using the local resolver.
	 191  // It returns a slice of that host's IPv4 and IPv6 addresses.
	 192  func LookupIP(host string) ([]IP, error) {
	 193  	addrs, err := DefaultResolver.LookupIPAddr(context.Background(), host)
	 194  	if err != nil {
	 195  		return nil, err
	 196  	}
	 197  	ips := make([]IP, len(addrs))
	 198  	for i, ia := range addrs {
	 199  		ips[i] = ia.IP
	 200  	}
	 201  	return ips, nil
	 202  }
	 203  
	 204  // LookupIPAddr looks up host using the local resolver.
	 205  // It returns a slice of that host's IPv4 and IPv6 addresses.
	 206  func (r *Resolver) LookupIPAddr(ctx context.Context, host string) ([]IPAddr, error) {
	 207  	return r.lookupIPAddr(ctx, "ip", host)
	 208  }
	 209  
	 210  // LookupIP looks up host for the given network using the local resolver.
	 211  // It returns a slice of that host's IP addresses of the type specified by
	 212  // network.
	 213  // network must be one of "ip", "ip4" or "ip6".
	 214  func (r *Resolver) LookupIP(ctx context.Context, network, host string) ([]IP, error) {
	 215  	afnet, _, err := parseNetwork(ctx, network, false)
	 216  	if err != nil {
	 217  		return nil, err
	 218  	}
	 219  	switch afnet {
	 220  	case "ip", "ip4", "ip6":
	 221  	default:
	 222  		return nil, UnknownNetworkError(network)
	 223  	}
	 224  	addrs, err := r.internetAddrList(ctx, afnet, host)
	 225  	if err != nil {
	 226  		return nil, err
	 227  	}
	 228  	ips := make([]IP, 0, len(addrs))
	 229  	for _, addr := range addrs {
	 230  		ips = append(ips, addr.(*IPAddr).IP)
	 231  	}
	 232  	return ips, nil
	 233  }
	 234  
	 235  // onlyValuesCtx is a context that uses an underlying context
	 236  // for value lookup if the underlying context hasn't yet expired.
	 237  type onlyValuesCtx struct {
	 238  	context.Context
	 239  	lookupValues context.Context
	 240  }
	 241  
	 242  var _ context.Context = (*onlyValuesCtx)(nil)
	 243  
	 244  // Value performs a lookup if the original context hasn't expired.
	 245  func (ovc *onlyValuesCtx) Value(key interface{}) interface{} {
	 246  	select {
	 247  	case <-ovc.lookupValues.Done():
	 248  		return nil
	 249  	default:
	 250  		return ovc.lookupValues.Value(key)
	 251  	}
	 252  }
	 253  
	 254  // withUnexpiredValuesPreserved returns a context.Context that only uses lookupCtx
	 255  // for its values, otherwise it is never canceled and has no deadline.
	 256  // If the lookup context expires, any looked up values will return nil.
	 257  // See Issue 28600.
	 258  func withUnexpiredValuesPreserved(lookupCtx context.Context) context.Context {
	 259  	return &onlyValuesCtx{Context: context.Background(), lookupValues: lookupCtx}
	 260  }
	 261  
	 262  // lookupIPAddr looks up host using the local resolver and particular network.
	 263  // It returns a slice of that host's IPv4 and IPv6 addresses.
	 264  func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]IPAddr, error) {
	 265  	// Make sure that no matter what we do later, host=="" is rejected.
	 266  	// parseIP, for example, does accept empty strings.
	 267  	if host == "" {
	 268  		return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
	 269  	}
	 270  	if ip, zone := parseIPZone(host); ip != nil {
	 271  		return []IPAddr{{IP: ip, Zone: zone}}, nil
	 272  	}
	 273  	trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace)
	 274  	if trace != nil && trace.DNSStart != nil {
	 275  		trace.DNSStart(host)
	 276  	}
	 277  	// The underlying resolver func is lookupIP by default but it
	 278  	// can be overridden by tests. This is needed by net/http, so it
	 279  	// uses a context key instead of unexported variables.
	 280  	resolverFunc := r.lookupIP
	 281  	if alt, _ := ctx.Value(nettrace.LookupIPAltResolverKey{}).(func(context.Context, string, string) ([]IPAddr, error)); alt != nil {
	 282  		resolverFunc = alt
	 283  	}
	 284  
	 285  	// We don't want a cancellation of ctx to affect the
	 286  	// lookupGroup operation. Otherwise if our context gets
	 287  	// canceled it might cause an error to be returned to a lookup
	 288  	// using a completely different context. However we need to preserve
	 289  	// only the values in context. See Issue 28600.
	 290  	lookupGroupCtx, lookupGroupCancel := context.WithCancel(withUnexpiredValuesPreserved(ctx))
	 291  
	 292  	lookupKey := network + "\000" + host
	 293  	dnsWaitGroup.Add(1)
	 294  	ch, called := r.getLookupGroup().DoChan(lookupKey, func() (interface{}, error) {
	 295  		defer dnsWaitGroup.Done()
	 296  		return testHookLookupIP(lookupGroupCtx, resolverFunc, network, host)
	 297  	})
	 298  	if !called {
	 299  		dnsWaitGroup.Done()
	 300  	}
	 301  
	 302  	select {
	 303  	case <-ctx.Done():
	 304  		// Our context was canceled. If we are the only
	 305  		// goroutine looking up this key, then drop the key
	 306  		// from the lookupGroup and cancel the lookup.
	 307  		// If there are other goroutines looking up this key,
	 308  		// let the lookup continue uncanceled, and let later
	 309  		// lookups with the same key share the result.
	 310  		// See issues 8602, 20703, 22724.
	 311  		if r.getLookupGroup().ForgetUnshared(lookupKey) {
	 312  			lookupGroupCancel()
	 313  		} else {
	 314  			go func() {
	 315  				<-ch
	 316  				lookupGroupCancel()
	 317  			}()
	 318  		}
	 319  		err := mapErr(ctx.Err())
	 320  		if trace != nil && trace.DNSDone != nil {
	 321  			trace.DNSDone(nil, false, err)
	 322  		}
	 323  		return nil, err
	 324  	case r := <-ch:
	 325  		lookupGroupCancel()
	 326  		if trace != nil && trace.DNSDone != nil {
	 327  			addrs, _ := r.Val.([]IPAddr)
	 328  			trace.DNSDone(ipAddrsEface(addrs), r.Shared, r.Err)
	 329  		}
	 330  		return lookupIPReturn(r.Val, r.Err, r.Shared)
	 331  	}
	 332  }
	 333  
	 334  // lookupIPReturn turns the return values from singleflight.Do into
	 335  // the return values from LookupIP.
	 336  func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IPAddr, error) {
	 337  	if err != nil {
	 338  		return nil, err
	 339  	}
	 340  	addrs := addrsi.([]IPAddr)
	 341  	if shared {
	 342  		clone := make([]IPAddr, len(addrs))
	 343  		copy(clone, addrs)
	 344  		addrs = clone
	 345  	}
	 346  	return addrs, nil
	 347  }
	 348  
	 349  // ipAddrsEface returns an empty interface slice of addrs.
	 350  func ipAddrsEface(addrs []IPAddr) []interface{} {
	 351  	s := make([]interface{}, len(addrs))
	 352  	for i, v := range addrs {
	 353  		s[i] = v
	 354  	}
	 355  	return s
	 356  }
	 357  
	 358  // LookupPort looks up the port for the given network and service.
	 359  //
	 360  // LookupPort uses context.Background internally; to specify the context, use
	 361  // Resolver.LookupPort.
	 362  func LookupPort(network, service string) (port int, err error) {
	 363  	return DefaultResolver.LookupPort(context.Background(), network, service)
	 364  }
	 365  
	 366  // LookupPort looks up the port for the given network and service.
	 367  func (r *Resolver) LookupPort(ctx context.Context, network, service string) (port int, err error) {
	 368  	port, needsLookup := parsePort(service)
	 369  	if needsLookup {
	 370  		switch network {
	 371  		case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
	 372  		case "": // a hint wildcard for Go 1.0 undocumented behavior
	 373  			network = "ip"
	 374  		default:
	 375  			return 0, &AddrError{Err: "unknown network", Addr: network}
	 376  		}
	 377  		port, err = r.lookupPort(ctx, network, service)
	 378  		if err != nil {
	 379  			return 0, err
	 380  		}
	 381  	}
	 382  	if 0 > port || port > 65535 {
	 383  		return 0, &AddrError{Err: "invalid port", Addr: service}
	 384  	}
	 385  	return port, nil
	 386  }
	 387  
	 388  // LookupCNAME returns the canonical name for the given host.
	 389  // Callers that do not care about the canonical name can call
	 390  // LookupHost or LookupIP directly; both take care of resolving
	 391  // the canonical name as part of the lookup.
	 392  //
	 393  // A canonical name is the final name after following zero
	 394  // or more CNAME records.
	 395  // LookupCNAME does not return an error if host does not
	 396  // contain DNS "CNAME" records, as long as host resolves to
	 397  // address records.
	 398  //
	 399  // The returned canonical name is validated to be a properly
	 400  // formatted presentation-format domain name.
	 401  //
	 402  // LookupCNAME uses context.Background internally; to specify the context, use
	 403  // Resolver.LookupCNAME.
	 404  func LookupCNAME(host string) (cname string, err error) {
	 405  	return DefaultResolver.LookupCNAME(context.Background(), host)
	 406  }
	 407  
	 408  // LookupCNAME returns the canonical name for the given host.
	 409  // Callers that do not care about the canonical name can call
	 410  // LookupHost or LookupIP directly; both take care of resolving
	 411  // the canonical name as part of the lookup.
	 412  //
	 413  // A canonical name is the final name after following zero
	 414  // or more CNAME records.
	 415  // LookupCNAME does not return an error if host does not
	 416  // contain DNS "CNAME" records, as long as host resolves to
	 417  // address records.
	 418  //
	 419  // The returned canonical name is validated to be a properly
	 420  // formatted presentation-format domain name.
	 421  func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error) {
	 422  	cname, err := r.lookupCNAME(ctx, host)
	 423  	if err != nil {
	 424  		return "", err
	 425  	}
	 426  	if !isDomainName(cname) {
	 427  		return "", &DNSError{Err: errMalformedDNSRecordsDetail, Name: host}
	 428  	}
	 429  	return cname, nil
	 430  }
	 431  
	 432  // LookupSRV tries to resolve an SRV query of the given service,
	 433  // protocol, and domain name. The proto is "tcp" or "udp".
	 434  // The returned records are sorted by priority and randomized
	 435  // by weight within a priority.
	 436  //
	 437  // LookupSRV constructs the DNS name to look up following RFC 2782.
	 438  // That is, it looks up _service._proto.name. To accommodate services
	 439  // publishing SRV records under non-standard names, if both service
	 440  // and proto are empty strings, LookupSRV looks up name directly.
	 441  //
	 442  // The returned service names are validated to be properly
	 443  // formatted presentation-format domain names. If the response contains
	 444  // invalid names, those records are filtered out and an error
	 445  // will be returned alongside the the remaining results, if any.
	 446  func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
	 447  	return DefaultResolver.LookupSRV(context.Background(), service, proto, name)
	 448  }
	 449  
	 450  // LookupSRV tries to resolve an SRV query of the given service,
	 451  // protocol, and domain name. The proto is "tcp" or "udp".
	 452  // The returned records are sorted by priority and randomized
	 453  // by weight within a priority.
	 454  //
	 455  // LookupSRV constructs the DNS name to look up following RFC 2782.
	 456  // That is, it looks up _service._proto.name. To accommodate services
	 457  // publishing SRV records under non-standard names, if both service
	 458  // and proto are empty strings, LookupSRV looks up name directly.
	 459  //
	 460  // The returned service names are validated to be properly
	 461  // formatted presentation-format domain names. If the response contains
	 462  // invalid names, those records are filtered out and an error
	 463  // will be returned alongside the the remaining results, if any.
	 464  func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
	 465  	cname, addrs, err := r.lookupSRV(ctx, service, proto, name)
	 466  	if err != nil {
	 467  		return "", nil, err
	 468  	}
	 469  	if cname != "" && !isDomainName(cname) {
	 470  		return "", nil, &DNSError{Err: "SRV header name is invalid", Name: name}
	 471  	}
	 472  	filteredAddrs := make([]*SRV, 0, len(addrs))
	 473  	for _, addr := range addrs {
	 474  		if addr == nil {
	 475  			continue
	 476  		}
	 477  		if !isDomainName(addr.Target) {
	 478  			continue
	 479  		}
	 480  		filteredAddrs = append(filteredAddrs, addr)
	 481  	}
	 482  	if len(addrs) != len(filteredAddrs) {
	 483  		return cname, filteredAddrs, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
	 484  	}
	 485  	return cname, filteredAddrs, nil
	 486  }
	 487  
	 488  // LookupMX returns the DNS MX records for the given domain name sorted by preference.
	 489  //
	 490  // The returned mail server names are validated to be properly
	 491  // formatted presentation-format domain names. If the response contains
	 492  // invalid names, those records are filtered out and an error
	 493  // will be returned alongside the the remaining results, if any.
	 494  //
	 495  // LookupMX uses context.Background internally; to specify the context, use
	 496  // Resolver.LookupMX.
	 497  func LookupMX(name string) ([]*MX, error) {
	 498  	return DefaultResolver.LookupMX(context.Background(), name)
	 499  }
	 500  
	 501  // LookupMX returns the DNS MX records for the given domain name sorted by preference.
	 502  //
	 503  // The returned mail server names are validated to be properly
	 504  // formatted presentation-format domain names. If the response contains
	 505  // invalid names, those records are filtered out and an error
	 506  // will be returned alongside the the remaining results, if any.
	 507  func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
	 508  	records, err := r.lookupMX(ctx, name)
	 509  	if err != nil {
	 510  		return nil, err
	 511  	}
	 512  	filteredMX := make([]*MX, 0, len(records))
	 513  	for _, mx := range records {
	 514  		if mx == nil {
	 515  			continue
	 516  		}
	 517  		// Bypass the hostname validity check for targets which contain only a dot,
	 518  		// as this is used to represent a 'Null' MX record.
	 519  		if mx.Host != "." && !isDomainName(mx.Host) {
	 520  			continue
	 521  		}
	 522  		filteredMX = append(filteredMX, mx)
	 523  	}
	 524  	if len(records) != len(filteredMX) {
	 525  		return filteredMX, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
	 526  	}
	 527  	return filteredMX, nil
	 528  }
	 529  
	 530  // LookupNS returns the DNS NS records for the given domain name.
	 531  //
	 532  // The returned name server names are validated to be properly
	 533  // formatted presentation-format domain names. If the response contains
	 534  // invalid names, those records are filtered out and an error
	 535  // will be returned alongside the the remaining results, if any.
	 536  //
	 537  // LookupNS uses context.Background internally; to specify the context, use
	 538  // Resolver.LookupNS.
	 539  func LookupNS(name string) ([]*NS, error) {
	 540  	return DefaultResolver.LookupNS(context.Background(), name)
	 541  }
	 542  
	 543  // LookupNS returns the DNS NS records for the given domain name.
	 544  //
	 545  // The returned name server names are validated to be properly
	 546  // formatted presentation-format domain names. If the response contains
	 547  // invalid names, those records are filtered out and an error
	 548  // will be returned alongside the the remaining results, if any.
	 549  func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) {
	 550  	records, err := r.lookupNS(ctx, name)
	 551  	if err != nil {
	 552  		return nil, err
	 553  	}
	 554  	filteredNS := make([]*NS, 0, len(records))
	 555  	for _, ns := range records {
	 556  		if ns == nil {
	 557  			continue
	 558  		}
	 559  		if !isDomainName(ns.Host) {
	 560  			continue
	 561  		}
	 562  		filteredNS = append(filteredNS, ns)
	 563  	}
	 564  	if len(records) != len(filteredNS) {
	 565  		return filteredNS, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
	 566  	}
	 567  	return filteredNS, nil
	 568  }
	 569  
	 570  // LookupTXT returns the DNS TXT records for the given domain name.
	 571  //
	 572  // LookupTXT uses context.Background internally; to specify the context, use
	 573  // Resolver.LookupTXT.
	 574  func LookupTXT(name string) ([]string, error) {
	 575  	return DefaultResolver.lookupTXT(context.Background(), name)
	 576  }
	 577  
	 578  // LookupTXT returns the DNS TXT records for the given domain name.
	 579  func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error) {
	 580  	return r.lookupTXT(ctx, name)
	 581  }
	 582  
	 583  // LookupAddr performs a reverse lookup for the given address, returning a list
	 584  // of names mapping to that address.
	 585  //
	 586  // The returned names are validated to be properly formatted presentation-format
	 587  // domain names. If the response contains invalid names, those records are filtered
	 588  // out and an error will be returned alongside the the remaining results, if any.
	 589  //
	 590  // When using the host C library resolver, at most one result will be
	 591  // returned. To bypass the host resolver, use a custom Resolver.
	 592  //
	 593  // LookupAddr uses context.Background internally; to specify the context, use
	 594  // Resolver.LookupAddr.
	 595  func LookupAddr(addr string) (names []string, err error) {
	 596  	return DefaultResolver.LookupAddr(context.Background(), addr)
	 597  }
	 598  
	 599  // LookupAddr performs a reverse lookup for the given address, returning a list
	 600  // of names mapping to that address.
	 601  //
	 602  // The returned names are validated to be properly formatted presentation-format
	 603  // domain names. If the response contains invalid names, those records are filtered
	 604  // out and an error will be returned alongside the the remaining results, if any.
	 605  func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) {
	 606  	names, err := r.lookupAddr(ctx, addr)
	 607  	if err != nil {
	 608  		return nil, err
	 609  	}
	 610  	filteredNames := make([]string, 0, len(names))
	 611  	for _, name := range names {
	 612  		if isDomainName(name) {
	 613  			filteredNames = append(filteredNames, name)
	 614  		}
	 615  	}
	 616  	if len(names) != len(filteredNames) {
	 617  		return filteredNames, &DNSError{Err: errMalformedDNSRecordsDetail, Name: addr}
	 618  	}
	 619  	return filteredNames, nil
	 620  }
	 621  
	 622  // errMalformedDNSRecordsDetail is the DNSError detail which is returned when a Resolver.Lookup...
	 623  // method recieves DNS records which contain invalid DNS names. This may be returned alongside
	 624  // results which have had the malformed records filtered out.
	 625  var errMalformedDNSRecordsDetail = "DNS response contained records which contain invalid names"
	 626  

View as plain text