// Copyright 2015 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 !jspackage netimport ()// conf represents a system's network configuration.type conf struct {// forceCgoLookupHost forces CGO to always be used, if available. forceCgoLookupHost bool netGo bool// go DNS resolution forced netCgo bool// non-go DNS resolution forced (cgo, or win32)// machine has an /etc/mdns.allow file hasMDNSAllow bool goos string// the runtime.GOOS, to ease testing dnsDebugLevel int}var ( confOnce sync.Once// guards init of confVal via initConfVal confVal = &conf{goos: runtime.GOOS})// systemConf returns the machine's network configuration.func systemConf() *conf {confOnce.Do(initConfVal)returnconfVal}func initConfVal() { , := goDebugNetDNS()confVal.dnsDebugLevel = confVal.netGo = netGo || == "go"confVal.netCgo = netCgo || == "cgo"if !confVal.netGo && !confVal.netCgo && (runtime.GOOS == "windows" || runtime.GOOS == "plan9") {// Neither of these platforms actually use cgo. // // The meaning of "cgo" mode in the net package is // really "the native OS way", which for libc meant // cgo on the original platforms that motivated // PreferGo support before Windows and Plan9 got support, // at which time the GODEBUG=netdns=go and GODEBUG=netdns=cgo // names were already kinda locked in.confVal.netCgo = true }ifconfVal.dnsDebugLevel > 0 {deferfunc() {ifconfVal.dnsDebugLevel > 1 {println("go package net: confVal.netCgo =", confVal.netCgo, " netGo =", confVal.netGo) }switch {caseconfVal.netGo:ifnetGo {println("go package net: built with netgo build tag; using Go's DNS resolver") } else {println("go package net: GODEBUG setting forcing use of Go's resolver") }caseconfVal.forceCgoLookupHost:println("go package net: using cgo DNS resolver")default:println("go package net: dynamic selection of DNS resolver") } }() }// Darwin pops up annoying dialog boxes if programs try to do // their own DNS requests. So always use cgo instead, which // avoids that.ifruntime.GOOS == "darwin" || runtime.GOOS == "ios" {confVal.forceCgoLookupHost = truereturn }ifruntime.GOOS == "windows" || runtime.GOOS == "plan9" {return }// If any environment-specified resolver options are specified, // force cgo. Note that LOCALDOMAIN can change behavior merely // by being specified with the empty string. , := syscall.Getenv("LOCALDOMAIN")ifos.Getenv("RES_OPTIONS") != "" ||os.Getenv("HOSTALIASES") != "" ||confVal.netCgo || {confVal.forceCgoLookupHost = truereturn }// OpenBSD apparently lets you override the location of resolv.conf // with ASR_CONFIG. If we notice that, defer to libc.ifruntime.GOOS == "openbsd" && os.Getenv("ASR_CONFIG") != "" {confVal.forceCgoLookupHost = truereturn }if , := os.Stat("/etc/mdns.allow"); == nil {confVal.hasMDNSAllow = true }}// canUseCgo reports whether calling cgo functions is allowed// for non-hostname lookups.func ( *conf) () bool { , := .hostLookupOrder(nil, "")return == hostLookupCgo}// hostLookupOrder determines which strategy to use to resolve hostname.// The provided Resolver is optional. nil means to not consider its options.// It also returns dnsConfig when it was used to determine the lookup order.func ( *conf) ( *Resolver, string) ( hostLookupOrder, *dnsConfig) {if .dnsDebugLevel > 1 {deferfunc() {print("go package net: hostLookupOrder(", , ") = ", .String(), "\n") }() } := hostLookupCgoif .netGo || .preferGo() {switch .goos {case"windows":// TODO(bradfitz): implement files-based // lookup on Windows too? I guess /etc/hosts // kinda exists on Windows. But for now, only // do DNS. = hostLookupDNSdefault: = hostLookupFilesDNS } }if .forceCgoLookupHost || .goos == "android" || .goos == "windows" || .goos == "plan9" {return , nil }ifbytealg.IndexByteString(, '\\') != -1 || bytealg.IndexByteString(, '%') != -1 {// Don't deal with special form hostnames with backslashes // or '%'.return , nil } := getSystemDNSConfig()if .err != nil && !os.IsNotExist(.err) && !os.IsPermission(.err) {// If we can't read the resolv.conf file, assume it // had something important in it and defer to cgo. // libc's resolver might then fail too, but at least // it wasn't our fault.return , }if .unknownOpt {return , }// OpenBSD is unique and doesn't use nsswitch.conf. // It also doesn't support mDNS.if .goos == "openbsd" {// OpenBSD's resolv.conf manpage says that a non-existent // resolv.conf means "lookup" defaults to only "files", // without DNS lookups.ifos.IsNotExist(.err) {returnhostLookupFiles, } := .lookupiflen() == 0 {// https://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man5/resolv.conf.5 // "If the lookup keyword is not used in the // system's resolv.conf file then the assumed // order is 'bind file'"returnhostLookupDNSFiles, }iflen() < 1 || len() > 2 {return , }switch [0] {case"bind":iflen() == 2 {if [1] == "file" {returnhostLookupDNSFiles, }return , }returnhostLookupDNS, case"file":iflen() == 2 {if [1] == "bind" {returnhostLookupFilesDNS, }return , }returnhostLookupFiles, default:return , } }// Canonicalize the hostname by removing any trailing dot.ifstringsHasSuffix(, ".") { = [:len()-1] }ifstringsHasSuffixFold(, ".local") {// Per RFC 6762, the ".local" TLD is special. And // because Go's native resolver doesn't do mDNS or // similar local resolution mechanisms, assume that // libc might (via Avahi, etc) and use cgo.return , } := getSystemNSS() := .sources["hosts"]// If /etc/nsswitch.conf doesn't exist or doesn't specify any // sources for "hosts", assume Go's DNS will work fine.ifos.IsNotExist(.err) || (.err == nil && len() == 0) {if .goos == "solaris" {// illumos defaults to "nis [NOTFOUND=return] files"return , }returnhostLookupFilesDNS, }if .err != nil {// We failed to parse or open nsswitch.conf, so // conservatively assume we should use cgo if it's // available.return , }var , , boolvarstringfor , := range {if .source == "myhostname" {ifisLocalhost() || isGateway() || isOutbound() {return , } , := getHostname()if != nil || stringsEqualFold(, ) {return , }continue }if .source == "files" || .source == "dns" {if !.standardCriteria() {return , // non-standard; let libc deal with it. }if .source == "files" { = true } elseif .source == "dns" { = true }if == "" { = .source }continue }ifstringsHasPrefix(.source, "mdns") {// e.g. "mdns4", "mdns4_minimal" // We already returned true before if it was *.local. // libc wouldn't have found a hit on this anyway. = truecontinue }// Some source we don't know how to deal with.return , }// We don't parse mdns.allow files. They're rare. If one // exists, it might list other TLDs (besides .local) or even // '*', so just let libc deal with it.if && .hasMDNSAllow {return , }// Cases where Go can handle it without cgo and C thread // overhead.switch {case && :if == "files" {returnhostLookupFilesDNS, } else {returnhostLookupDNSFiles, }case :returnhostLookupFiles, case :returnhostLookupDNS, }// Something weird. Let libc deal with it.return , }var netdns = godebug.New("netdns")// goDebugNetDNS parses the value of the GODEBUG "netdns" value.// The netdns value can be of the form://// 1 // debug level 1// 2 // debug level 2// cgo // use cgo for DNS lookups// go // use go for DNS lookups// cgo+1 // use cgo for DNS lookups + debug level 1// 1+cgo // same// cgo+2 // same, but debug level 2//// etc.func goDebugNetDNS() ( string, int) { := netdns.Value() := func( string) {if == "" {return }if'0' <= [0] && [0] <= '9' { , _, _ = dtoi() } else { = } }if := bytealg.IndexByteString(, '+'); != -1 { ([:]) ([+1:])return } ()return}// isLocalhost reports whether h should be considered a "localhost"// name for the myhostname NSS module.func isLocalhost( string) bool {returnstringsEqualFold(, "localhost") || stringsEqualFold(, "localhost.localdomain") || stringsHasSuffixFold(, ".localhost") || stringsHasSuffixFold(, ".localhost.localdomain")}// isGateway reports whether h should be considered a "gateway"// name for the myhostname NSS module.func isGateway( string) bool {returnstringsEqualFold(, "_gateway")}// isOutbound reports whether h should be considered a "outbound"// name for the myhostname NSS module.func isOutbound( string) bool {returnstringsEqualFold(, "_outbound")}
The pages are generated with Goldsv0.5.5. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.