1 // Copyright 2011 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.
5 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
14 var onceReadProtocols sync
.Once
16 // readProtocols loads contents of /etc/protocols into protocols map
18 func readProtocols() {
19 file
, err
:= open("/etc/protocols")
25 for line
, ok
:= file
.readLine(); ok
; line
, ok
= file
.readLine() {
26 // tcp 6 TCP # transmission control protocol
27 if i
:= byteIndex(line
, '#'); i
>= 0 {
34 if proto
, _
, ok
:= dtoi(f
[1]); ok
{
35 if _
, ok
:= protocols
[f
[0]]; !ok
{
36 protocols
[f
[0]] = proto
38 for _
, alias
:= range f
[2:] {
39 if _
, ok
:= protocols
[alias
]; !ok
{
40 protocols
[alias
] = proto
47 // lookupProtocol looks up IP protocol name in /etc/protocols and
48 // returns correspondent protocol number.
49 func lookupProtocol(_ context
.Context
, name
string) (int, error
) {
50 onceReadProtocols
.Do(readProtocols
)
51 return lookupProtocolMap(name
)
54 func (r
*Resolver
) dial(ctx context
.Context
, network
, server
string) (dnsConn
, error
) {
55 // Calling Dial here is scary -- we have to be sure not to
56 // dial a name that will require a DNS lookup, or Dial will
57 // call back here to translate it. The DNS config parser has
58 // already checked that all the cfg.servers are IP
59 // addresses, which Dial will use without a DNS lookup.
63 c
, err
= r
.Dial(ctx
, network
, server
)
66 c
, err
= d
.DialContext(ctx
, network
, server
)
69 return nil, mapErr(err
)
71 if _
, ok
:= c
.(PacketConn
); ok
{
72 return &dnsPacketConn
{c
}, nil
74 return &dnsStreamConn
{c
}, nil
77 func (r
*Resolver
) lookupHost(ctx context
.Context
, host
string) (addrs
[]string, err error
) {
78 order
:= systemConf().hostLookupOrder(host
)
79 if !r
.PreferGo
&& order
== hostLookupCgo
{
80 if addrs
, err
, ok
:= cgoLookupHost(ctx
, host
); ok
{
83 // cgo not available (or netgo); fall back to Go's DNS resolver
84 order
= hostLookupFilesDNS
86 return r
.goLookupHostOrder(ctx
, host
, order
)
89 func (r
*Resolver
) lookupIP(ctx context
.Context
, host
string) (addrs
[]IPAddr
, err error
) {
91 return r
.goLookupIP(ctx
, host
)
93 order
:= systemConf().hostLookupOrder(host
)
94 if order
== hostLookupCgo
{
95 if addrs
, err
, ok
:= cgoLookupIP(ctx
, host
); ok
{
98 // cgo not available (or netgo); fall back to Go's DNS resolver
99 order
= hostLookupFilesDNS
101 addrs
, _
, err
= r
.goLookupIPCNAMEOrder(ctx
, host
, order
)
105 func (r
*Resolver
) lookupPort(ctx context
.Context
, network
, service
string) (int, error
) {
106 if !r
.PreferGo
&& systemConf().canUseCgo() {
107 if port
, err
, ok
:= cgoLookupPort(ctx
, network
, service
); ok
{
109 // Issue 18213: if cgo fails, first check to see whether we
110 // have the answer baked-in to the net package.
111 if port
, err
:= goLookupPort(network
, service
); err
== nil {
118 return goLookupPort(network
, service
)
121 func (r
*Resolver
) lookupCNAME(ctx context
.Context
, name
string) (string, error
) {
122 if !r
.PreferGo
&& systemConf().canUseCgo() {
123 if cname
, err
, ok
:= cgoLookupCNAME(ctx
, name
); ok
{
127 return r
.goLookupCNAME(ctx
, name
)
130 func (r
*Resolver
) lookupSRV(ctx context
.Context
, service
, proto
, name
string) (string, []*SRV
, error
) {
132 if service
== "" && proto
== "" {
135 target
= "_" + service
+ "._" + proto
+ "." + name
137 cname
, rrs
, err
:= r
.lookup(ctx
, target
, dnsTypeSRV
)
141 srvs
:= make([]*SRV
, len(rrs
))
142 for i
, rr
:= range rrs
{
143 rr
:= rr
.(*dnsRR_SRV
)
144 srvs
[i
] = &SRV
{Target
: rr
.Target
, Port
: rr
.Port
, Priority
: rr
.Priority
, Weight
: rr
.Weight
}
146 byPriorityWeight(srvs
).sort()
147 return cname
, srvs
, nil
150 func (r
*Resolver
) lookupMX(ctx context
.Context
, name
string) ([]*MX
, error
) {
151 _
, rrs
, err
:= r
.lookup(ctx
, name
, dnsTypeMX
)
155 mxs
:= make([]*MX
, len(rrs
))
156 for i
, rr
:= range rrs
{
158 mxs
[i
] = &MX
{Host
: rr
.Mx
, Pref
: rr
.Pref
}
164 func (r
*Resolver
) lookupNS(ctx context
.Context
, name
string) ([]*NS
, error
) {
165 _
, rrs
, err
:= r
.lookup(ctx
, name
, dnsTypeNS
)
169 nss
:= make([]*NS
, len(rrs
))
170 for i
, rr
:= range rrs
{
171 nss
[i
] = &NS
{Host
: rr
.(*dnsRR_NS
).Ns
}
176 func (r
*Resolver
) lookupTXT(ctx context
.Context
, name
string) ([]string, error
) {
177 _
, rrs
, err
:= r
.lookup(ctx
, name
, dnsTypeTXT
)
181 txts
:= make([]string, len(rrs
))
182 for i
, rr
:= range rrs
{
183 txts
[i
] = rr
.(*dnsRR_TXT
).Txt
188 func (r
*Resolver
) lookupAddr(ctx context
.Context
, addr
string) ([]string, error
) {
189 if !r
.PreferGo
&& systemConf().canUseCgo() {
190 if ptrs
, err
, ok
:= cgoLookupPTR(ctx
, addr
); ok
{
194 return r
.goLookupPTR(ctx
, addr
)