mirror of
https://github.com/golang/go
synced 2024-11-26 06:07:57 -07:00
net: use libc (not cgo) for DNS on macOS
Change the macOS implementation to use libc calls. Using libc calls directly is what we do for all the runtime and os syscalls. Doing so here as well improves consistency and also makes it possible to cross-compile (from non-Mac systems) macOS binaries that use the native name resolver. Fixes #12524. Change-Id: I011f4fcc5c50fbb5396e494889765dcbb9342336 Reviewed-on: https://go-review.googlesource.com/c/go/+/446178 Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
661e931dd1
commit
a3559f3301
@ -6,3 +6,15 @@
|
|||||||
|
|
||||||
TEXT ·libc_getentropy_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_getentropy_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_getentropy(SB)
|
JMP libc_getentropy(SB)
|
||||||
|
|
||||||
|
TEXT ·libc_getaddrinfo_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getaddrinfo(SB)
|
||||||
|
|
||||||
|
TEXT ·libc_freeaddrinfo_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_freeaddrinfo(SB)
|
||||||
|
|
||||||
|
TEXT ·libc_getnameinfo_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_getnameinfo(SB)
|
||||||
|
|
||||||
|
TEXT ·libc_gai_strerror_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_gai_strerror(SB)
|
||||||
|
@ -8,7 +8,6 @@ package unix
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"internal/abi"
|
"internal/abi"
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,6 +26,3 @@ func GetEntropy(p []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname syscall_syscall syscall.syscall
|
|
||||||
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
|
||||||
|
116
src/internal/syscall/unix/net_darwin.go
Normal file
116
src/internal/syscall/unix/net_darwin.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"internal/abi"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
AI_CANONNAME = 0x2
|
||||||
|
AI_ALL = 0x100
|
||||||
|
AI_V4MAPPED = 0x800
|
||||||
|
AI_MASK = 0x1407
|
||||||
|
|
||||||
|
EAI_AGAIN = 2
|
||||||
|
EAI_NONAME = 8
|
||||||
|
EAI_SYSTEM = 11
|
||||||
|
EAI_OVERFLOW = 14
|
||||||
|
|
||||||
|
NI_NAMEREQD = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
type Addrinfo struct {
|
||||||
|
Flags int32
|
||||||
|
Family int32
|
||||||
|
Socktype int32
|
||||||
|
Protocol int32
|
||||||
|
Addrlen uint32
|
||||||
|
Canonname *byte
|
||||||
|
Addr *syscall.RawSockaddr
|
||||||
|
Next *Addrinfo
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:cgo_import_dynamic libc_getaddrinfo getaddrinfo "/usr/lib/libSystem.B.dylib"
|
||||||
|
func libc_getaddrinfo_trampoline()
|
||||||
|
|
||||||
|
func Getaddrinfo(hostname, servname *byte, hints *Addrinfo, res **Addrinfo) (int, error) {
|
||||||
|
gerrno, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getaddrinfo_trampoline),
|
||||||
|
uintptr(unsafe.Pointer(hostname)),
|
||||||
|
uintptr(unsafe.Pointer(servname)),
|
||||||
|
uintptr(unsafe.Pointer(hints)),
|
||||||
|
uintptr(unsafe.Pointer(res)),
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
var err error
|
||||||
|
if errno != 0 {
|
||||||
|
err = errno
|
||||||
|
}
|
||||||
|
return int(gerrno), err
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:cgo_import_dynamic libc_freeaddrinfo freeaddrinfo "/usr/lib/libSystem.B.dylib"
|
||||||
|
func libc_freeaddrinfo_trampoline()
|
||||||
|
|
||||||
|
func Freeaddrinfo(ai *Addrinfo) {
|
||||||
|
syscall_syscall6(abi.FuncPCABI0(libc_freeaddrinfo_trampoline),
|
||||||
|
uintptr(unsafe.Pointer(ai)),
|
||||||
|
0, 0, 0, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:cgo_import_dynamic libc_getnameinfo getnameinfo "/usr/lib/libSystem.B.dylib"
|
||||||
|
func libc_getnameinfo_trampoline()
|
||||||
|
|
||||||
|
func Getnameinfo(sa *syscall.RawSockaddr, salen int, host *byte, hostlen int, serv *byte, servlen int, flags int) (int, error) {
|
||||||
|
gerrno, _, errno := syscall_syscall9(abi.FuncPCABI0(libc_getnameinfo_trampoline),
|
||||||
|
uintptr(unsafe.Pointer(sa)),
|
||||||
|
uintptr(salen),
|
||||||
|
uintptr(unsafe.Pointer(host)),
|
||||||
|
uintptr(hostlen),
|
||||||
|
uintptr(unsafe.Pointer(serv)),
|
||||||
|
uintptr(servlen),
|
||||||
|
uintptr(flags),
|
||||||
|
0,
|
||||||
|
0)
|
||||||
|
var err error
|
||||||
|
if errno != 0 {
|
||||||
|
err = errno
|
||||||
|
}
|
||||||
|
return int(gerrno), err
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:cgo_import_dynamic libc_gai_strerror gai_strerror "/usr/lib/libSystem.B.dylib"
|
||||||
|
func libc_gai_strerror_trampoline()
|
||||||
|
|
||||||
|
func GaiStrerror(ecode int) string {
|
||||||
|
r1, _, _ := syscall_syscall(abi.FuncPCABI0(libc_gai_strerror_trampoline),
|
||||||
|
uintptr(ecode),
|
||||||
|
0, 0)
|
||||||
|
return GoString((*byte)(unsafe.Pointer(r1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GoString(p *byte) string {
|
||||||
|
if p == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
x := unsafe.Slice(p, 1e9)
|
||||||
|
for i, c := range x {
|
||||||
|
if c == 0 {
|
||||||
|
return string(x[:i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname syscall_syscall syscall.syscall
|
||||||
|
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||||
|
|
||||||
|
//go:linkname syscall_syscall6 syscall.syscall6
|
||||||
|
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||||
|
|
||||||
|
//go:linkname syscall_syscall9 syscall.syscall9
|
||||||
|
func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build cgo && !netgo && (darwin || (linux && !android) || netbsd || solaris)
|
//go:build cgo && !netgo && ((linux && !android) || netbsd || solaris)
|
||||||
|
|
||||||
package net
|
package net
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build cgo && !netgo && (aix || darwin || dragonfly || freebsd || netbsd || openbsd)
|
//go:build cgo && !netgo && (aix || dragonfly || freebsd || netbsd || openbsd)
|
||||||
|
|
||||||
package net
|
package net
|
||||||
|
|
||||||
|
@ -2,25 +2,15 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This file is called cgo_unix.go, but to allow syscalls-to-libc-based
|
||||||
|
// implementations to share the code, it does not use cgo directly.
|
||||||
|
// Instead of C.foo it uses _C_foo, which is defined in either
|
||||||
|
// cgo_unix_cgo.go or cgo_unix_syscall.go
|
||||||
|
|
||||||
//go:build cgo && !netgo && unix
|
//go:build cgo && !netgo && unix
|
||||||
|
|
||||||
package net
|
package net
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// If nothing else defined EAI_OVERFLOW, make sure it has a value.
|
|
||||||
#ifndef EAI_OVERFLOW
|
|
||||||
#define EAI_OVERFLOW -12
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -32,8 +22,8 @@ import (
|
|||||||
// by convention.
|
// by convention.
|
||||||
type addrinfoErrno int
|
type addrinfoErrno int
|
||||||
|
|
||||||
func (eai addrinfoErrno) Error() string { return C.GoString(C.gai_strerror(C.int(eai))) }
|
func (eai addrinfoErrno) Error() string { return _C_gai_strerror(_C_int(eai)) }
|
||||||
func (eai addrinfoErrno) Temporary() bool { return eai == C.EAI_AGAIN }
|
func (eai addrinfoErrno) Temporary() bool { return eai == _C_EAI_AGAIN }
|
||||||
func (eai addrinfoErrno) Timeout() bool { return false }
|
func (eai addrinfoErrno) Timeout() bool { return false }
|
||||||
|
|
||||||
type portLookupResult struct {
|
type portLookupResult struct {
|
||||||
@ -61,23 +51,23 @@ func cgoLookupHost(ctx context.Context, name string) (hosts []string, err error,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cgoLookupPort(ctx context.Context, network, service string) (port int, err error, completed bool) {
|
func cgoLookupPort(ctx context.Context, network, service string) (port int, err error, completed bool) {
|
||||||
var hints C.struct_addrinfo
|
var hints _C_struct_addrinfo
|
||||||
switch network {
|
switch network {
|
||||||
case "": // no hints
|
case "": // no hints
|
||||||
case "tcp", "tcp4", "tcp6":
|
case "tcp", "tcp4", "tcp6":
|
||||||
hints.ai_socktype = C.SOCK_STREAM
|
*_C_ai_socktype(&hints) = _C_SOCK_STREAM
|
||||||
hints.ai_protocol = C.IPPROTO_TCP
|
*_C_ai_protocol(&hints) = _C_IPPROTO_TCP
|
||||||
case "udp", "udp4", "udp6":
|
case "udp", "udp4", "udp6":
|
||||||
hints.ai_socktype = C.SOCK_DGRAM
|
*_C_ai_socktype(&hints) = _C_SOCK_DGRAM
|
||||||
hints.ai_protocol = C.IPPROTO_UDP
|
*_C_ai_protocol(&hints) = _C_IPPROTO_UDP
|
||||||
default:
|
default:
|
||||||
return 0, &DNSError{Err: "unknown network", Name: network + "/" + service}, true
|
return 0, &DNSError{Err: "unknown network", Name: network + "/" + service}, true
|
||||||
}
|
}
|
||||||
switch ipVersion(network) {
|
switch ipVersion(network) {
|
||||||
case '4':
|
case '4':
|
||||||
hints.ai_family = C.AF_INET
|
*_C_ai_family(&hints) = _C_AF_INET
|
||||||
case '6':
|
case '6':
|
||||||
hints.ai_family = C.AF_INET6
|
*_C_ai_family(&hints) = _C_AF_INET6
|
||||||
}
|
}
|
||||||
if ctx.Done() == nil {
|
if ctx.Done() == nil {
|
||||||
port, err := cgoLookupServicePort(&hints, network, service)
|
port, err := cgoLookupServicePort(&hints, network, service)
|
||||||
@ -95,19 +85,19 @@ func cgoLookupPort(ctx context.Context, network, service string) (port int, err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cgoLookupServicePort(hints *C.struct_addrinfo, network, service string) (port int, err error) {
|
func cgoLookupServicePort(hints *_C_struct_addrinfo, network, service string) (port int, err error) {
|
||||||
cservice := make([]byte, len(service)+1)
|
cservice := make([]byte, len(service)+1)
|
||||||
copy(cservice, service)
|
copy(cservice, service)
|
||||||
// Lowercase the C service name.
|
// Lowercase the C service name.
|
||||||
for i, b := range cservice[:len(service)] {
|
for i, b := range cservice[:len(service)] {
|
||||||
cservice[i] = lowerASCII(b)
|
cservice[i] = lowerASCII(b)
|
||||||
}
|
}
|
||||||
var res *C.struct_addrinfo
|
var res *_C_struct_addrinfo
|
||||||
gerrno, err := C.getaddrinfo(nil, (*C.char)(unsafe.Pointer(&cservice[0])), hints, &res)
|
gerrno, err := _C_getaddrinfo(nil, (*_C_char)(unsafe.Pointer(&cservice[0])), hints, &res)
|
||||||
if gerrno != 0 {
|
if gerrno != 0 {
|
||||||
isTemporary := false
|
isTemporary := false
|
||||||
switch gerrno {
|
switch gerrno {
|
||||||
case C.EAI_SYSTEM:
|
case _C_EAI_SYSTEM:
|
||||||
if err == nil { // see golang.org/issue/6232
|
if err == nil { // see golang.org/issue/6232
|
||||||
err = syscall.EMFILE
|
err = syscall.EMFILE
|
||||||
}
|
}
|
||||||
@ -117,16 +107,16 @@ func cgoLookupServicePort(hints *C.struct_addrinfo, network, service string) (po
|
|||||||
}
|
}
|
||||||
return 0, &DNSError{Err: err.Error(), Name: network + "/" + service, IsTemporary: isTemporary}
|
return 0, &DNSError{Err: err.Error(), Name: network + "/" + service, IsTemporary: isTemporary}
|
||||||
}
|
}
|
||||||
defer C.freeaddrinfo(res)
|
defer _C_freeaddrinfo(res)
|
||||||
|
|
||||||
for r := res; r != nil; r = r.ai_next {
|
for r := res; r != nil; r = *_C_ai_next(r) {
|
||||||
switch r.ai_family {
|
switch *_C_ai_family(r) {
|
||||||
case C.AF_INET:
|
case _C_AF_INET:
|
||||||
sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.ai_addr))
|
sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(*_C_ai_addr(r)))
|
||||||
p := (*[2]byte)(unsafe.Pointer(&sa.Port))
|
p := (*[2]byte)(unsafe.Pointer(&sa.Port))
|
||||||
return int(p[0])<<8 | int(p[1]), nil
|
return int(p[0])<<8 | int(p[1]), nil
|
||||||
case C.AF_INET6:
|
case _C_AF_INET6:
|
||||||
sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.ai_addr))
|
sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(*_C_ai_addr(r)))
|
||||||
p := (*[2]byte)(unsafe.Pointer(&sa.Port))
|
p := (*[2]byte)(unsafe.Pointer(&sa.Port))
|
||||||
return int(p[0])<<8 | int(p[1]), nil
|
return int(p[0])<<8 | int(p[1]), nil
|
||||||
}
|
}
|
||||||
@ -134,7 +124,7 @@ func cgoLookupServicePort(hints *C.struct_addrinfo, network, service string) (po
|
|||||||
return 0, &DNSError{Err: "unknown port", Name: network + "/" + service}
|
return 0, &DNSError{Err: "unknown port", Name: network + "/" + service}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cgoPortLookup(result chan<- portLookupResult, hints *C.struct_addrinfo, network, service string) {
|
func cgoPortLookup(result chan<- portLookupResult, hints *_C_struct_addrinfo, network, service string) {
|
||||||
port, err := cgoLookupServicePort(hints, network, service)
|
port, err := cgoLookupServicePort(hints, network, service)
|
||||||
result <- portLookupResult{port, err}
|
result <- portLookupResult{port, err}
|
||||||
}
|
}
|
||||||
@ -143,29 +133,29 @@ func cgoLookupIPCNAME(network, name string) (addrs []IPAddr, cname string, err e
|
|||||||
acquireThread()
|
acquireThread()
|
||||||
defer releaseThread()
|
defer releaseThread()
|
||||||
|
|
||||||
var hints C.struct_addrinfo
|
var hints _C_struct_addrinfo
|
||||||
hints.ai_flags = cgoAddrInfoFlags
|
*_C_ai_flags(&hints) = cgoAddrInfoFlags
|
||||||
hints.ai_socktype = C.SOCK_STREAM
|
*_C_ai_socktype(&hints) = _C_SOCK_STREAM
|
||||||
hints.ai_family = C.AF_UNSPEC
|
*_C_ai_family(&hints) = _C_AF_UNSPEC
|
||||||
switch ipVersion(network) {
|
switch ipVersion(network) {
|
||||||
case '4':
|
case '4':
|
||||||
hints.ai_family = C.AF_INET
|
*_C_ai_family(&hints) = _C_AF_INET
|
||||||
case '6':
|
case '6':
|
||||||
hints.ai_family = C.AF_INET6
|
*_C_ai_family(&hints) = _C_AF_INET6
|
||||||
}
|
}
|
||||||
|
|
||||||
h := make([]byte, len(name)+1)
|
h := make([]byte, len(name)+1)
|
||||||
copy(h, name)
|
copy(h, name)
|
||||||
var res *C.struct_addrinfo
|
var res *_C_struct_addrinfo
|
||||||
gerrno, err := C.getaddrinfo((*C.char)(unsafe.Pointer(&h[0])), nil, &hints, &res)
|
gerrno, err := _C_getaddrinfo((*_C_char)(unsafe.Pointer(&h[0])), nil, &hints, &res)
|
||||||
if gerrno != 0 {
|
if gerrno != 0 {
|
||||||
isErrorNoSuchHost := false
|
isErrorNoSuchHost := false
|
||||||
isTemporary := false
|
isTemporary := false
|
||||||
switch gerrno {
|
switch gerrno {
|
||||||
case C.EAI_SYSTEM:
|
case _C_EAI_SYSTEM:
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// err should not be nil, but sometimes getaddrinfo returns
|
// err should not be nil, but sometimes getaddrinfo returns
|
||||||
// gerrno == C.EAI_SYSTEM with err == nil on Linux.
|
// gerrno == _C_EAI_SYSTEM with err == nil on Linux.
|
||||||
// The report claims that it happens when we have too many
|
// The report claims that it happens when we have too many
|
||||||
// open files, so use syscall.EMFILE (too many open files in system).
|
// open files, so use syscall.EMFILE (too many open files in system).
|
||||||
// Most system calls would return ENFILE (too many open files),
|
// Most system calls would return ENFILE (too many open files),
|
||||||
@ -173,7 +163,7 @@ func cgoLookupIPCNAME(network, name string) (addrs []IPAddr, cname string, err e
|
|||||||
// comes up again. golang.org/issue/6232.
|
// comes up again. golang.org/issue/6232.
|
||||||
err = syscall.EMFILE
|
err = syscall.EMFILE
|
||||||
}
|
}
|
||||||
case C.EAI_NONAME:
|
case _C_EAI_NONAME:
|
||||||
err = errNoSuchHost
|
err = errNoSuchHost
|
||||||
isErrorNoSuchHost = true
|
isErrorNoSuchHost = true
|
||||||
default:
|
default:
|
||||||
@ -183,10 +173,10 @@ func cgoLookupIPCNAME(network, name string) (addrs []IPAddr, cname string, err e
|
|||||||
|
|
||||||
return nil, "", &DNSError{Err: err.Error(), Name: name, IsNotFound: isErrorNoSuchHost, IsTemporary: isTemporary}
|
return nil, "", &DNSError{Err: err.Error(), Name: name, IsNotFound: isErrorNoSuchHost, IsTemporary: isTemporary}
|
||||||
}
|
}
|
||||||
defer C.freeaddrinfo(res)
|
defer _C_freeaddrinfo(res)
|
||||||
|
|
||||||
if res != nil {
|
if res != nil {
|
||||||
cname = C.GoString(res.ai_canonname)
|
cname = _C_GoString(*_C_ai_canonname(res))
|
||||||
if cname == "" {
|
if cname == "" {
|
||||||
cname = name
|
cname = name
|
||||||
}
|
}
|
||||||
@ -194,18 +184,18 @@ func cgoLookupIPCNAME(network, name string) (addrs []IPAddr, cname string, err e
|
|||||||
cname += "."
|
cname += "."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for r := res; r != nil; r = r.ai_next {
|
for r := res; r != nil; r = *_C_ai_next(r) {
|
||||||
// We only asked for SOCK_STREAM, but check anyhow.
|
// We only asked for SOCK_STREAM, but check anyhow.
|
||||||
if r.ai_socktype != C.SOCK_STREAM {
|
if *_C_ai_socktype(r) != _C_SOCK_STREAM {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
switch r.ai_family {
|
switch *_C_ai_family(r) {
|
||||||
case C.AF_INET:
|
case _C_AF_INET:
|
||||||
sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.ai_addr))
|
sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(*_C_ai_addr(r)))
|
||||||
addr := IPAddr{IP: copyIP(sa.Addr[:])}
|
addr := IPAddr{IP: copyIP(sa.Addr[:])}
|
||||||
addrs = append(addrs, addr)
|
addrs = append(addrs, addr)
|
||||||
case C.AF_INET6:
|
case _C_AF_INET6:
|
||||||
sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.ai_addr))
|
sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(*_C_ai_addr(r)))
|
||||||
addr := IPAddr{IP: copyIP(sa.Addr[:]), Zone: zoneCache.name(int(sa.Scope_id))}
|
addr := IPAddr{IP: copyIP(sa.Addr[:]), Zone: zoneCache.name(int(sa.Scope_id))}
|
||||||
addrs = append(addrs, addr)
|
addrs = append(addrs, addr)
|
||||||
}
|
}
|
||||||
@ -288,7 +278,7 @@ func cgoLookupPTR(ctx context.Context, addr string) (names []string, err error,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cgoLookupAddrPTR(addr string, sa *C.struct_sockaddr, salen C.socklen_t) (names []string, err error) {
|
func cgoLookupAddrPTR(addr string, sa *_C_struct_sockaddr, salen _C_socklen_t) (names []string, err error) {
|
||||||
acquireThread()
|
acquireThread()
|
||||||
defer releaseThread()
|
defer releaseThread()
|
||||||
|
|
||||||
@ -297,14 +287,14 @@ func cgoLookupAddrPTR(addr string, sa *C.struct_sockaddr, salen C.socklen_t) (na
|
|||||||
for l := nameinfoLen; l <= maxNameinfoLen; l *= 2 {
|
for l := nameinfoLen; l <= maxNameinfoLen; l *= 2 {
|
||||||
b = make([]byte, l)
|
b = make([]byte, l)
|
||||||
gerrno, err = cgoNameinfoPTR(b, sa, salen)
|
gerrno, err = cgoNameinfoPTR(b, sa, salen)
|
||||||
if gerrno == 0 || gerrno != C.EAI_OVERFLOW {
|
if gerrno == 0 || gerrno != _C_EAI_OVERFLOW {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if gerrno != 0 {
|
if gerrno != 0 {
|
||||||
isTemporary := false
|
isTemporary := false
|
||||||
switch gerrno {
|
switch gerrno {
|
||||||
case C.EAI_SYSTEM:
|
case _C_EAI_SYSTEM:
|
||||||
if err == nil { // see golang.org/issue/6232
|
if err == nil { // see golang.org/issue/6232
|
||||||
err = syscall.EMFILE
|
err = syscall.EMFILE
|
||||||
}
|
}
|
||||||
@ -323,17 +313,17 @@ func cgoLookupAddrPTR(addr string, sa *C.struct_sockaddr, salen C.socklen_t) (na
|
|||||||
return []string{absDomainName(string(b))}, nil
|
return []string{absDomainName(string(b))}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cgoReverseLookup(result chan<- reverseLookupResult, addr string, sa *C.struct_sockaddr, salen C.socklen_t) {
|
func cgoReverseLookup(result chan<- reverseLookupResult, addr string, sa *_C_struct_sockaddr, salen _C_socklen_t) {
|
||||||
names, err := cgoLookupAddrPTR(addr, sa, salen)
|
names, err := cgoLookupAddrPTR(addr, sa, salen)
|
||||||
result <- reverseLookupResult{names, err}
|
result <- reverseLookupResult{names, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cgoSockaddr(ip IP, zone string) (*C.struct_sockaddr, C.socklen_t) {
|
func cgoSockaddr(ip IP, zone string) (*_C_struct_sockaddr, _C_socklen_t) {
|
||||||
if ip4 := ip.To4(); ip4 != nil {
|
if ip4 := ip.To4(); ip4 != nil {
|
||||||
return cgoSockaddrInet4(ip4), C.socklen_t(syscall.SizeofSockaddrInet4)
|
return cgoSockaddrInet4(ip4), _C_socklen_t(syscall.SizeofSockaddrInet4)
|
||||||
}
|
}
|
||||||
if ip6 := ip.To16(); ip6 != nil {
|
if ip6 := ip.To16(); ip6 != nil {
|
||||||
return cgoSockaddrInet6(ip6, zoneCache.index(zone)), C.socklen_t(syscall.SizeofSockaddrInet6)
|
return cgoSockaddrInet6(ip6, zoneCache.index(zone)), _C_socklen_t(syscall.SizeofSockaddrInet6)
|
||||||
}
|
}
|
||||||
return nil, 0
|
return nil, 0
|
||||||
}
|
}
|
||||||
|
71
src/net/cgo_unix_cgo.go
Normal file
71
src/net/cgo_unix_cgo.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build cgo && !netgo && unix && !darwin
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// If nothing else defined EAI_OVERFLOW, make sure it has a value.
|
||||||
|
#ifndef EAI_OVERFLOW
|
||||||
|
#define EAI_OVERFLOW -12
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
_C_AF_INET = C.AF_INET
|
||||||
|
_C_AF_INET6 = C.AF_INET6
|
||||||
|
_C_AF_UNSPEC = C.AF_UNSPEC
|
||||||
|
_C_EAI_AGAIN = C.EAI_AGAIN
|
||||||
|
_C_EAI_NONAME = C.EAI_NONAME
|
||||||
|
_C_EAI_OVERFLOW = C.EAI_OVERFLOW
|
||||||
|
_C_EAI_SYSTEM = C.EAI_SYSTEM
|
||||||
|
_C_IPPROTO_TCP = C.IPPROTO_TCP
|
||||||
|
_C_IPPROTO_UDP = C.IPPROTO_UDP
|
||||||
|
_C_SOCK_DGRAM = C.SOCK_DGRAM
|
||||||
|
_C_SOCK_STREAM = C.SOCK_STREAM
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
_C_char = C.char
|
||||||
|
_C_uchar = C.uchar
|
||||||
|
_C_int = C.int
|
||||||
|
_C_uint = C.uint
|
||||||
|
_C_socklen_t = C.socklen_t
|
||||||
|
_C_struct_addrinfo = C.struct_addrinfo
|
||||||
|
_C_struct_sockaddr = C.struct_sockaddr
|
||||||
|
)
|
||||||
|
|
||||||
|
func _C_GoString(p *_C_char) string { return C.GoString(p) }
|
||||||
|
func _C_CString(s string) *_C_char { return C.CString(s) }
|
||||||
|
|
||||||
|
func _C_ai_addr(ai *_C_struct_addrinfo) **_C_struct_sockaddr { return &ai.ai_addr }
|
||||||
|
func _C_ai_addrlen(ai *_C_struct_addrinfo) *_C_uint { return &ai.ai_addrlen }
|
||||||
|
func _C_ai_canonname(ai *_C_struct_addrinfo) **_C_char { return &ai.ai_canonname }
|
||||||
|
func _C_ai_family(ai *_C_struct_addrinfo) *_C_int { return &ai.ai_family }
|
||||||
|
func _C_ai_flags(ai *_C_struct_addrinfo) *_C_int { return &ai.ai_flags }
|
||||||
|
func _C_ai_next(ai *_C_struct_addrinfo) **_C_struct_addrinfo { return &ai.ai_next }
|
||||||
|
func _C_ai_protocol(ai *_C_struct_addrinfo) *_C_int { return &ai.ai_protocol }
|
||||||
|
func _C_ai_socktype(ai *_C_struct_addrinfo) *_C_int { return &ai.ai_socktype }
|
||||||
|
|
||||||
|
func _C_freeaddrinfo(ai *_C_struct_addrinfo) {
|
||||||
|
C.freeaddrinfo(ai)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _C_gai_strerror(eai _C_int) string {
|
||||||
|
return C.GoString(C.gai_strerror(eai))
|
||||||
|
}
|
||||||
|
|
||||||
|
func _C_getaddrinfo(hostname, servname *_C_char, hints *_C_struct_addrinfo, res **_C_struct_addrinfo) (int, error) {
|
||||||
|
x, err := C.getaddrinfo(hostname, servname, hints, res)
|
||||||
|
return int(x), err
|
||||||
|
}
|
85
src/net/cgo_unix_syscall.go
Normal file
85
src/net/cgo_unix_syscall.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build cgo && !netgo && darwin
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"internal/syscall/unix"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_C_AF_INET = syscall.AF_INET
|
||||||
|
_C_AF_INET6 = syscall.AF_INET6
|
||||||
|
_C_AF_UNSPEC = syscall.AF_UNSPEC
|
||||||
|
_C_EAI_AGAIN = unix.EAI_AGAIN
|
||||||
|
_C_EAI_NONAME = unix.EAI_NONAME
|
||||||
|
_C_EAI_OVERFLOW = unix.EAI_OVERFLOW
|
||||||
|
_C_EAI_SYSTEM = unix.EAI_SYSTEM
|
||||||
|
_C_IPPROTO_TCP = syscall.IPPROTO_TCP
|
||||||
|
_C_IPPROTO_UDP = syscall.IPPROTO_UDP
|
||||||
|
_C_SOCK_DGRAM = syscall.SOCK_DGRAM
|
||||||
|
_C_SOCK_STREAM = syscall.SOCK_STREAM
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
_C_char = byte
|
||||||
|
_C_int = int32
|
||||||
|
_C_uchar = byte
|
||||||
|
_C_uint = uint32
|
||||||
|
_C_socklen_t = int
|
||||||
|
_C_struct_addrinfo = unix.Addrinfo
|
||||||
|
_C_struct_sockaddr = syscall.RawSockaddr
|
||||||
|
)
|
||||||
|
|
||||||
|
func _C_GoString(p *_C_char) string {
|
||||||
|
return unix.GoString(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _C_CString(s string) *_C_char {
|
||||||
|
b := make([]byte, len(s)+1)
|
||||||
|
copy(b, s)
|
||||||
|
return &b[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func _C_ai_addr(ai *_C_struct_addrinfo) **_C_struct_sockaddr { return &ai.Addr }
|
||||||
|
func _C_ai_addrlen(ai *_C_struct_addrinfo) *_C_uint { return &ai.Addrlen }
|
||||||
|
func _C_ai_canonname(ai *_C_struct_addrinfo) **_C_char { return &ai.Canonname }
|
||||||
|
func _C_ai_family(ai *_C_struct_addrinfo) *_C_int { return &ai.Family }
|
||||||
|
func _C_ai_flags(ai *_C_struct_addrinfo) *_C_int { return &ai.Flags }
|
||||||
|
func _C_ai_next(ai *_C_struct_addrinfo) **_C_struct_addrinfo { return &ai.Next }
|
||||||
|
func _C_ai_protocol(ai *_C_struct_addrinfo) *_C_int { return &ai.Protocol }
|
||||||
|
func _C_ai_socktype(ai *_C_struct_addrinfo) *_C_int { return &ai.Socktype }
|
||||||
|
|
||||||
|
func _C_freeaddrinfo(ai *_C_struct_addrinfo) {
|
||||||
|
unix.Freeaddrinfo(ai)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _C_gai_strerror(eai _C_int) string {
|
||||||
|
return unix.GaiStrerror(int(eai))
|
||||||
|
}
|
||||||
|
|
||||||
|
func _C_getaddrinfo(hostname, servname *byte, hints *_C_struct_addrinfo, res **_C_struct_addrinfo) (int, error) {
|
||||||
|
return unix.Getaddrinfo(hostname, servname, hints, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cgoNameinfoPTR(b []byte, sa *syscall.RawSockaddr, salen int) (int, error) {
|
||||||
|
gerrno, err := unix.Getnameinfo(sa, salen, &b[0], len(b), nil, 0, unix.NI_NAMEREQD)
|
||||||
|
return int(gerrno), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func cgoSockaddrInet4(ip IP) *syscall.RawSockaddr {
|
||||||
|
sa := syscall.RawSockaddrInet4{Len: syscall.SizeofSockaddrInet4, Family: syscall.AF_INET}
|
||||||
|
copy(sa.Addr[:], ip)
|
||||||
|
return (*syscall.RawSockaddr)(unsafe.Pointer(&sa))
|
||||||
|
}
|
||||||
|
|
||||||
|
func cgoSockaddrInet6(ip IP, zone int) *syscall.RawSockaddr {
|
||||||
|
sa := syscall.RawSockaddrInet6{Len: syscall.SizeofSockaddrInet6, Family: syscall.AF_INET6, Scope_id: uint32(zone)}
|
||||||
|
copy(sa.Addr[:], ip)
|
||||||
|
return (*syscall.RawSockaddr)(unsafe.Pointer(&sa))
|
||||||
|
}
|
@ -49,6 +49,17 @@ func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
|
|||||||
}
|
}
|
||||||
func syscall6()
|
func syscall6()
|
||||||
|
|
||||||
|
//go:linkname syscall_syscall9 syscall.syscall9
|
||||||
|
//go:nosplit
|
||||||
|
//go:cgo_unsafe_args
|
||||||
|
func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
|
||||||
|
entersyscall()
|
||||||
|
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall9)), unsafe.Pointer(&fn))
|
||||||
|
exitsyscall()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func syscall9()
|
||||||
|
|
||||||
//go:linkname syscall_syscall6X syscall.syscall6X
|
//go:linkname syscall_syscall6X syscall.syscall6X
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
|
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
|
||||||
@ -87,7 +98,7 @@ func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintpt
|
|||||||
return args.r1, args.r2, args.err
|
return args.r1, args.r2, args.err
|
||||||
}
|
}
|
||||||
|
|
||||||
// syscallNoErr is used in crypto/x509 to call into Security.framework and CF.
|
// crypto_x509_syscall is used in crypto/x509/internal/macos to call into Security.framework and CF.
|
||||||
|
|
||||||
//go:linkname crypto_x509_syscall crypto/x509/internal/macos.syscall
|
//go:linkname crypto_x509_syscall crypto/x509/internal/macos.syscall
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
|
@ -839,6 +839,65 @@ ok:
|
|||||||
POPQ BP
|
POPQ BP
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// syscall9 calls a function in libc on behalf of the syscall package.
|
||||||
|
// syscall9 takes a pointer to a struct like:
|
||||||
|
// struct {
|
||||||
|
// fn uintptr
|
||||||
|
// a1 uintptr
|
||||||
|
// a2 uintptr
|
||||||
|
// a3 uintptr
|
||||||
|
// a4 uintptr
|
||||||
|
// a5 uintptr
|
||||||
|
// a6 uintptr
|
||||||
|
// a7 uintptr
|
||||||
|
// a8 uintptr
|
||||||
|
// a9 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall9 must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
//
|
||||||
|
// syscall9 expects a 32-bit result and tests for 32-bit -1
|
||||||
|
// to decide there was an error.
|
||||||
|
TEXT runtime·syscall9(SB),NOSPLIT,$0
|
||||||
|
PUSHQ BP
|
||||||
|
MOVQ SP, BP
|
||||||
|
SUBQ $16, SP
|
||||||
|
MOVQ (0*8)(DI), R13// fn
|
||||||
|
MOVQ (2*8)(DI), SI // a2
|
||||||
|
MOVQ (3*8)(DI), DX // a3
|
||||||
|
MOVQ (4*8)(DI), CX // a4
|
||||||
|
MOVQ (5*8)(DI), R8 // a5
|
||||||
|
MOVQ (6*8)(DI), R9 // a6
|
||||||
|
MOVQ (7*8)(DI), R10 // a7
|
||||||
|
MOVQ (8*8)(DI), R11 // a8
|
||||||
|
MOVQ (9*8)(DI), R12 // a9
|
||||||
|
MOVQ DI, (SP)
|
||||||
|
MOVQ (1*8)(DI), DI // a1
|
||||||
|
XORL AX, AX // vararg: say "no float args"
|
||||||
|
|
||||||
|
CALL R13
|
||||||
|
|
||||||
|
MOVQ (SP), DI
|
||||||
|
MOVQ AX, (10*8)(DI) // r1
|
||||||
|
MOVQ DX, (11*8)(DI) // r2
|
||||||
|
|
||||||
|
CMPL AX, $-1
|
||||||
|
JNE ok
|
||||||
|
|
||||||
|
CALL libc_error(SB)
|
||||||
|
MOVLQSX (AX), AX
|
||||||
|
MOVQ (SP), DI
|
||||||
|
MOVQ AX, (12*8)(DI) // err
|
||||||
|
|
||||||
|
ok:
|
||||||
|
XORL AX, AX // no error (it's ignored anyway)
|
||||||
|
MOVQ BP, SP
|
||||||
|
POPQ BP
|
||||||
|
RET
|
||||||
|
|
||||||
// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,
|
// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,
|
||||||
// takes 5 uintptrs and 1 float64, and only returns one value,
|
// takes 5 uintptrs and 1 float64, and only returns one value,
|
||||||
// for use with standard C ABI functions.
|
// for use with standard C ABI functions.
|
||||||
|
@ -669,6 +669,63 @@ TEXT runtime·syscall6X(SB),NOSPLIT,$0
|
|||||||
ok:
|
ok:
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// syscall9 calls a function in libc on behalf of the syscall package.
|
||||||
|
// syscall9 takes a pointer to a struct like:
|
||||||
|
// struct {
|
||||||
|
// fn uintptr
|
||||||
|
// a1 uintptr
|
||||||
|
// a2 uintptr
|
||||||
|
// a3 uintptr
|
||||||
|
// a4 uintptr
|
||||||
|
// a5 uintptr
|
||||||
|
// a6 uintptr
|
||||||
|
// a7 uintptr
|
||||||
|
// a8 uintptr
|
||||||
|
// a9 uintptr
|
||||||
|
// r1 uintptr
|
||||||
|
// r2 uintptr
|
||||||
|
// err uintptr
|
||||||
|
// }
|
||||||
|
// syscall9 must be called on the g0 stack with the
|
||||||
|
// C calling convention (use libcCall).
|
||||||
|
TEXT runtime·syscall9(SB),NOSPLIT,$0
|
||||||
|
SUB $16, RSP // push structure pointer
|
||||||
|
MOVD R0, 8(RSP)
|
||||||
|
|
||||||
|
MOVD 0(R0), R12 // fn
|
||||||
|
MOVD 16(R0), R1 // a2
|
||||||
|
MOVD 24(R0), R2 // a3
|
||||||
|
MOVD 32(R0), R3 // a4
|
||||||
|
MOVD 40(R0), R4 // a5
|
||||||
|
MOVD 48(R0), R5 // a6
|
||||||
|
MOVD 56(R0), R6 // a7
|
||||||
|
MOVD 64(R0), R7 // a8
|
||||||
|
MOVD 72(R0), R8 // a9
|
||||||
|
MOVD 8(R0), R0 // a1
|
||||||
|
|
||||||
|
// If fn is declared as vararg, we have to pass the vararg arguments on the stack.
|
||||||
|
// See syscall above. The only function this applies to is openat, for which the 4th
|
||||||
|
// arg must be on the stack.
|
||||||
|
MOVD R3, (RSP)
|
||||||
|
|
||||||
|
BL (R12)
|
||||||
|
|
||||||
|
MOVD 8(RSP), R2 // pop structure pointer
|
||||||
|
ADD $16, RSP
|
||||||
|
MOVD R0, 80(R2) // save r1
|
||||||
|
MOVD R1, 88(R2) // save r2
|
||||||
|
CMPW $-1, R0
|
||||||
|
BNE ok
|
||||||
|
SUB $16, RSP // push structure pointer
|
||||||
|
MOVD R2, 8(RSP)
|
||||||
|
BL libc_error(SB)
|
||||||
|
MOVW (R0), R0
|
||||||
|
MOVD 8(RSP), R2 // pop structure pointer
|
||||||
|
ADD $16, RSP
|
||||||
|
MOVD R0, 96(R2) // save err
|
||||||
|
ok:
|
||||||
|
RET
|
||||||
|
|
||||||
// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,
|
// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,
|
||||||
// takes 5 uintptrs and 1 float64, and only returns one value,
|
// takes 5 uintptrs and 1 float64, and only returns one value,
|
||||||
// for use with standard C ABI functions.
|
// for use with standard C ABI functions.
|
||||||
|
Loading…
Reference in New Issue
Block a user