mirror of
https://github.com/golang/go
synced 2024-11-23 17:30:02 -07:00
net: allow LookupAddr to use getnameinfo when cgo is enabled
This change allows LookupAddr to use getnameinfo through cgo for working together with various name services other than DNS. Fixes #7855. Change-Id: I5b3b4aefe3d1b904541c3350865734d8cbb1c1c4 Reviewed-on: https://go-review.googlesource.com/3420 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
deb6c5b920
commit
99f5f796d9
23
src/net/cgo_resnew.go
Normal file
23
src/net/cgo_resnew.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// +build cgo,!netgo
|
||||||
|
// +build darwin linux solaris
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func cgoNameinfoPTR(b []byte, sa *C.struct_sockaddr, salen C.socklen_t) (int, error) {
|
||||||
|
gerrno, err := C.getnameinfo(sa, salen, (*C.char)(unsafe.Pointer(&b[0])), C.socklen_t(len(b)), nil, 0, C.NI_NAMEREQD)
|
||||||
|
return int(gerrno), err
|
||||||
|
}
|
23
src/net/cgo_resold.go
Normal file
23
src/net/cgo_resold.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// +build cgo,!netgo
|
||||||
|
// +build freebsd dragonfly netbsd openbsd
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func cgoNameinfoPTR(b []byte, sa *C.struct_sockaddr, salen C.socklen_t) (int, error) {
|
||||||
|
gerrno, err := C.getnameinfo(sa, salen, (*C.char)(unsafe.Pointer(&b[0])), C.size_t(len(b)), nil, 0, C.NI_NAMEREQD)
|
||||||
|
return int(gerrno), err
|
||||||
|
}
|
33
src/net/cgo_socknew.go
Normal file
33
src/net/cgo_socknew.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// +build cgo,!netgo
|
||||||
|
// +build android linux solaris
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func cgoSockaddrInet4(ip IP) *C.struct_sockaddr {
|
||||||
|
sa := syscall.RawSockaddrInet4{Family: syscall.AF_INET}
|
||||||
|
copy(sa.Addr[:], ip)
|
||||||
|
return (*C.struct_sockaddr)(unsafe.Pointer(&sa))
|
||||||
|
}
|
||||||
|
|
||||||
|
func cgoSockaddrInet6(ip IP) *C.struct_sockaddr {
|
||||||
|
sa := syscall.RawSockaddrInet6{Family: syscall.AF_INET6}
|
||||||
|
copy(sa.Addr[:], ip)
|
||||||
|
return (*C.struct_sockaddr)(unsafe.Pointer(&sa))
|
||||||
|
}
|
33
src/net/cgo_sockold.go
Normal file
33
src/net/cgo_sockold.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// +build cgo,!netgo
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func cgoSockaddrInet4(ip IP) *C.struct_sockaddr {
|
||||||
|
sa := syscall.RawSockaddrInet4{Len: syscall.SizeofSockaddrInet4, Family: syscall.AF_INET}
|
||||||
|
copy(sa.Addr[:], ip)
|
||||||
|
return (*C.struct_sockaddr)(unsafe.Pointer(&sa))
|
||||||
|
}
|
||||||
|
|
||||||
|
func cgoSockaddrInet6(ip IP) *C.struct_sockaddr {
|
||||||
|
sa := syscall.RawSockaddrInet6{Len: syscall.SizeofSockaddrInet6, Family: syscall.AF_INET6}
|
||||||
|
copy(sa.Addr[:], ip)
|
||||||
|
return (*C.struct_sockaddr)(unsafe.Pointer(&sa))
|
||||||
|
}
|
@ -27,3 +27,7 @@ func cgoLookupIP(name string) (addrs []IPAddr, err error, completed bool) {
|
|||||||
func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
|
func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
|
||||||
return "", nil, false
|
return "", nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cgoLookupPTR(addr string) (ptrs []string, err error, completed bool) {
|
||||||
|
return nil, nil, false
|
||||||
|
}
|
||||||
|
@ -169,6 +169,72 @@ func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These are roughly enough for the following:
|
||||||
|
//
|
||||||
|
// Source Encoding Maximum length of single name entry
|
||||||
|
// Unicast DNS ASCII or <=253 + a NUL terminator
|
||||||
|
// Unicode in RFC 5892 252 * total number of labels + delimiters + a NUL terminator
|
||||||
|
// Multicast DNS UTF-8 in RFC 5198 or <=253 + a NUL terminator
|
||||||
|
// the same as unicast DNS ASCII <=253 + a NUL terminator
|
||||||
|
// Local database various depends on implementation
|
||||||
|
const (
|
||||||
|
nameinfoLen = 64
|
||||||
|
maxNameinfoLen = 4096
|
||||||
|
)
|
||||||
|
|
||||||
|
func cgoLookupPTR(addr string) ([]string, error, bool) {
|
||||||
|
acquireThread()
|
||||||
|
defer releaseThread()
|
||||||
|
|
||||||
|
ip := ParseIP(addr)
|
||||||
|
if ip == nil {
|
||||||
|
return nil, &DNSError{Err: "invalid address", Name: addr}, true
|
||||||
|
}
|
||||||
|
sa, salen := cgoSockaddr(ip)
|
||||||
|
if sa == nil {
|
||||||
|
return nil, &DNSError{Err: "invalid address " + ip.String(), Name: addr}, true
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
var b []byte
|
||||||
|
var gerrno int
|
||||||
|
for l := nameinfoLen; l <= maxNameinfoLen; l *= 2 {
|
||||||
|
b = make([]byte, l)
|
||||||
|
gerrno, err = cgoNameinfoPTR(b, sa, salen)
|
||||||
|
if gerrno == 0 || gerrno != C.EAI_OVERFLOW {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if gerrno != 0 {
|
||||||
|
switch gerrno {
|
||||||
|
case C.EAI_SYSTEM:
|
||||||
|
if err == nil { // see golang.org/issue/6232
|
||||||
|
err = syscall.EMFILE
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = addrinfoErrno(gerrno)
|
||||||
|
}
|
||||||
|
return nil, &DNSError{Err: err.Error(), Name: addr}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(b); i++ {
|
||||||
|
if b[i] == 0 {
|
||||||
|
b = b[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return []string{string(b)}, nil, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func cgoSockaddr(ip IP) (*C.struct_sockaddr, C.socklen_t) {
|
||||||
|
if ip4 := ip.To4(); ip4 != nil {
|
||||||
|
return cgoSockaddrInet4(ip4), C.socklen_t(syscall.SizeofSockaddrInet4)
|
||||||
|
}
|
||||||
|
if ip6 := ip.To16(); ip6 != nil {
|
||||||
|
return cgoSockaddrInet6(ip6), C.socklen_t(syscall.SizeofSockaddrInet6)
|
||||||
|
}
|
||||||
|
return nil, 0
|
||||||
|
}
|
||||||
|
|
||||||
func copyIP(x IP) IP {
|
func copyIP(x IP) IP {
|
||||||
if len(x) < 16 {
|
if len(x) < 16 {
|
||||||
return x.To16()
|
return x.To16()
|
||||||
|
@ -479,3 +479,28 @@ func goLookupCNAME(name string) (cname string, err error) {
|
|||||||
cname = rr[0].(*dnsRR_CNAME).Cname
|
cname = rr[0].(*dnsRR_CNAME).Cname
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// goLookupPTR is the native Go implementation of LookupAddr.
|
||||||
|
// Used only if cgoLookupPTR refuses to handle the request (that is,
|
||||||
|
// only if cgoLookupPTR is the stub in cgo_stub.go).
|
||||||
|
// Normally we let cgo use the C library resolver instead of depending
|
||||||
|
// on our lookup code, so that Go and C get the same answers.
|
||||||
|
func goLookupPTR(addr string) ([]string, error) {
|
||||||
|
names := lookupStaticAddr(addr)
|
||||||
|
if len(names) > 0 {
|
||||||
|
return names, nil
|
||||||
|
}
|
||||||
|
arpa, err := reverseaddr(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, rrs, err := lookup(arpa, dnsTypePTR)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ptrs := make([]string, len(rrs))
|
||||||
|
for i, rr := range rrs {
|
||||||
|
ptrs[i] = rr.(*dnsRR_PTR).Ptr
|
||||||
|
}
|
||||||
|
return ptrs, nil
|
||||||
|
}
|
||||||
|
@ -174,7 +174,7 @@ func TestLookupGmailTXT(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var lookupGooglePublicDNSAddrs = []struct {
|
var lookupGooglePublicDNSAddrTests = []struct {
|
||||||
addr, name string
|
addr, name string
|
||||||
}{
|
}{
|
||||||
{"8.8.8.8", ".google.com"},
|
{"8.8.8.8", ".google.com"},
|
||||||
@ -191,7 +191,7 @@ func TestLookupGooglePublicDNSAddr(t *testing.T) {
|
|||||||
t.Skip("both IPv4 and IPv6 are required")
|
t.Skip("both IPv4 and IPv6 are required")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range lookupGooglePublicDNSAddrs {
|
for _, tt := range lookupGooglePublicDNSAddrTests {
|
||||||
names, err := LookupAddr(tt.addr)
|
names, err := LookupAddr(tt.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -148,21 +148,9 @@ func lookupTXT(name string) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func lookupAddr(addr string) ([]string, error) {
|
func lookupAddr(addr string) ([]string, error) {
|
||||||
names := lookupStaticAddr(addr)
|
ptrs, err, ok := cgoLookupPTR(addr)
|
||||||
if len(names) > 0 {
|
if !ok {
|
||||||
return names, nil
|
ptrs, err = goLookupPTR(addr)
|
||||||
}
|
}
|
||||||
arpa, err := reverseaddr(addr)
|
return ptrs, err
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, rrs, err := lookup(arpa, dnsTypePTR)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ptrs := make([]string, len(rrs))
|
|
||||||
for i, rr := range rrs {
|
|
||||||
ptrs[i] = rr.(*dnsRR_PTR).Ptr
|
|
||||||
}
|
|
||||||
return ptrs, nil
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user