// Copyright 2011 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.

//go:build unix

package net

import (
	
	
	
	
)

var onceReadProtocols sync.Once

// readProtocols loads contents of /etc/protocols into protocols map
// for quick access.
func readProtocols() {
	,  := open("/etc/protocols")
	if  != nil {
		return
	}
	defer .close()

	for ,  := .readLine(); ; ,  = .readLine() {
		// tcp    6   TCP    # transmission control protocol
		if  := bytealg.IndexByteString(, '#');  >= 0 {
			 = [0:]
		}
		 := getFields()
		if len() < 2 {
			continue
		}
		if , ,  := dtoi([1]);  {
			if ,  := protocols[[0]]; ! {
				protocols[[0]] = 
			}
			for ,  := range [2:] {
				if ,  := protocols[]; ! {
					protocols[] = 
				}
			}
		}
	}
}

// lookupProtocol looks up IP protocol name in /etc/protocols and
// returns correspondent protocol number.
func lookupProtocol( context.Context,  string) (int, error) {
	onceReadProtocols.Do(readProtocols)
	return lookupProtocolMap()
}

func ( *Resolver) ( context.Context,  string) ( []string,  error) {
	 := systemConf().hostLookupOrder(, )
	if !.preferGo() &&  == hostLookupCgo {
		if , ,  := cgoLookupHost(, );  {
			return , 
		}
		// cgo not available (or netgo); fall back to Go's DNS resolver
		 = hostLookupFilesDNS
	}
	return .goLookupHostOrder(, , )
}

func ( *Resolver) ( context.Context, ,  string) ( []IPAddr,  error) {
	if .preferGo() {
		return .goLookupIP(, , )
	}
	 := systemConf().hostLookupOrder(, )
	if  == hostLookupCgo {
		if , ,  := cgoLookupIP(, , );  {
			return , 
		}
		// cgo not available (or netgo); fall back to Go's DNS resolver
		 = hostLookupFilesDNS
	}
	, ,  := .goLookupIPCNAMEOrder(, , , )
	return , 
}

func ( *Resolver) ( context.Context, ,  string) (int, error) {
	if !.preferGo() && systemConf().canUseCgo() {
		if , ,  := cgoLookupPort(, , );  {
			if  != nil {
				// Issue 18213: if cgo fails, first check to see whether we
				// have the answer baked-in to the net package.
				if ,  := goLookupPort(, );  == nil {
					return , nil
				}
			}
			return , 
		}
	}
	return goLookupPort(, )
}

func ( *Resolver) ( context.Context,  string) (string, error) {
	if !.preferGo() && systemConf().canUseCgo() {
		if , ,  := cgoLookupCNAME(, );  {
			return , 
		}
	}
	return .goLookupCNAME(, )
}

func ( *Resolver) ( context.Context, , ,  string) (string, []*SRV, error) {
	return .goLookupSRV(, , , )
}

func ( *Resolver) ( context.Context,  string) ([]*MX, error) {
	return .goLookupMX(, )
}

func ( *Resolver) ( context.Context,  string) ([]*NS, error) {
	return .goLookupNS(, )
}

func ( *Resolver) ( context.Context,  string) ([]string, error) {
	return .goLookupTXT(, )
}

func ( *Resolver) ( context.Context,  string) ([]string, error) {
	if !.preferGo() && systemConf().canUseCgo() {
		if , ,  := cgoLookupPTR(, );  {
			return , 
		}
	}
	return .goLookupPTR(, )
}

// concurrentThreadsLimit returns the number of threads we permit to
// run concurrently doing DNS lookups via cgo. A DNS lookup may use a
// file descriptor so we limit this to less than the number of
// permitted open files. On some systems, notably Darwin, if
// getaddrinfo is unable to open a file descriptor it simply returns
// EAI_NONAME rather than a useful error. Limiting the number of
// concurrent getaddrinfo calls to less than the permitted number of
// file descriptors makes that error less likely. We don't bother to
// apply the same limit to DNS lookups run directly from Go, because
// there we will return a meaningful "too many open files" error.
func concurrentThreadsLimit() int {
	var  syscall.Rlimit
	if  := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &);  != nil {
		return 500
	}
	 := int(.Cur)
	if  > 500 {
		 = 500
	} else if  > 30 {
		 -= 30
	}
	return 
}