annotate libgo/go/net/cgo_unix.go @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 // Copyright 2011 The Go Authors. All rights reserved.
kono
parents:
diff changeset
2 // Use of this source code is governed by a BSD-style
kono
parents:
diff changeset
3 // license that can be found in the LICENSE file.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 // +build cgo,!netgo
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
6 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
111
kono
parents:
diff changeset
7
kono
parents:
diff changeset
8 package net
kono
parents:
diff changeset
9
kono
parents:
diff changeset
10 /*
kono
parents:
diff changeset
11 #include <sys/types.h>
kono
parents:
diff changeset
12 #include <sys/socket.h>
kono
parents:
diff changeset
13 #include <netinet/in.h>
kono
parents:
diff changeset
14 #include <netdb.h>
kono
parents:
diff changeset
15 #include <unistd.h>
kono
parents:
diff changeset
16 #include <string.h>
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
17
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
18 // If nothing else defined EAI_OVERFLOW, make sure it has a value.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
19 #ifndef EAI_OVERFLOW
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
20 #define EAI_OVERFLOW -12
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
21 #endif
111
kono
parents:
diff changeset
22 */
kono
parents:
diff changeset
23
kono
parents:
diff changeset
24 import (
kono
parents:
diff changeset
25 "context"
kono
parents:
diff changeset
26 "syscall"
kono
parents:
diff changeset
27 "unsafe"
kono
parents:
diff changeset
28 )
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 //extern getaddrinfo
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
31 func libc_getaddrinfo(node *byte, service *byte, hints *syscall.Addrinfo, res **syscall.Addrinfo) int32
111
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 //extern freeaddrinfo
kono
parents:
diff changeset
34 func libc_freeaddrinfo(res *syscall.Addrinfo)
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 //extern gai_strerror
kono
parents:
diff changeset
37 func libc_gai_strerror(errcode int) *byte
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 // bytePtrToString takes a NUL-terminated array of bytes and convert
kono
parents:
diff changeset
40 // it to a Go string.
kono
parents:
diff changeset
41 func bytePtrToString(p *byte) string {
kono
parents:
diff changeset
42 a := (*[10000]byte)(unsafe.Pointer(p))
kono
parents:
diff changeset
43 i := 0
kono
parents:
diff changeset
44 for a[i] != 0 {
kono
parents:
diff changeset
45 i++
kono
parents:
diff changeset
46 }
kono
parents:
diff changeset
47 return string(a[:i])
kono
parents:
diff changeset
48 }
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 // An addrinfoErrno represents a getaddrinfo, getnameinfo-specific
kono
parents:
diff changeset
51 // error number. It's a signed number and a zero value is a non-error
kono
parents:
diff changeset
52 // by convention.
kono
parents:
diff changeset
53 type addrinfoErrno int
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 func (eai addrinfoErrno) Error() string { return bytePtrToString(libc_gai_strerror(int(eai))) }
kono
parents:
diff changeset
56 func (eai addrinfoErrno) Temporary() bool { return eai == syscall.EAI_AGAIN }
kono
parents:
diff changeset
57 func (eai addrinfoErrno) Timeout() bool { return false }
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 type portLookupResult struct {
kono
parents:
diff changeset
60 port int
kono
parents:
diff changeset
61 err error
kono
parents:
diff changeset
62 }
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 type ipLookupResult struct {
kono
parents:
diff changeset
65 addrs []IPAddr
kono
parents:
diff changeset
66 cname string
kono
parents:
diff changeset
67 err error
kono
parents:
diff changeset
68 }
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 type reverseLookupResult struct {
kono
parents:
diff changeset
71 names []string
kono
parents:
diff changeset
72 err error
kono
parents:
diff changeset
73 }
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 func cgoLookupHost(ctx context.Context, name string) (hosts []string, err error, completed bool) {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
76 addrs, err, completed := cgoLookupIP(ctx, "ip", name)
111
kono
parents:
diff changeset
77 for _, addr := range addrs {
kono
parents:
diff changeset
78 hosts = append(hosts, addr.String())
kono
parents:
diff changeset
79 }
kono
parents:
diff changeset
80 return
kono
parents:
diff changeset
81 }
kono
parents:
diff changeset
82
kono
parents:
diff changeset
83 func cgoLookupPort(ctx context.Context, network, service string) (port int, err error, completed bool) {
kono
parents:
diff changeset
84 var hints syscall.Addrinfo
kono
parents:
diff changeset
85 switch network {
kono
parents:
diff changeset
86 case "": // no hints
kono
parents:
diff changeset
87 case "tcp", "tcp4", "tcp6":
kono
parents:
diff changeset
88 hints.Ai_socktype = syscall.SOCK_STREAM
kono
parents:
diff changeset
89 hints.Ai_protocol = syscall.IPPROTO_TCP
kono
parents:
diff changeset
90 case "udp", "udp4", "udp6":
kono
parents:
diff changeset
91 hints.Ai_socktype = syscall.SOCK_DGRAM
kono
parents:
diff changeset
92 hints.Ai_protocol = syscall.IPPROTO_UDP
kono
parents:
diff changeset
93 default:
kono
parents:
diff changeset
94 return 0, &DNSError{Err: "unknown network", Name: network + "/" + service}, true
kono
parents:
diff changeset
95 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
96 switch ipVersion(network) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
97 case '4':
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
98 hints.Ai_family = syscall.AF_INET
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
99 case '6':
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
100 hints.Ai_family = syscall.AF_INET6
111
kono
parents:
diff changeset
101 }
kono
parents:
diff changeset
102 if ctx.Done() == nil {
kono
parents:
diff changeset
103 port, err := cgoLookupServicePort(&hints, network, service)
kono
parents:
diff changeset
104 return port, err, true
kono
parents:
diff changeset
105 }
kono
parents:
diff changeset
106 result := make(chan portLookupResult, 1)
kono
parents:
diff changeset
107 go cgoPortLookup(result, &hints, network, service)
kono
parents:
diff changeset
108 select {
kono
parents:
diff changeset
109 case r := <-result:
kono
parents:
diff changeset
110 return r.port, r.err, true
kono
parents:
diff changeset
111 case <-ctx.Done():
kono
parents:
diff changeset
112 // Since there isn't a portable way to cancel the lookup,
kono
parents:
diff changeset
113 // we just let it finish and write to the buffered channel.
kono
parents:
diff changeset
114 return 0, mapErr(ctx.Err()), false
kono
parents:
diff changeset
115 }
kono
parents:
diff changeset
116 }
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 func cgoLookupServicePort(hints *syscall.Addrinfo, network, service string) (port int, err error) {
kono
parents:
diff changeset
119 s, err := syscall.BytePtrFromString(service)
kono
parents:
diff changeset
120 if err != nil {
kono
parents:
diff changeset
121 return 0, err
kono
parents:
diff changeset
122 }
kono
parents:
diff changeset
123 // Lowercase the service name in the memory passed to C.
kono
parents:
diff changeset
124 for i := 0; i < len(service); i++ {
kono
parents:
diff changeset
125 bp := (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(s)) + uintptr(i)))
kono
parents:
diff changeset
126 *bp = lowerASCII(*bp)
kono
parents:
diff changeset
127 }
kono
parents:
diff changeset
128 var res *syscall.Addrinfo
kono
parents:
diff changeset
129 syscall.Entersyscall()
kono
parents:
diff changeset
130 gerrno := libc_getaddrinfo(nil, s, hints, &res)
kono
parents:
diff changeset
131 syscall.Exitsyscall()
kono
parents:
diff changeset
132 if gerrno != 0 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
133 isTemporary := false
111
kono
parents:
diff changeset
134 switch gerrno {
kono
parents:
diff changeset
135 case syscall.EAI_SYSTEM:
kono
parents:
diff changeset
136 errno := syscall.GetErrno()
kono
parents:
diff changeset
137 if errno == 0 { // see golang.org/issue/6232
kono
parents:
diff changeset
138 errno = syscall.EMFILE
kono
parents:
diff changeset
139 }
kono
parents:
diff changeset
140 err = errno
kono
parents:
diff changeset
141 default:
kono
parents:
diff changeset
142 err = addrinfoErrno(gerrno)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
143 isTemporary = addrinfoErrno(gerrno).Temporary()
111
kono
parents:
diff changeset
144 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
145 return 0, &DNSError{Err: err.Error(), Name: network + "/" + service, IsTemporary: isTemporary}
111
kono
parents:
diff changeset
146 }
kono
parents:
diff changeset
147 defer libc_freeaddrinfo(res)
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 for r := res; r != nil; r = r.Ai_next {
kono
parents:
diff changeset
150 switch r.Ai_family {
kono
parents:
diff changeset
151 case syscall.AF_INET:
kono
parents:
diff changeset
152 sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.Ai_addr))
kono
parents:
diff changeset
153 p := (*[2]byte)(unsafe.Pointer(&sa.Port))
kono
parents:
diff changeset
154 return int(p[0])<<8 | int(p[1]), nil
kono
parents:
diff changeset
155 case syscall.AF_INET6:
kono
parents:
diff changeset
156 sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.Ai_addr))
kono
parents:
diff changeset
157 p := (*[2]byte)(unsafe.Pointer(&sa.Port))
kono
parents:
diff changeset
158 return int(p[0])<<8 | int(p[1]), nil
kono
parents:
diff changeset
159 }
kono
parents:
diff changeset
160 }
kono
parents:
diff changeset
161 return 0, &DNSError{Err: "unknown port", Name: network + "/" + service}
kono
parents:
diff changeset
162 }
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 func cgoPortLookup(result chan<- portLookupResult, hints *syscall.Addrinfo, network, service string) {
kono
parents:
diff changeset
165 port, err := cgoLookupServicePort(hints, network, service)
kono
parents:
diff changeset
166 result <- portLookupResult{port, err}
kono
parents:
diff changeset
167 }
kono
parents:
diff changeset
168
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
169 func cgoLookupIPCNAME(network, name string) (addrs []IPAddr, cname string, err error) {
111
kono
parents:
diff changeset
170 acquireThread()
kono
parents:
diff changeset
171 defer releaseThread()
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 var hints syscall.Addrinfo
kono
parents:
diff changeset
174 hints.Ai_flags = int32(cgoAddrInfoFlags)
kono
parents:
diff changeset
175 hints.Ai_socktype = syscall.SOCK_STREAM
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
176 hints.Ai_family = syscall.AF_UNSPEC
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
177 switch ipVersion(network) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
178 case '4':
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
179 hints.Ai_family = syscall.AF_INET
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
180 case '6':
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
181 hints.Ai_family = syscall.AF_INET6
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
182 }
111
kono
parents:
diff changeset
183
kono
parents:
diff changeset
184 h := syscall.StringBytePtr(name)
kono
parents:
diff changeset
185 var res *syscall.Addrinfo
kono
parents:
diff changeset
186 syscall.Entersyscall()
kono
parents:
diff changeset
187 gerrno := libc_getaddrinfo(h, nil, &hints, &res)
kono
parents:
diff changeset
188 syscall.Exitsyscall()
kono
parents:
diff changeset
189 if gerrno != 0 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
190 isErrorNoSuchHost := false
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
191 isTemporary := false
111
kono
parents:
diff changeset
192 switch gerrno {
kono
parents:
diff changeset
193 case syscall.EAI_SYSTEM:
kono
parents:
diff changeset
194 errno := syscall.GetErrno()
kono
parents:
diff changeset
195 if errno == 0 {
kono
parents:
diff changeset
196 // err should not be nil, but sometimes getaddrinfo returns
kono
parents:
diff changeset
197 // gerrno == C.EAI_SYSTEM with err == nil on Linux.
kono
parents:
diff changeset
198 // The report claims that it happens when we have too many
kono
parents:
diff changeset
199 // open files, so use syscall.EMFILE (too many open files in system).
kono
parents:
diff changeset
200 // Most system calls would return ENFILE (too many open files),
kono
parents:
diff changeset
201 // so at the least EMFILE should be easy to recognize if this
kono
parents:
diff changeset
202 // comes up again. golang.org/issue/6232.
kono
parents:
diff changeset
203 errno = syscall.EMFILE
kono
parents:
diff changeset
204 }
kono
parents:
diff changeset
205 err = errno
kono
parents:
diff changeset
206 case syscall.EAI_NONAME:
kono
parents:
diff changeset
207 err = errNoSuchHost
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
208 isErrorNoSuchHost = true
111
kono
parents:
diff changeset
209 default:
kono
parents:
diff changeset
210 err = addrinfoErrno(gerrno)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
211 isTemporary = addrinfoErrno(gerrno).Temporary()
111
kono
parents:
diff changeset
212 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
213
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
214 return nil, "", &DNSError{Err: err.Error(), Name: name, IsNotFound: isErrorNoSuchHost, IsTemporary: isTemporary}
111
kono
parents:
diff changeset
215 }
kono
parents:
diff changeset
216 defer libc_freeaddrinfo(res)
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 if res != nil {
kono
parents:
diff changeset
219 cname = bytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
kono
parents:
diff changeset
220 if cname == "" {
kono
parents:
diff changeset
221 cname = name
kono
parents:
diff changeset
222 }
kono
parents:
diff changeset
223 if len(cname) > 0 && cname[len(cname)-1] != '.' {
kono
parents:
diff changeset
224 cname += "."
kono
parents:
diff changeset
225 }
kono
parents:
diff changeset
226 }
kono
parents:
diff changeset
227 for r := res; r != nil; r = r.Ai_next {
kono
parents:
diff changeset
228 // We only asked for SOCK_STREAM, but check anyhow.
kono
parents:
diff changeset
229 if r.Ai_socktype != syscall.SOCK_STREAM {
kono
parents:
diff changeset
230 continue
kono
parents:
diff changeset
231 }
kono
parents:
diff changeset
232 switch r.Ai_family {
kono
parents:
diff changeset
233 case syscall.AF_INET:
kono
parents:
diff changeset
234 sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.Ai_addr))
kono
parents:
diff changeset
235 addr := IPAddr{IP: copyIP(sa.Addr[:])}
kono
parents:
diff changeset
236 addrs = append(addrs, addr)
kono
parents:
diff changeset
237 case syscall.AF_INET6:
kono
parents:
diff changeset
238 sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.Ai_addr))
kono
parents:
diff changeset
239 addr := IPAddr{IP: copyIP(sa.Addr[:]), Zone: zoneCache.name(int(sa.Scope_id))}
kono
parents:
diff changeset
240 addrs = append(addrs, addr)
kono
parents:
diff changeset
241 }
kono
parents:
diff changeset
242 }
kono
parents:
diff changeset
243 return addrs, cname, nil
kono
parents:
diff changeset
244 }
kono
parents:
diff changeset
245
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
246 func cgoIPLookup(result chan<- ipLookupResult, network, name string) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
247 addrs, cname, err := cgoLookupIPCNAME(network, name)
111
kono
parents:
diff changeset
248 result <- ipLookupResult{addrs, cname, err}
kono
parents:
diff changeset
249 }
kono
parents:
diff changeset
250
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
251 func cgoLookupIP(ctx context.Context, network, name string) (addrs []IPAddr, err error, completed bool) {
111
kono
parents:
diff changeset
252 if ctx.Done() == nil {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
253 addrs, _, err = cgoLookupIPCNAME(network, name)
111
kono
parents:
diff changeset
254 return addrs, err, true
kono
parents:
diff changeset
255 }
kono
parents:
diff changeset
256 result := make(chan ipLookupResult, 1)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
257 go cgoIPLookup(result, network, name)
111
kono
parents:
diff changeset
258 select {
kono
parents:
diff changeset
259 case r := <-result:
kono
parents:
diff changeset
260 return r.addrs, r.err, true
kono
parents:
diff changeset
261 case <-ctx.Done():
kono
parents:
diff changeset
262 return nil, mapErr(ctx.Err()), false
kono
parents:
diff changeset
263 }
kono
parents:
diff changeset
264 }
kono
parents:
diff changeset
265
kono
parents:
diff changeset
266 func cgoLookupCNAME(ctx context.Context, name string) (cname string, err error, completed bool) {
kono
parents:
diff changeset
267 if ctx.Done() == nil {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
268 _, cname, err = cgoLookupIPCNAME("ip", name)
111
kono
parents:
diff changeset
269 return cname, err, true
kono
parents:
diff changeset
270 }
kono
parents:
diff changeset
271 result := make(chan ipLookupResult, 1)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
272 go cgoIPLookup(result, "ip", name)
111
kono
parents:
diff changeset
273 select {
kono
parents:
diff changeset
274 case r := <-result:
kono
parents:
diff changeset
275 return r.cname, r.err, true
kono
parents:
diff changeset
276 case <-ctx.Done():
kono
parents:
diff changeset
277 return "", mapErr(ctx.Err()), false
kono
parents:
diff changeset
278 }
kono
parents:
diff changeset
279 }
kono
parents:
diff changeset
280
kono
parents:
diff changeset
281 // These are roughly enough for the following:
kono
parents:
diff changeset
282 //
kono
parents:
diff changeset
283 // Source Encoding Maximum length of single name entry
kono
parents:
diff changeset
284 // Unicast DNS ASCII or <=253 + a NUL terminator
kono
parents:
diff changeset
285 // Unicode in RFC 5892 252 * total number of labels + delimiters + a NUL terminator
kono
parents:
diff changeset
286 // Multicast DNS UTF-8 in RFC 5198 or <=253 + a NUL terminator
kono
parents:
diff changeset
287 // the same as unicast DNS ASCII <=253 + a NUL terminator
kono
parents:
diff changeset
288 // Local database various depends on implementation
kono
parents:
diff changeset
289 const (
kono
parents:
diff changeset
290 nameinfoLen = 64
kono
parents:
diff changeset
291 maxNameinfoLen = 4096
kono
parents:
diff changeset
292 )
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294 func cgoLookupPTR(ctx context.Context, addr string) (names []string, err error, completed bool) {
kono
parents:
diff changeset
295 var zone string
kono
parents:
diff changeset
296 ip := parseIPv4(addr)
kono
parents:
diff changeset
297 if ip == nil {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
298 ip, zone = parseIPv6Zone(addr)
111
kono
parents:
diff changeset
299 }
kono
parents:
diff changeset
300 if ip == nil {
kono
parents:
diff changeset
301 return nil, &DNSError{Err: "invalid address", Name: addr}, true
kono
parents:
diff changeset
302 }
kono
parents:
diff changeset
303 sa, salen := cgoSockaddr(ip, zone)
kono
parents:
diff changeset
304 if sa == nil {
kono
parents:
diff changeset
305 return nil, &DNSError{Err: "invalid address " + ip.String(), Name: addr}, true
kono
parents:
diff changeset
306 }
kono
parents:
diff changeset
307 if ctx.Done() == nil {
kono
parents:
diff changeset
308 names, err := cgoLookupAddrPTR(addr, sa, salen)
kono
parents:
diff changeset
309 return names, err, true
kono
parents:
diff changeset
310 }
kono
parents:
diff changeset
311 result := make(chan reverseLookupResult, 1)
kono
parents:
diff changeset
312 go cgoReverseLookup(result, addr, sa, salen)
kono
parents:
diff changeset
313 select {
kono
parents:
diff changeset
314 case r := <-result:
kono
parents:
diff changeset
315 return r.names, r.err, true
kono
parents:
diff changeset
316 case <-ctx.Done():
kono
parents:
diff changeset
317 return nil, mapErr(ctx.Err()), false
kono
parents:
diff changeset
318 }
kono
parents:
diff changeset
319 }
kono
parents:
diff changeset
320
kono
parents:
diff changeset
321 func cgoLookupAddrPTR(addr string, sa *syscall.RawSockaddr, salen syscall.Socklen_t) (names []string, err error) {
kono
parents:
diff changeset
322 acquireThread()
kono
parents:
diff changeset
323 defer releaseThread()
kono
parents:
diff changeset
324
kono
parents:
diff changeset
325 var gerrno int
kono
parents:
diff changeset
326 var b []byte
kono
parents:
diff changeset
327 for l := nameinfoLen; l <= maxNameinfoLen; l *= 2 {
kono
parents:
diff changeset
328 b = make([]byte, l)
kono
parents:
diff changeset
329 gerrno, err = cgoNameinfoPTR(b, sa, salen)
kono
parents:
diff changeset
330 if gerrno == 0 || gerrno != syscall.EAI_OVERFLOW {
kono
parents:
diff changeset
331 break
kono
parents:
diff changeset
332 }
kono
parents:
diff changeset
333 }
kono
parents:
diff changeset
334 if gerrno != 0 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
335 isTemporary := false
111
kono
parents:
diff changeset
336 switch gerrno {
kono
parents:
diff changeset
337 case syscall.EAI_SYSTEM:
kono
parents:
diff changeset
338 if err == nil { // see golang.org/issue/6232
kono
parents:
diff changeset
339 err = syscall.EMFILE
kono
parents:
diff changeset
340 }
kono
parents:
diff changeset
341 default:
kono
parents:
diff changeset
342 err = addrinfoErrno(gerrno)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
343 isTemporary = addrinfoErrno(gerrno).Temporary()
111
kono
parents:
diff changeset
344 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
345 return nil, &DNSError{Err: err.Error(), Name: addr, IsTemporary: isTemporary}
111
kono
parents:
diff changeset
346 }
kono
parents:
diff changeset
347 for i := 0; i < len(b); i++ {
kono
parents:
diff changeset
348 if b[i] == 0 {
kono
parents:
diff changeset
349 b = b[:i]
kono
parents:
diff changeset
350 break
kono
parents:
diff changeset
351 }
kono
parents:
diff changeset
352 }
kono
parents:
diff changeset
353 return []string{absDomainName(b)}, nil
kono
parents:
diff changeset
354 }
kono
parents:
diff changeset
355
kono
parents:
diff changeset
356 func cgoReverseLookup(result chan<- reverseLookupResult, addr string, sa *syscall.RawSockaddr, salen syscall.Socklen_t) {
kono
parents:
diff changeset
357 names, err := cgoLookupAddrPTR(addr, sa, salen)
kono
parents:
diff changeset
358 result <- reverseLookupResult{names, err}
kono
parents:
diff changeset
359 }
kono
parents:
diff changeset
360
kono
parents:
diff changeset
361 func cgoSockaddr(ip IP, zone string) (*syscall.RawSockaddr, syscall.Socklen_t) {
kono
parents:
diff changeset
362 if ip4 := ip.To4(); ip4 != nil {
kono
parents:
diff changeset
363 return cgoSockaddrInet4(ip4), syscall.Socklen_t(syscall.SizeofSockaddrInet4)
kono
parents:
diff changeset
364 }
kono
parents:
diff changeset
365 if ip6 := ip.To16(); ip6 != nil {
kono
parents:
diff changeset
366 return cgoSockaddrInet6(ip6, zoneCache.index(zone)), syscall.Socklen_t(syscall.SizeofSockaddrInet6)
kono
parents:
diff changeset
367 }
kono
parents:
diff changeset
368 return nil, 0
kono
parents:
diff changeset
369 }
kono
parents:
diff changeset
370
kono
parents:
diff changeset
371 func copyIP(x IP) IP {
kono
parents:
diff changeset
372 if len(x) < 16 {
kono
parents:
diff changeset
373 return x.To16()
kono
parents:
diff changeset
374 }
kono
parents:
diff changeset
375 y := make(IP, len(x))
kono
parents:
diff changeset
376 copy(y, x)
kono
parents:
diff changeset
377 return y
kono
parents:
diff changeset
378 }