package net
import (
)
const cgoAvailable = true
type addrinfoErrno int
func ( addrinfoErrno) () string { return _C_gai_strerror(_C_int()) }
func ( addrinfoErrno) () bool { return == _C_EAI_AGAIN }
func ( addrinfoErrno) () bool { return false }
func ( addrinfoErrno) () {}
func [ any]( context.Context, string, func() (, error)) (, error) {
if := acquireThread(); != nil {
var
return , &DNSError{
Name: ,
Err: mapErr().Error(),
IsTimeout: == context.DeadlineExceeded,
}
}
if .Done() == nil {
defer releaseThread()
return ()
}
type struct {
error
}
:= make(chan , 1)
go func() {
defer releaseThread()
var
., . = ()
<-
}()
select {
case := <-:
return ., .
case <-.Done():
var
return , &DNSError{
Name: ,
Err: mapErr(.Err()).Error(),
IsTimeout: .Err() == context.DeadlineExceeded,
}
}
}
func ( context.Context, string) ( []string, error) {
, := cgoLookupIP(, "ip", )
if != nil {
return nil,
}
for , := range {
= append(, .String())
}
return , nil
}
func ( context.Context, , string) ( int, error) {
var _C_struct_addrinfo
switch {
case "ip":
case "tcp", "tcp4", "tcp6":
*_C_ai_socktype(&) = _C_SOCK_STREAM
*_C_ai_protocol(&) = _C_IPPROTO_TCP
case "udp", "udp4", "udp6":
*_C_ai_socktype(&) = _C_SOCK_DGRAM
*_C_ai_protocol(&) = _C_IPPROTO_UDP
default:
return 0, &DNSError{Err: "unknown network", Name: + "/" + }
}
switch ipVersion() {
case '4':
*_C_ai_family(&) = _C_AF_INET
case '6':
*_C_ai_family(&) = _C_AF_INET6
}
return doBlockingWithCtx(, +"/"+, func() (int, error) {
return cgoLookupServicePort(&, , )
})
}
func ( *_C_struct_addrinfo, , string) ( int, error) {
, := syscall.ByteSliceFromString()
if != nil {
return 0, &DNSError{Err: .Error(), Name: + "/" + }
}
for , := range [:len()] {
[] = lowerASCII()
}
var *_C_struct_addrinfo
, := _C_getaddrinfo(nil, (*_C_char)(unsafe.Pointer(&[0])), , &)
if != 0 {
switch {
case _C_EAI_SYSTEM:
if == nil {
= syscall.EMFILE
}
return 0, newDNSError(, +"/"+, "")
case _C_EAI_SERVICE, _C_EAI_NONAME:
return 0, newDNSError(errUnknownPort, +"/"+, "")
default:
return 0, newDNSError(addrinfoErrno(), +"/"+, "")
}
}
defer _C_freeaddrinfo()
for := ; != nil; = *_C_ai_next() {
switch *_C_ai_family() {
case _C_AF_INET:
:= (*syscall.RawSockaddrInet4)(unsafe.Pointer(*_C_ai_addr()))
:= (*[2]byte)(unsafe.Pointer(&.Port))
return int([0])<<8 | int([1]), nil
case _C_AF_INET6:
:= (*syscall.RawSockaddrInet6)(unsafe.Pointer(*_C_ai_addr()))
:= (*[2]byte)(unsafe.Pointer(&.Port))
return int([0])<<8 | int([1]), nil
}
}
return 0, newDNSError(errUnknownPort, +"/"+, "")
}
func (, string) ( []IPAddr, error) {
var _C_struct_addrinfo
*_C_ai_flags(&) = cgoAddrInfoFlags
*_C_ai_socktype(&) = _C_SOCK_STREAM
*_C_ai_family(&) = _C_AF_UNSPEC
switch ipVersion() {
case '4':
*_C_ai_family(&) = _C_AF_INET
case '6':
*_C_ai_family(&) = _C_AF_INET6
}
, := syscall.BytePtrFromString()
if != nil {
return nil, &DNSError{Err: .Error(), Name: }
}
var *_C_struct_addrinfo
, := _C_getaddrinfo((*_C_char)(unsafe.Pointer()), nil, &, &)
if != 0 {
switch {
case _C_EAI_SYSTEM:
if == nil {
= syscall.EMFILE
}
return nil, newDNSError(, , "")
case _C_EAI_NONAME, _C_EAI_NODATA:
return nil, newDNSError(errNoSuchHost, , "")
case _C_EAI_ADDRFAMILY:
if runtime.GOOS == "freebsd" {
return nil, newDNSError(errNoSuchHost, , "")
}
fallthrough
default:
return nil, newDNSError(addrinfoErrno(), , "")
}
}
defer _C_freeaddrinfo()
for := ; != nil; = *_C_ai_next() {
if *_C_ai_socktype() != _C_SOCK_STREAM {
continue
}
switch *_C_ai_family() {
case _C_AF_INET:
:= (*syscall.RawSockaddrInet4)(unsafe.Pointer(*_C_ai_addr()))
:= IPAddr{IP: copyIP(.Addr[:])}
= append(, )
case _C_AF_INET6:
:= (*syscall.RawSockaddrInet6)(unsafe.Pointer(*_C_ai_addr()))
:= IPAddr{IP: copyIP(.Addr[:]), Zone: zoneCache.name(int(.Scope_id))}
= append(, )
}
}
return , nil
}
func ( context.Context, , string) ( []IPAddr, error) {
return doBlockingWithCtx(, , func() ([]IPAddr, error) {
return cgoLookupHostIP(, )
})
}
const (
nameinfoLen = 64
maxNameinfoLen = 4096
)
func ( context.Context, string) ( []string, error) {
, := netip.ParseAddr()
if != nil {
return nil, &DNSError{Err: "invalid address", Name: }
}
, := cgoSockaddr(IP(.AsSlice()), .Zone())
if == nil {
return nil, &DNSError{Err: "invalid address " + .String(), Name: }
}
return doBlockingWithCtx(, , func() ([]string, error) {
return cgoLookupAddrPTR(, , )
})
}
func ( string, *_C_struct_sockaddr, _C_socklen_t) ( []string, error) {
var int
var []byte
for := nameinfoLen; <= maxNameinfoLen; *= 2 {
= make([]byte, )
, = cgoNameinfoPTR(, , )
if == 0 || != _C_EAI_OVERFLOW {
break
}
}
if != 0 {
switch {
case _C_EAI_SYSTEM:
if == nil {
= syscall.EMFILE
}
return nil, newDNSError(, , "")
case _C_EAI_NONAME:
return nil, newDNSError(errNoSuchHost, , "")
default:
return nil, newDNSError(addrinfoErrno(), , "")
}
}
if := bytealg.IndexByte(, 0); != -1 {
= [:]
}
return []string{absDomainName(string())}, nil
}
func ( IP, string) (*_C_struct_sockaddr, _C_socklen_t) {
if := .To4(); != nil {
return cgoSockaddrInet4(), _C_socklen_t(syscall.SizeofSockaddrInet4)
}
if := .To16(); != nil {
return cgoSockaddrInet6(, zoneCache.index()), _C_socklen_t(syscall.SizeofSockaddrInet6)
}
return nil, 0
}
func ( context.Context, string) ( string, error, bool) {
, := resSearch(, , int(dnsmessage.TypeCNAME), int(dnsmessage.ClassINET))
if != nil {
return
}
, = parseCNAMEFromResources()
if != nil {
return "", , false
}
return , nil, true
}
func ( context.Context, string, , int) ([]dnsmessage.Resource, error) {
return doBlockingWithCtx(, , func() ([]dnsmessage.Resource, error) {
return cgoResSearch(, , )
})
}
func ( string, , int) ([]dnsmessage.Resource, error) {
:= unsafe.Sizeof(_C_struct___res_state{})
var *_C_struct___res_state
if > 0 {
:= _C_malloc()
defer _C_free()
:= unsafe.Slice((*byte)(), )
clear()
= (*_C_struct___res_state)(unsafe.Pointer(&[0]))
}
if := _C_res_ninit(); != nil {
return nil, errors.New("res_ninit failure: " + .Error())
}
defer _C_res_nclose()
:= maxDNSPacketSize
:= (*_C_uchar)(_C_malloc(uintptr()))
defer _C_free(unsafe.Pointer())
, := syscall.BytePtrFromString()
if != nil {
return nil,
}
var int
for {
:= _C_res_nsearch(, (*_C_char)(unsafe.Pointer()), , , , )
if <= 0 || > 0xffff {
return nil, errors.New("res_nsearch failure")
}
if <= {
break
}
_C_free(unsafe.Pointer())
=
= (*_C_uchar)(_C_malloc(uintptr()))
}
var dnsmessage.Parser
if , := .Start(unsafe.Slice((*byte)(unsafe.Pointer()), )); != nil {
return nil,
}
.SkipAllQuestions()
, := .AllAnswers()
if != nil {
return nil,
}
return , nil
}