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 darwin freebsd linux netbsd openbsd
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
25 func libc_getaddrinfo(node
*byte, service
*byte, hints
*syscall
.Addrinfo
, res
**syscall
.Addrinfo
) int
28 func libc_freeaddrinfo(res
*syscall
.Addrinfo
)
31 func libc_gai_strerror(errcode
int) *byte
33 // bytePtrToString takes a NUL-terminated array of bytes and convert
35 func bytePtrToString(p
*byte) string {
36 a
:= (*[10000]byte)(unsafe
.Pointer(p
))
44 func cgoLookupHost(name
string) (addrs
[]string, err error
, completed
bool) {
45 ip
, err
, completed
:= cgoLookupIP(name
)
46 for _
, p
:= range ip
{
47 addrs
= append(addrs
, p
.String())
52 func cgoLookupPort(net
, service
string) (port
int, err error
, completed
bool) {
53 var res
*syscall
.Addrinfo
54 var hints syscall
.Addrinfo
59 case "tcp", "tcp4", "tcp6":
60 hints
.Ai_socktype
= syscall
.SOCK_STREAM
61 hints
.Ai_protocol
= syscall
.IPPROTO_TCP
62 case "udp", "udp4", "udp6":
63 hints
.Ai_socktype
= syscall
.SOCK_DGRAM
64 hints
.Ai_protocol
= syscall
.IPPROTO_UDP
66 return 0, UnknownNetworkError(net
), true
71 hints
.Ai_family
= syscall
.AF_INET
73 hints
.Ai_family
= syscall
.AF_INET6
77 s
:= syscall
.StringBytePtr(service
)
78 syscall
.Entersyscall()
79 gerrno
:= libc_getaddrinfo(nil, s
, &hints
, &res
)
82 defer libc_freeaddrinfo(res
)
83 for r
:= res
; r
!= nil; r
= r
.Ai_next
{
88 sa
:= (*syscall
.RawSockaddrInet4
)(unsafe
.Pointer(r
.Ai_addr
))
89 p
:= (*[2]byte)(unsafe
.Pointer(&sa
.Port
))
90 return int(p
[0])<<8 |
int(p
[1]), nil, true
91 case syscall
.AF_INET6
:
92 sa
:= (*syscall
.RawSockaddrInet6
)(unsafe
.Pointer(r
.Ai_addr
))
93 p
:= (*[2]byte)(unsafe
.Pointer(&sa
.Port
))
94 return int(p
[0])<<8 |
int(p
[1]), nil, true
98 return 0, &AddrError
{"unknown port", net
+ "/" + service
}, true
101 func cgoLookupIPCNAME(name
string) (addrs
[]IP
, cname
string, err error
, completed
bool) {
102 var res
*syscall
.Addrinfo
103 var hints syscall
.Addrinfo
105 hints
.Ai_flags
= int32(cgoAddrInfoFlags())
107 h
:= syscall
.StringBytePtr(name
)
108 syscall
.Entersyscall()
109 gerrno
:= libc_getaddrinfo(h
, nil, &hints
, &res
)
110 syscall
.Exitsyscall()
113 if gerrno
== syscall
.EAI_NONAME
{
115 } else if gerrno
== syscall
.EAI_SYSTEM
{
116 str
= syscall
.GetErrno().Error()
118 str
= bytePtrToString(libc_gai_strerror(gerrno
))
120 return nil, "", &DNSError
{Err
: str
, Name
: name
}, true
122 defer libc_freeaddrinfo(res
)
124 cname
= bytePtrToString((*byte)(unsafe
.Pointer(res
.Ai_canonname
)))
128 if len(cname
) > 0 && cname
[len(cname
)-1] != '.' {
132 for r
:= res
; r
!= nil; r
= r
.Ai_next
{
133 // Everything comes back twice, once for UDP and once for TCP.
134 if r
.Ai_socktype
!= syscall
.SOCK_STREAM
{
140 case syscall
.AF_INET
:
141 sa
:= (*syscall
.RawSockaddrInet4
)(unsafe
.Pointer(r
.Ai_addr
))
142 addrs
= append(addrs
, copyIP(sa
.Addr
[:]))
143 case syscall
.AF_INET6
:
144 sa
:= (*syscall
.RawSockaddrInet6
)(unsafe
.Pointer(r
.Ai_addr
))
145 addrs
= append(addrs
, copyIP(sa
.Addr
[:]))
148 return addrs
, cname
, nil, true
151 func cgoLookupIP(name
string) (addrs
[]IP
, err error
, completed
bool) {
152 addrs
, _
, err
, completed
= cgoLookupIPCNAME(name
)
156 func cgoLookupCNAME(name
string) (cname
string, err error
, completed
bool) {
157 _
, cname
, err
, completed
= cgoLookupIPCNAME(name
)
161 func copyIP(x IP
) IP
{
162 y
:= make(IP
, len(x
))