1 // Copyright 2009 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.
15 lookupPort
= oldLookupPort
16 lookupIP
= oldLookupIP
19 func getprotobyname(name
string) (proto
int, err error
) {
20 p
, err
:= syscall
.GetProtoByName(name
)
22 return 0, os
.NewSyscallError("GetProtoByName", err
)
24 return int(p
.Proto
), nil
27 // lookupProtocol looks up IP protocol name and returns correspondent protocol number.
28 func lookupProtocol(name
string) (proto
int, err error
) {
29 // GetProtoByName return value is stored in thread local storage.
30 // Start new os thread before the call to prevent races.
35 ch
:= make(chan result
)
37 runtime
.LockOSThread()
38 defer runtime
.UnlockOSThread()
39 proto
, err
:= getprotobyname(name
)
40 ch
<- result
{proto
: proto
, err
: err
}
46 func lookupHost(name
string) (addrs
[]string, err error
) {
47 ips
, err
:= LookupIP(name
)
51 addrs
= make([]string, 0, len(ips
))
52 for _
, ip
:= range ips
{
53 addrs
= append(addrs
, ip
.String())
58 func gethostbyname(name
string) (addrs
[]IP
, err error
) {
59 h
, err
:= syscall
.GetHostByName(name
)
61 return nil, os
.NewSyscallError("GetHostByName", err
)
66 addrs
= make([]IP
, 100) // plenty of room to grow
67 for p
:= (*[100](*[4]byte))(unsafe
.Pointer(h
.AddrList
)); i
< cap(addrs
) && p
[i
] != nil; i
++ {
68 addrs
[i
] = IPv4(p
[i
][0], p
[i
][1], p
[i
][2], p
[i
][3])
71 default: // TODO(vcc): Implement non IPv4 address lookups.
72 return nil, os
.NewSyscallError("LookupIP", syscall
.EWINDOWS
)
77 func oldLookupIP(name
string) (addrs
[]IP
, err error
) {
78 // GetHostByName return value is stored in thread local storage.
79 // Start new os thread before the call to prevent races.
84 ch
:= make(chan result
)
86 runtime
.LockOSThread()
87 defer runtime
.UnlockOSThread()
88 addrs
, err
:= gethostbyname(name
)
89 ch
<- result
{addrs
: addrs
, err
: err
}
95 func newLookupIP(name
string) (addrs
[]IP
, err error
) {
96 hints
:= syscall
.AddrinfoW
{
97 Family
: syscall
.AF_UNSPEC
,
98 Socktype
: syscall
.SOCK_STREAM
,
99 Protocol
: syscall
.IPPROTO_IP
,
101 var result
*syscall
.AddrinfoW
102 e
:= syscall
.GetAddrInfoW(syscall
.StringToUTF16Ptr(name
), nil, &hints
, &result
)
104 return nil, os
.NewSyscallError("GetAddrInfoW", e
)
106 defer syscall
.FreeAddrInfoW(result
)
107 addrs
= make([]IP
, 0, 5)
108 for ; result
!= nil; result
= result
.Next
{
109 addr
:= unsafe
.Pointer(result
.Addr
)
110 switch result
.Family
{
111 case syscall
.AF_INET
:
112 a
:= (*syscall
.RawSockaddrInet4
)(addr
).Addr
113 addrs
= append(addrs
, IPv4(a
[0], a
[1], a
[2], a
[3]))
114 case syscall
.AF_INET6
:
115 a
:= (*syscall
.RawSockaddrInet6
)(addr
).Addr
116 addrs
= append(addrs
, IP
{a
[0], a
[1], a
[2], a
[3], a
[4], a
[5], a
[6], a
[7], a
[8], a
[9], a
[10], a
[11], a
[12], a
[13], a
[14], a
[15]})
118 return nil, os
.NewSyscallError("LookupIP", syscall
.EWINDOWS
)
124 func getservbyname(network
, service
string) (port
int, err error
) {
131 s
, err
:= syscall
.GetServByName(service
, network
)
133 return 0, os
.NewSyscallError("GetServByName", err
)
135 return int(syscall
.Ntohs(s
.Port
)), nil
138 func oldLookupPort(network
, service
string) (port
int, err error
) {
139 // GetServByName return value is stored in thread local storage.
140 // Start new os thread before the call to prevent races.
145 ch
:= make(chan result
)
147 runtime
.LockOSThread()
148 defer runtime
.UnlockOSThread()
149 port
, err
:= getservbyname(network
, service
)
150 ch
<- result
{port
: port
, err
: err
}
156 func newLookupPort(network
, service
string) (port
int, err error
) {
160 stype
= syscall
.SOCK_STREAM
162 stype
= syscall
.SOCK_DGRAM
164 hints
:= syscall
.AddrinfoW
{
165 Family
: syscall
.AF_UNSPEC
,
167 Protocol
: syscall
.IPPROTO_IP
,
169 var result
*syscall
.AddrinfoW
170 e
:= syscall
.GetAddrInfoW(nil, syscall
.StringToUTF16Ptr(service
), &hints
, &result
)
172 return 0, os
.NewSyscallError("GetAddrInfoW", e
)
174 defer syscall
.FreeAddrInfoW(result
)
176 return 0, os
.NewSyscallError("LookupPort", syscall
.EINVAL
)
178 addr
:= unsafe
.Pointer(result
.Addr
)
179 switch result
.Family
{
180 case syscall
.AF_INET
:
181 a
:= (*syscall
.RawSockaddrInet4
)(addr
)
182 return int(syscall
.Ntohs(a
.Port
)), nil
183 case syscall
.AF_INET6
:
184 a
:= (*syscall
.RawSockaddrInet6
)(addr
)
185 return int(syscall
.Ntohs(a
.Port
)), nil
187 return 0, os
.NewSyscallError("LookupPort", syscall
.EINVAL
)
190 func lookupCNAME(name
string) (cname
string, err error
) {
191 var r
*syscall
.DNSRecord
192 e
:= syscall
.DnsQuery(name
, syscall
.DNS_TYPE_CNAME
, 0, nil, &r
, nil)
194 return "", os
.NewSyscallError("LookupCNAME", e
)
196 defer syscall
.DnsRecordListFree(r
, 1)
197 if r
!= nil && r
.Type
== syscall
.DNS_TYPE_CNAME
{
198 v
:= (*syscall
.DNSPTRData
)(unsafe
.Pointer(&r
.Data
[0]))
199 cname
= syscall
.UTF16ToString((*[256]uint16)(unsafe
.Pointer(v
.Host
))[:]) + "."
204 func lookupSRV(service
, proto
, name
string) (cname
string, addrs
[]*SRV
, err error
) {
206 if service
== "" && proto
== "" {
209 target
= "_" + service
+ "._" + proto
+ "." + name
211 var r
*syscall
.DNSRecord
212 e
:= syscall
.DnsQuery(target
, syscall
.DNS_TYPE_SRV
, 0, nil, &r
, nil)
214 return "", nil, os
.NewSyscallError("LookupSRV", e
)
216 defer syscall
.DnsRecordListFree(r
, 1)
217 addrs
= make([]*SRV
, 0, 10)
218 for p
:= r
; p
!= nil && p
.Type
== syscall
.DNS_TYPE_SRV
; p
= p
.Next
{
219 v
:= (*syscall
.DNSSRVData
)(unsafe
.Pointer(&p
.Data
[0]))
220 addrs
= append(addrs
, &SRV
{syscall
.UTF16ToString((*[256]uint16)(unsafe
.Pointer(v
.Target
))[:]), v
.Port
, v
.Priority
, v
.Weight
})
222 byPriorityWeight(addrs
).sort()
223 return name
, addrs
, nil
226 func lookupMX(name
string) (mx
[]*MX
, err error
) {
227 var r
*syscall
.DNSRecord
228 e
:= syscall
.DnsQuery(name
, syscall
.DNS_TYPE_MX
, 0, nil, &r
, nil)
230 return nil, os
.NewSyscallError("LookupMX", e
)
232 defer syscall
.DnsRecordListFree(r
, 1)
233 mx
= make([]*MX
, 0, 10)
234 for p
:= r
; p
!= nil && p
.Type
== syscall
.DNS_TYPE_MX
; p
= p
.Next
{
235 v
:= (*syscall
.DNSMXData
)(unsafe
.Pointer(&p
.Data
[0]))
236 mx
= append(mx
, &MX
{syscall
.UTF16ToString((*[256]uint16)(unsafe
.Pointer(v
.NameExchange
))[:]) + ".", v
.Preference
})
242 func lookupNS(name
string) (ns
[]*NS
, err error
) {
243 var r
*syscall
.DNSRecord
244 e
:= syscall
.DnsQuery(name
, syscall
.DNS_TYPE_NS
, 0, nil, &r
, nil)
246 return nil, os
.NewSyscallError("LookupNS", e
)
248 defer syscall
.DnsRecordListFree(r
, 1)
249 ns
= make([]*NS
, 0, 10)
250 for p
:= r
; p
!= nil && p
.Type
== syscall
.DNS_TYPE_NS
; p
= p
.Next
{
251 v
:= (*syscall
.DNSPTRData
)(unsafe
.Pointer(&p
.Data
[0]))
252 ns
= append(ns
, &NS
{syscall
.UTF16ToString((*[256]uint16)(unsafe
.Pointer(v
.Host
))[:]) + "."})
257 func lookupTXT(name
string) (txt
[]string, err error
) {
258 var r
*syscall
.DNSRecord
259 e
:= syscall
.DnsQuery(name
, syscall
.DNS_TYPE_TEXT
, 0, nil, &r
, nil)
261 return nil, os
.NewSyscallError("LookupTXT", e
)
263 defer syscall
.DnsRecordListFree(r
, 1)
264 txt
= make([]string, 0, 10)
265 if r
!= nil && r
.Type
== syscall
.DNS_TYPE_TEXT
{
266 d
:= (*syscall
.DNSTXTData
)(unsafe
.Pointer(&r
.Data
[0]))
267 for _
, v
:= range (*[1 << 10]*uint16)(unsafe
.Pointer(&(d
.StringArray
[0])))[:d
.StringCount
] {
268 s
:= syscall
.UTF16ToString((*[1 << 20]uint16)(unsafe
.Pointer(v
))[:])
275 func lookupAddr(addr
string) (name
[]string, err error
) {
276 arpa
, err
:= reverseaddr(addr
)
280 var r
*syscall
.DNSRecord
281 e
:= syscall
.DnsQuery(arpa
, syscall
.DNS_TYPE_PTR
, 0, nil, &r
, nil)
283 return nil, os
.NewSyscallError("LookupAddr", e
)
285 defer syscall
.DnsRecordListFree(r
, 1)
286 name
= make([]string, 0, 10)
287 for p
:= r
; p
!= nil && p
.Type
== syscall
.DNS_TYPE_PTR
; p
= p
.Next
{
288 v
:= (*syscall
.DNSPTRData
)(unsafe
.Pointer(&p
.Data
[0]))
289 name
= append(name
, syscall
.UTF16ToString((*[256]uint16)(unsafe
.Pointer(v
.Host
))[:]))