1
0
mirror of https://github.com/golang/go synced 2024-10-04 15:11:20 -06:00
go/src/net/lookup_unix.go
Russ Cox 773b9b8452 net: respect go vs cgo resolver selection in all lookup routines
This is especially important for LookupAddr, which used to be pure Go
(lightweight, one goroutine per call) and without this CL is now
unconditionally cgo (heavy, one thread per call).

Fixes #12190.

Change-Id: I43436a942bc1838b024225893e156f280a1e80cf
Reviewed-on: https://go-review.googlesource.com/13698
Reviewed-by: Rob Pike <r@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-08-19 04:20:37 +00:00

160 lines
3.8 KiB
Go

// 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.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
package net
import "sync"
var onceReadProtocols sync.Once
// readProtocols loads contents of /etc/protocols into protocols map
// for quick access.
func readProtocols() {
if file, err := open("/etc/protocols"); err == nil {
for line, ok := file.readLine(); ok; line, ok = file.readLine() {
// tcp 6 TCP # transmission control protocol
if i := byteIndex(line, '#'); i >= 0 {
line = line[0:i]
}
f := getFields(line)
if len(f) < 2 {
continue
}
if proto, _, ok := dtoi(f[1], 0); ok {
if _, ok := protocols[f[0]]; !ok {
protocols[f[0]] = proto
}
for _, alias := range f[2:] {
if _, ok := protocols[alias]; !ok {
protocols[alias] = proto
}
}
}
}
file.close()
}
}
// lookupProtocol looks up IP protocol name in /etc/protocols and
// returns correspondent protocol number.
func lookupProtocol(name string) (int, error) {
onceReadProtocols.Do(readProtocols)
proto, found := protocols[name]
if !found {
return 0, &AddrError{Err: "unknown IP protocol specified", Addr: name}
}
return proto, nil
}
func lookupHost(host string) (addrs []string, err error) {
order := systemConf().hostLookupOrder(host)
if order == hostLookupCgo {
if addrs, err, ok := cgoLookupHost(host); ok {
return addrs, err
}
// cgo not available (or netgo); fall back to Go's DNS resolver
order = hostLookupFilesDNS
}
return goLookupHostOrder(host, order)
}
func lookupIP(host string) (addrs []IPAddr, err error) {
order := systemConf().hostLookupOrder(host)
if order == hostLookupCgo {
if addrs, err, ok := cgoLookupIP(host); ok {
return addrs, err
}
// cgo not available (or netgo); fall back to Go's DNS resolver
order = hostLookupFilesDNS
}
return goLookupIPOrder(host, order)
}
func lookupPort(network, service string) (int, error) {
if systemConf().canUseCgo() {
if port, err, ok := cgoLookupPort(network, service); ok {
return port, err
}
}
return goLookupPort(network, service)
}
func lookupCNAME(name string) (string, error) {
if systemConf().canUseCgo() {
if cname, err, ok := cgoLookupCNAME(name); ok {
return cname, err
}
}
return goLookupCNAME(name)
}
func lookupSRV(service, proto, name string) (string, []*SRV, error) {
var target string
if service == "" && proto == "" {
target = name
} else {
target = "_" + service + "._" + proto + "." + name
}
cname, rrs, err := lookup(target, dnsTypeSRV)
if err != nil {
return "", nil, err
}
srvs := make([]*SRV, len(rrs))
for i, rr := range rrs {
rr := rr.(*dnsRR_SRV)
srvs[i] = &SRV{Target: rr.Target, Port: rr.Port, Priority: rr.Priority, Weight: rr.Weight}
}
byPriorityWeight(srvs).sort()
return cname, srvs, nil
}
func lookupMX(name string) ([]*MX, error) {
_, rrs, err := lookup(name, dnsTypeMX)
if err != nil {
return nil, err
}
mxs := make([]*MX, len(rrs))
for i, rr := range rrs {
rr := rr.(*dnsRR_MX)
mxs[i] = &MX{Host: rr.Mx, Pref: rr.Pref}
}
byPref(mxs).sort()
return mxs, nil
}
func lookupNS(name string) ([]*NS, error) {
_, rrs, err := lookup(name, dnsTypeNS)
if err != nil {
return nil, err
}
nss := make([]*NS, len(rrs))
for i, rr := range rrs {
nss[i] = &NS{Host: rr.(*dnsRR_NS).Ns}
}
return nss, nil
}
func lookupTXT(name string) ([]string, error) {
_, rrs, err := lookup(name, dnsTypeTXT)
if err != nil {
return nil, err
}
txts := make([]string, len(rrs))
for i, rr := range rrs {
txts[i] = rr.(*dnsRR_TXT).Txt
}
return txts, nil
}
func lookupAddr(addr string) ([]string, error) {
if systemConf().canUseCgo() {
if ptrs, err, ok := cgoLookupPTR(addr); ok {
return ptrs, err
}
}
return goLookupPTR(addr)
}