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.
12 func query(filename
, query
string, bufSize
int) (res
[]string, err error
) {
13 file
, err
:= os
.OpenFile(filename
, os
.O_RDWR
, 0)
19 _
, err
= file
.Seek(0, 0)
23 _
, err
= file
.WriteString(query
)
27 _
, err
= file
.Seek(0, 0)
31 buf
:= make([]byte, bufSize
)
33 n
, _
:= file
.Read(buf
)
37 res
= append(res
, string(buf
[:n
]))
42 func queryCS(net
, host
, service
string) (res
[]string, err error
) {
52 return query(netdir
+"/cs", net
+"!"+host
+"!"+service
, 128)
55 func queryCS1(net
string, ip IP
, port
int) (clone
, dest
string, err error
) {
57 if len(ip
) != 0 && !ip
.IsUnspecified() {
60 lines
, err
:= queryCS(net
, ips
, itoa(port
))
64 f
:= getFields(lines
[0])
66 return "", "", errors
.New("bad response from ndb/cs")
68 clone
, dest
= f
[0], f
[1]
72 func queryDNS(addr
string, typ
string) (res
[]string, err error
) {
73 return query(netdir
+"/dns", addr
+" "+typ
, 1024)
76 // toLower returns a lower-case version of in. Restricting us to
77 // ASCII is sufficient to handle the IP protocol names and allow
78 // us to not depend on the strings and unicode packages.
79 func toLower(in
string) string {
80 for _
, c
:= range in
{
81 if 'A' <= c
&& c
<= 'Z' {
82 // Has upper case; need to fix.
84 for i
:= 0; i
< len(in
); i
++ {
86 if 'A' <= c
&& c
<= 'Z' {
97 // lookupProtocol looks up IP protocol name and returns
98 // the corresponding protocol number.
99 func lookupProtocol(name
string) (proto
int, err error
) {
100 lines
, err
:= query(netdir
+"/cs", "!protocol="+toLower(name
), 128)
104 unknownProtoError
:= errors
.New("unknown IP protocol specified: " + name
)
106 return 0, unknownProtoError
108 f
:= getFields(lines
[0])
110 return 0, unknownProtoError
113 if n
, _
, ok
:= dtoi(s
, byteIndex(s
, '=')+1); ok
{
116 return 0, unknownProtoError
119 func lookupHost(host
string) (addrs
[]string, err error
) {
120 // Use netdir/cs instead of netdir/dns because cs knows about
121 // host names in local network (e.g. from /lib/ndb/local)
122 lines
, err
:= queryCS("net", host
, "1")
127 for _
, line
:= range lines
{
133 if i
:= byteIndex(addr
, '!'); i
>= 0 {
134 addr
= addr
[:i
] // remove port
136 if ParseIP(addr
) == nil {
139 // only return unique addresses
140 for _
, a
:= range addrs
{
145 addrs
= append(addrs
, addr
)
150 func lookupIP(host
string) (ips
[]IP
, err error
) {
151 addrs
, err
:= LookupHost(host
)
155 for _
, addr
:= range addrs
{
156 if ip
:= ParseIP(addr
); ip
!= nil {
157 ips
= append(ips
, ip
)
163 func lookupPort(network
, service
string) (port
int, err error
) {
170 lines
, err
:= queryCS(network
, "127.0.0.1", service
)
174 unknownPortError
:= &AddrError
{"unknown port", network
+ "/" + service
}
176 return 0, unknownPortError
178 f
:= getFields(lines
[0])
180 return 0, unknownPortError
183 if i
:= byteIndex(s
, '!'); i
>= 0 {
184 s
= s
[i
+1:] // remove address
186 if n
, _
, ok
:= dtoi(s
, 0); ok
{
189 return 0, unknownPortError
192 func lookupCNAME(name
string) (cname
string, err error
) {
193 lines
, err
:= queryDNS(name
, "cname")
198 if f
:= getFields(lines
[0]); len(f
) >= 3 {
199 return f
[2] + ".", nil
202 return "", errors
.New("bad response from ndb/dns")
205 func lookupSRV(service
, proto
, name
string) (cname
string, addrs
[]*SRV
, err error
) {
207 if service
== "" && proto
== "" {
210 target
= "_" + service
+ "._" + proto
+ "." + name
212 lines
, err
:= queryDNS(target
, "srv")
216 for _
, line
:= range lines
{
221 port
, _
, portOk
:= dtoi(f
[4], 0)
222 priority
, _
, priorityOk
:= dtoi(f
[3], 0)
223 weight
, _
, weightOk
:= dtoi(f
[2], 0)
224 if !(portOk
&& priorityOk
&& weightOk
) {
227 addrs
= append(addrs
, &SRV
{f
[5], uint16(port
), uint16(priority
), uint16(weight
)})
230 byPriorityWeight(addrs
).sort()
234 func lookupMX(name
string) (mx
[]*MX
, err error
) {
235 lines
, err
:= queryDNS(name
, "mx")
239 for _
, line
:= range lines
{
244 if pref
, _
, ok
:= dtoi(f
[2], 0); ok
{
245 mx
= append(mx
, &MX
{f
[3], uint16(pref
)})
252 func lookupNS(name
string) (ns
[]*NS
, err error
) {
253 lines
, err
:= queryDNS(name
, "ns")
257 for _
, line
:= range lines
{
262 ns
= append(ns
, &NS
{f
[2]})
267 func lookupTXT(name
string) (txt
[]string, err error
) {
268 lines
, err
:= queryDNS(name
, "txt")
272 for _
, line
:= range lines
{
273 if i
:= byteIndex(line
, '\t'); i
>= 0 {
274 txt
= append(txt
, line
[i
+1:])
280 func lookupAddr(addr
string) (name
[]string, err error
) {
281 arpa
, err
:= reverseaddr(addr
)
285 lines
, err
:= queryDNS(arpa
, "ptr")
289 for _
, line
:= range lines
{
294 name
= append(name
, f
[2])