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.
6 // +build darwin dragonfly freebsd linux netbsd openbsd
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
26 func libc_getaddrinfo(node
*byte, service
*byte, hints
*syscall
.Addrinfo
, res
**syscall
.Addrinfo
) int
29 func libc_freeaddrinfo(res
*syscall
.Addrinfo
)
32 func libc_gai_strerror(errcode
int) *byte
34 // bytePtrToString takes a NUL-terminated array of bytes and convert
36 func bytePtrToString(p
*byte) string {
37 a
:= (*[10000]byte)(unsafe
.Pointer(p
))
45 func cgoLookupHost(name
string) (addrs
[]string, err error
, completed
bool) {
46 ip
, err
, completed
:= cgoLookupIP(name
)
47 for _
, p
:= range ip
{
48 addrs
= append(addrs
, p
.String())
53 func cgoLookupPort(net
, service
string) (port
int, err error
, completed
bool) {
57 var res
*syscall
.Addrinfo
58 var hints syscall
.Addrinfo
63 case "tcp", "tcp4", "tcp6":
64 hints
.Ai_socktype
= syscall
.SOCK_STREAM
65 hints
.Ai_protocol
= syscall
.IPPROTO_TCP
66 case "udp", "udp4", "udp6":
67 hints
.Ai_socktype
= syscall
.SOCK_DGRAM
68 hints
.Ai_protocol
= syscall
.IPPROTO_UDP
70 return 0, UnknownNetworkError(net
), true
75 hints
.Ai_family
= syscall
.AF_INET
77 hints
.Ai_family
= syscall
.AF_INET6
81 s
:= syscall
.StringBytePtr(service
)
82 syscall
.Entersyscall()
83 gerrno
:= libc_getaddrinfo(nil, s
, &hints
, &res
)
86 defer libc_freeaddrinfo(res
)
87 for r
:= res
; r
!= nil; r
= r
.Ai_next
{
92 sa
:= (*syscall
.RawSockaddrInet4
)(unsafe
.Pointer(r
.Ai_addr
))
93 p
:= (*[2]byte)(unsafe
.Pointer(&sa
.Port
))
94 return int(p
[0])<<8 |
int(p
[1]), nil, true
95 case syscall
.AF_INET6
:
96 sa
:= (*syscall
.RawSockaddrInet6
)(unsafe
.Pointer(r
.Ai_addr
))
97 p
:= (*[2]byte)(unsafe
.Pointer(&sa
.Port
))
98 return int(p
[0])<<8 |
int(p
[1]), nil, true
102 return 0, &AddrError
{"unknown port", net
+ "/" + service
}, true
105 func cgoLookupIPCNAME(name
string) (addrs
[]IP
, cname
string, err error
, completed
bool) {
107 defer releaseThread()
109 var res
*syscall
.Addrinfo
110 var hints syscall
.Addrinfo
112 hints
.Ai_flags
= int32(cgoAddrInfoFlags())
113 hints
.Ai_socktype
= syscall
.SOCK_STREAM
115 h
:= syscall
.StringBytePtr(name
)
116 syscall
.Entersyscall()
117 gerrno
:= libc_getaddrinfo(h
, nil, &hints
, &res
)
118 syscall
.Exitsyscall()
121 if gerrno
== syscall
.EAI_NONAME
{
123 } else if gerrno
== syscall
.EAI_SYSTEM
{
124 errno
:= syscall
.GetErrno()
126 // err should not be nil, but sometimes getaddrinfo returns
127 // gerrno == C.EAI_SYSTEM with err == nil on Linux.
128 // The report claims that it happens when we have too many
129 // open files, so use syscall.EMFILE (too many open files in system).
130 // Most system calls would return ENFILE (too many open files),
131 // so at the least EMFILE should be easy to recognize if this
132 // comes up again. golang.org/issue/6232.
133 errno
= syscall
.EMFILE
137 str
= bytePtrToString(libc_gai_strerror(gerrno
))
139 return nil, "", &DNSError
{Err
: str
, Name
: name
}, true
141 defer libc_freeaddrinfo(res
)
143 cname
= bytePtrToString((*byte)(unsafe
.Pointer(res
.Ai_canonname
)))
147 if len(cname
) > 0 && cname
[len(cname
)-1] != '.' {
151 for r
:= res
; r
!= nil; r
= r
.Ai_next
{
152 // We only asked for SOCK_STREAM, but check anyhow.
153 if r
.Ai_socktype
!= syscall
.SOCK_STREAM
{
159 case syscall
.AF_INET
:
160 sa
:= (*syscall
.RawSockaddrInet4
)(unsafe
.Pointer(r
.Ai_addr
))
161 addrs
= append(addrs
, copyIP(sa
.Addr
[:]))
162 case syscall
.AF_INET6
:
163 sa
:= (*syscall
.RawSockaddrInet6
)(unsafe
.Pointer(r
.Ai_addr
))
164 addrs
= append(addrs
, copyIP(sa
.Addr
[:]))
167 return addrs
, cname
, nil, true
170 func cgoLookupIP(name
string) (addrs
[]IP
, err error
, completed
bool) {
171 addrs
, _
, err
, completed
= cgoLookupIPCNAME(name
)
175 func cgoLookupCNAME(name
string) (cname
string, err error
, completed
bool) {
176 _
, cname
, err
, completed
= cgoLookupIPCNAME(name
)
180 func copyIP(x IP
) IP
{
184 y
:= make(IP
, len(x
))