From 6bc69c135c3d3d894c16d75c0127cbdcc9685c83 Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 1 Mar 2019 14:49:52 -0500 Subject: [PATCH 01/36] Add cgo bindings to include the libSystem res_query function and amd64 asm routine Signed-off-by: grant --- src/runtime/sys_darwin.go | 9 +++++++++ src/runtime/sys_darwin_amd64.s | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index f34ac88352465d..34331b68554129 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -381,6 +381,13 @@ func closeonexec(fd int32) { fcntl(fd, _F_SETFD, _FD_CLOEXEC) } +//go:nosplit +//go:cgo_unsafe_args +func res_search(name *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { + return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&name)) +} +func res_search_trampoline() + // Tell the linker that the libc_* functions are to be found // in a system library, with the libc_ prefix missing. @@ -424,6 +431,8 @@ func closeonexec(fd int32) { //go:cgo_import_dynamic libc_pthread_cond_timedwait_relative_np pthread_cond_timedwait_relative_np "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_pthread_cond_signal pthread_cond_signal "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_res_search res_search "/usr/lib/libSystem.B.dylib" + // Magic incantation to get libSystem actually dynamically linked. // TODO: Why does the code require this? See cmd/link/internal/ld/go.go //go:cgo_import_dynamic _ _ "/usr/lib/libSystem.B.dylib" diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s index f99cb00ab8cf09..c92d7c28201a74 100644 --- a/src/runtime/sys_darwin_amd64.s +++ b/src/runtime/sys_darwin_amd64.s @@ -741,3 +741,15 @@ ok: MOVQ BP, SP POPQ BP RET + +TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 + PUSHQ BP + MOVQ SP, BP + MOVL (DI), R8 // arg 5 anslen + MOVQ 16(DI), CX // arg 4 answer + MOVL 8(DI), SI // arg 2 class + MOVQ 12(DI), DX // arg 3 type + MOVQ 0(DI), DI // arg 1 name + CALL libc_res_search(SB) + POPQ BP + RET From 0252e5cb7554b2f0ece4444ac2355a78057a2e31 Mon Sep 17 00:00:00 2001 From: grant Date: Mon, 4 Mar 2019 17:41:50 -0500 Subject: [PATCH 02/36] move bindings to net package Signed-off-by: grant --- src/net/lookup_darwin.go | 35 +++++++++++++++++++++++++++++++++++ src/net/lookup_darwin.s | 15 +++++++++++++++ src/net/lookup_unix.go | 12 +++++++++++- 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/net/lookup_darwin.go create mode 100644 src/net/lookup_darwin.s diff --git a/src/net/lookup_darwin.go b/src/net/lookup_darwin.go new file mode 100644 index 00000000000000..abe015559f588a --- /dev/null +++ b/src/net/lookup_darwin.go @@ -0,0 +1,35 @@ +// Copyright 2009 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 darwin + +package net + +import ( + "context" + "errors" + "unsafe" + + "github.com/golang/go.bkp/src/runtime" +) + +func resSearch(ctx context.Context, hostname string) ([]IPAddr, error) { + + var byteHostname = []byte(hostname) + var responseBuffer = [512]byte{} + retcode := runtime.Res_search(&byteHostname[0], 1, 1, &responseBuffer[0], 512) + if retcode < 0 { + return nil, errors.New("//TODO:") + } + +} + +//go:nosplit +//go:cgo_unsafe_args +func res_search(name *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { + return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&name)) +} +func res_search_trampoline() + +//go:cgo_import_dynamic libc_res_search res_search "/usr/lib/libSystem.B.dylib" diff --git a/src/net/lookup_darwin.s b/src/net/lookup_darwin.s new file mode 100644 index 00000000000000..9173e5658f5f70 --- /dev/null +++ b/src/net/lookup_darwin.s @@ -0,0 +1,15 @@ +// Copyright 2019 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. + +TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 + PUSHQ BP + MOVQ SP, BP + MOVL (DI), R8 // arg 5 anslen + MOVQ 16(DI), CX // arg 4 answer + MOVL 8(DI), SI // arg 2 class + MOVQ 12(DI), DX // arg 3 type + MOVQ 0(DI), DI // arg 1 name + CALL libc_res_search(SB) + POPQ BP + RET diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index 9055826d405c62..8c2bdc36943173 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -9,6 +9,7 @@ package net import ( "context" "internal/bytealg" + "runtime" "sync" "syscall" @@ -81,9 +82,18 @@ func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, if addrs, err, ok := cgoLookupHost(ctx, host); ok { return addrs, err } - // cgo not available (or netgo); fall back to Go's DNS resolver + // cgo not available (or netgo); fall back to linked bindings order = hostLookupFilesDNS } + + // darwin has unique resolution files, use libSystem binding + // even if cgo is disabled. + if runtime.GOOS == "darwin" { + // + + // something went wrong, fallback to Go's DNS resolver + } + return r.goLookupHostOrder(ctx, host, order) } From 5652e61069d77cee4de12a62de1a830cd5bb9c72 Mon Sep 17 00:00:00 2001 From: grant Date: Tue, 5 Mar 2019 17:00:11 -0500 Subject: [PATCH 03/36] Update lookup_darwin.go Signed-off-by: grant --- src/net/lookup_darwin.go | 62 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/src/net/lookup_darwin.go b/src/net/lookup_darwin.go index abe015559f588a..9bc5df40eb13ea 100644 --- a/src/net/lookup_darwin.go +++ b/src/net/lookup_darwin.go @@ -9,20 +9,74 @@ package net import ( "context" "errors" + "fmt" + "strings" "unsafe" - "github.com/golang/go.bkp/src/runtime" + "golang.org/x/net/dns/dnsmessage" ) -func resSearch(ctx context.Context, hostname string) ([]IPAddr, error) { +func resSearch(ctx context.Context, hostname string, rtype, class int32) ([]IPAddr, error) { var byteHostname = []byte(hostname) var responseBuffer = [512]byte{} - retcode := runtime.Res_search(&byteHostname[0], 1, 1, &responseBuffer[0], 512) + + retcode := res_search(&byteHostname[0], class, rtype, &responseBuffer[0], 512) if retcode < 0 { - return nil, errors.New("//TODO:") + return nil, errors.New("could not complete domain resolution") + } + + msg := &dnsmessage.Message{} + err := msg.Unpack(responseBuffer[:]) + if err != nil { + return nil, fmt.Errorf("could not parse dns response: %s", err.Error()) + } + + // parse received answers + var dnsParser dnsmessage.Parser + + if _, err := dnsParser.Start(responseBuffer); err != nil { + return nil, err } + var answers []IPAddr + for { + h, err := dnsParser.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, err + } + + if (h.Type != dnsmessage.TypeA && h.Type != dnsmessage.TypeAAAA) || + h.Class != dnsmessage.ClassINET { + continue + } + + if !strings.EqualFold(h.Name.String(), hostname) { + if err := p.SkipAnswer(); err != nil { + return nil, err + } + continue + } + + switch h.Type { + case dnsmessage.TypeA: + r, err := dnsParser.AResource() + if err != nil { + return nil, err + } + answers = append(answers, IPAddr{IP: r.A[:]}) + case dnsmessage.TypeAAAA: + r, err := dnsParser.AAAAResource() + if err != nil { + return nil, err + } + answers = append(answers, IPAddr{IP: r.AAAA[:]}) + } + } + return answers, nil } //go:nosplit From b26bb0f097ca2d6cd001be1a1a113077ef082bec Mon Sep 17 00:00:00 2001 From: grant Date: Wed, 6 Mar 2019 17:45:06 -0500 Subject: [PATCH 04/36] add res search logic to the actual resolver logic Signed-off-by: grant --- src/net/lookup_unix.go | 108 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 5 deletions(-) diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index 8c2bdc36943173..05c476e2705df5 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -8,10 +8,14 @@ package net import ( "context" + "errors" + "fmt" "internal/bytealg" "runtime" + "strings" "sync" "syscall" + "unsafe" "golang.org/x/net/dns/dnsmessage" ) @@ -86,11 +90,12 @@ func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, order = hostLookupFilesDNS } - // darwin has unique resolution files, use libSystem binding - // even if cgo is disabled. + // darwin has unique resolution files, use libSystem binding if cgo is disabled. if runtime.GOOS == "darwin" { - // - + addrs, err := resSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) + if err == nil { + return addrs, nil + } // something went wrong, fallback to Go's DNS resolver } @@ -106,7 +111,16 @@ func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs [] if addrs, err, ok := cgoLookupIP(ctx, network, host); ok { return addrs, err } - // cgo not available (or netgo); fall back to Go's DNS resolver + + // darwin has unique resolution files, use libSystem binding if cgo is disabled. + if runtime.GOOS == "darwin" { + addrs, err := resSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) + if err == nil { + return addrs, nil + } + // something went wrong, fallback to Go's DNS resolver + } + order = hostLookupFilesDNS } ips, _, err := r.goLookupIPCNAMEOrder(ctx, host, order) @@ -135,6 +149,16 @@ func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) return cname, err } } + + // darwin has unique resolution files, use libSystem binding if cgo is not an option. + if runtime.GOOS == "darwin" { + addrs, err := resSearch(ctx, host, int32(dnsmessage.TypeCNAME), int32(dnsmessage.ClassINET)) + if err == nil { + return addrs, nil + } + // something went wrong, fallback to Go's DNS resolver + } + return r.goLookupCNAME(ctx, name) } @@ -361,3 +385,77 @@ func concurrentThreadsLimit() int { } return r } + +// resSearch is a darwin specific function. It will make a call to the 'res_search' routine in libSystem +// and parse the output as a slice of IPAddr's +func resSearch(ctx context.Context, hostname string, rtype, class int32) ([]string, error) { + + var byteHostname = []byte(hostname) + var responseBuffer = [512]byte{} + + retcode := res_search(&byteHostname[0], class, rtype, &responseBuffer[0], 512) + if retcode < 0 { + return nil, errors.New("could not complete domain resolution") + } + + msg := &dnsmessage.Message{} + err := msg.Unpack(responseBuffer[:]) + if err != nil { + return nil, fmt.Errorf("could not parse dns response: %s", err.Error()) + } + + // parse received answers + var dnsParser dnsmessage.Parser + + if _, err := dnsParser.Start(responseBuffer); err != nil { + return nil, err + } + + var answers []string + for { + h, err := dnsParser.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, err + } + + if (h.Type != dnsmessage.TypeA && h.Type != dnsmessage.TypeAAAA) || + h.Class != dnsmessage.ClassINET { + continue + } + + if !strings.EqualFold(h.Name.String(), hostname) { + if err := p.SkipAnswer(); err != nil { + return nil, err + } + continue + } + + switch h.Type { + case dnsmessage.TypeA: + r, err := dnsParser.AResource() + if err != nil { + return nil, err + } + answers = append(answers, fmt.Strinf("%s", r.A)) + case dnsmessage.TypeAAAA: + r, err := dnsParser.AAAAResource() + if err != nil { + return nil, err + } + answers = append(answers, fmt.Strinf("%s", r.AAAA)) + } + } + return answers, nil +} + +//go:nosplit +//go:cgo_unsafe_args +func res_search(name *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { + return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&name)) +} +func res_search_trampoline() + +//go:cgo_import_dynamic libc_res_search res_search "/usr/lib/libSystem.B.dylib" From ea4ec37a69765abc2c375d4b2e741859e806f4d0 Mon Sep 17 00:00:00 2001 From: grant Date: Wed, 6 Mar 2019 18:02:11 -0500 Subject: [PATCH 05/36] Add reminder for fixing CNAME logic Signed-off-by: grant --- src/net/lookup_unix.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index 05c476e2705df5..ece7d6a3855f8a 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -421,6 +421,7 @@ func resSearch(ctx context.Context, hostname string, rtype, class int32) ([]stri return nil, err } + //FIXME: also need CNAME here? if (h.Type != dnsmessage.TypeA && h.Type != dnsmessage.TypeAAAA) || h.Class != dnsmessage.ClassINET { continue From 61fa16b6b7ea544e20e0e01815c5e1d88f216d61 Mon Sep 17 00:00:00 2001 From: grant Date: Thu, 7 Mar 2019 11:24:19 -0500 Subject: [PATCH 06/36] Remove unneeded check, remove superfluous file Signed-off-by: grant --- src/net/lookup_darwin.go | 89 ---------------------------------------- src/net/lookup_unix.go | 10 +---- 2 files changed, 2 insertions(+), 97 deletions(-) delete mode 100644 src/net/lookup_darwin.go diff --git a/src/net/lookup_darwin.go b/src/net/lookup_darwin.go deleted file mode 100644 index 9bc5df40eb13ea..00000000000000 --- a/src/net/lookup_darwin.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2009 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 darwin - -package net - -import ( - "context" - "errors" - "fmt" - "strings" - "unsafe" - - "golang.org/x/net/dns/dnsmessage" -) - -func resSearch(ctx context.Context, hostname string, rtype, class int32) ([]IPAddr, error) { - - var byteHostname = []byte(hostname) - var responseBuffer = [512]byte{} - - retcode := res_search(&byteHostname[0], class, rtype, &responseBuffer[0], 512) - if retcode < 0 { - return nil, errors.New("could not complete domain resolution") - } - - msg := &dnsmessage.Message{} - err := msg.Unpack(responseBuffer[:]) - if err != nil { - return nil, fmt.Errorf("could not parse dns response: %s", err.Error()) - } - - // parse received answers - var dnsParser dnsmessage.Parser - - if _, err := dnsParser.Start(responseBuffer); err != nil { - return nil, err - } - - var answers []IPAddr - for { - h, err := dnsParser.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, err - } - - if (h.Type != dnsmessage.TypeA && h.Type != dnsmessage.TypeAAAA) || - h.Class != dnsmessage.ClassINET { - continue - } - - if !strings.EqualFold(h.Name.String(), hostname) { - if err := p.SkipAnswer(); err != nil { - return nil, err - } - continue - } - - switch h.Type { - case dnsmessage.TypeA: - r, err := dnsParser.AResource() - if err != nil { - return nil, err - } - answers = append(answers, IPAddr{IP: r.A[:]}) - case dnsmessage.TypeAAAA: - r, err := dnsParser.AAAAResource() - if err != nil { - return nil, err - } - answers = append(answers, IPAddr{IP: r.AAAA[:]}) - } - } - return answers, nil -} - -//go:nosplit -//go:cgo_unsafe_args -func res_search(name *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { - return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&name)) -} -func res_search_trampoline() - -//go:cgo_import_dynamic libc_res_search res_search "/usr/lib/libSystem.B.dylib" diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index ece7d6a3855f8a..3dc8c29c9adc39 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -386,9 +386,9 @@ func concurrentThreadsLimit() int { return r } -// resSearch is a darwin specific function. It will make a call to the 'res_search' routine in libSystem +// resolverSearch is a darwin specific function. It will make a call to the 'res_search' routine in libSystem // and parse the output as a slice of IPAddr's -func resSearch(ctx context.Context, hostname string, rtype, class int32) ([]string, error) { +func resolverSearch(ctx context.Context, hostname string, rtype, class int32) ([]string, error) { var byteHostname = []byte(hostname) var responseBuffer = [512]byte{} @@ -421,12 +421,6 @@ func resSearch(ctx context.Context, hostname string, rtype, class int32) ([]stri return nil, err } - //FIXME: also need CNAME here? - if (h.Type != dnsmessage.TypeA && h.Type != dnsmessage.TypeAAAA) || - h.Class != dnsmessage.ClassINET { - continue - } - if !strings.EqualFold(h.Name.String(), hostname) { if err := p.SkipAnswer(); err != nil { return nil, err From c38ac967fe6d955e25a773d088277ec7e2a335fb Mon Sep 17 00:00:00 2001 From: grant Date: Thu, 7 Mar 2019 16:56:59 -0500 Subject: [PATCH 07/36] Make sure we can query CNAME's Signed-off-by: grant --- src/net/lookup_unix.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index 3dc8c29c9adc39..5b0bce1e50a3c1 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -405,7 +405,7 @@ func resolverSearch(ctx context.Context, hostname string, rtype, class int32) ([ } // parse received answers - var dnsParser dnsmessage.Parser + var dnsParser dnsmessage.Parserw if _, err := dnsParser.Start(responseBuffer); err != nil { return nil, err @@ -441,6 +441,13 @@ func resolverSearch(ctx context.Context, hostname string, rtype, class int32) ([ return nil, err } answers = append(answers, fmt.Strinf("%s", r.AAAA)) + + case dnsmessage.TypeCNAME: + r, err := dnsParser.CNAMEResource() + if err != nil { + return nil, err + } + answers = append(answers, fmt.Strinf("%s", r.Name)) } } return answers, nil From 1dc855b9dba3bfb68acd4cb222be3088a64e8d04 Mon Sep 17 00:00:00 2001 From: grant Date: Thu, 7 Mar 2019 18:22:11 -0500 Subject: [PATCH 08/36] seperate out x86_64 and 32 bit assembly Signed-off-by: grant --- src/net/lookup_darwin_386.s | 27 +++++++++++++++++++ ...{lookup_darwin.s => lookup_darwin_amd64.s} | 4 +++ 2 files changed, 31 insertions(+) create mode 100644 src/net/lookup_darwin_386.s rename src/net/{lookup_darwin.s => lookup_darwin_amd64.s} (87%) diff --git a/src/net/lookup_darwin_386.s b/src/net/lookup_darwin_386.s new file mode 100644 index 00000000000000..02090f9e0e1726 --- /dev/null +++ b/src/net/lookup_darwin_386.s @@ -0,0 +1,27 @@ +// Copyright 2019 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. + +#include "go_asm.h" +#include "go_tls.h" +#include "textflag.h" + +TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 + PUSHL BP + MOVL SP, BP + SUBL $24, SP + MOVL 32(SP), CX + MOVL 16(CX), AX // arg 5 anslen + MOVL AX, 16(SP) + MOVL 12(CX), AX // arg 4 answer + MOVL AX, 12(SP) + MOVL 4(CX), AX // arg 2 class + MOVL AX, 4(SP) + MOVL 8(CX), AX // arg 3 type + MOVL AX, 8(SP) + MOVL 0(CX), AX // arg 1 name + MOVL AX, 0(SP) + CALL libc_res_search(SB) + MOVL BP, SP + POPL BP + RET diff --git a/src/net/lookup_darwin.s b/src/net/lookup_darwin_amd64.s similarity index 87% rename from src/net/lookup_darwin.s rename to src/net/lookup_darwin_amd64.s index 9173e5658f5f70..b699108b8e88b7 100644 --- a/src/net/lookup_darwin.s +++ b/src/net/lookup_darwin_amd64.s @@ -2,6 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +#include "go_asm.h" +#include "go_tls.h" +#include "textflag.h" + TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 PUSHQ BP MOVQ SP, BP From a438a8e6261f9e09a6123fdca6ab5bd7ab68c48f Mon Sep 17 00:00:00 2001 From: grant Date: Thu, 7 Mar 2019 18:22:55 -0500 Subject: [PATCH 09/36] Remove res_search from runtime package Signed-off-by: grant --- src/runtime/sys_darwin.go | 9 --------- src/runtime/sys_darwin_amd64.s | 12 ------------ 2 files changed, 21 deletions(-) diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index 34331b68554129..f34ac88352465d 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -381,13 +381,6 @@ func closeonexec(fd int32) { fcntl(fd, _F_SETFD, _FD_CLOEXEC) } -//go:nosplit -//go:cgo_unsafe_args -func res_search(name *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { - return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&name)) -} -func res_search_trampoline() - // Tell the linker that the libc_* functions are to be found // in a system library, with the libc_ prefix missing. @@ -431,8 +424,6 @@ func res_search_trampoline() //go:cgo_import_dynamic libc_pthread_cond_timedwait_relative_np pthread_cond_timedwait_relative_np "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_pthread_cond_signal pthread_cond_signal "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_res_search res_search "/usr/lib/libSystem.B.dylib" - // Magic incantation to get libSystem actually dynamically linked. // TODO: Why does the code require this? See cmd/link/internal/ld/go.go //go:cgo_import_dynamic _ _ "/usr/lib/libSystem.B.dylib" diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s index c92d7c28201a74..f99cb00ab8cf09 100644 --- a/src/runtime/sys_darwin_amd64.s +++ b/src/runtime/sys_darwin_amd64.s @@ -741,15 +741,3 @@ ok: MOVQ BP, SP POPQ BP RET - -TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 - PUSHQ BP - MOVQ SP, BP - MOVL (DI), R8 // arg 5 anslen - MOVQ 16(DI), CX // arg 4 answer - MOVL 8(DI), SI // arg 2 class - MOVQ 12(DI), DX // arg 3 type - MOVQ 0(DI), DI // arg 1 name - CALL libc_res_search(SB) - POPQ BP - RET From 534863c8948552cbcba4693dabed7d98f8963b78 Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 8 Mar 2019 11:04:05 -0500 Subject: [PATCH 10/36] fix formatting Signed-off-by: grant --- src/net/lookup_darwin_386.s | 4 ++-- src/test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 src/test.go diff --git a/src/net/lookup_darwin_386.s b/src/net/lookup_darwin_386.s index 02090f9e0e1726..c95d71879354ff 100644 --- a/src/net/lookup_darwin_386.s +++ b/src/net/lookup_darwin_386.s @@ -9,8 +9,8 @@ TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 PUSHL BP MOVL SP, BP - SUBL $24, SP - MOVL 32(SP), CX + SUBL $24, SP + MOVL 32(SP), CX MOVL 16(CX), AX // arg 5 anslen MOVL AX, 16(SP) MOVL 12(CX), AX // arg 4 answer diff --git a/src/test.go b/src/test.go new file mode 100644 index 00000000000000..9829213253f807 --- /dev/null +++ b/src/test.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "os" + "runtime" + + "golang.org/x/net/dns/dnsmessage" +) + +func main() { + + name := []byte(os.Args[1]) + + var buffer = [512]byte{} + ret := runtime.Res_search(&name[0], 1, 1, &buffer[0], 512) + if ret != 0 { + fmt.Println(ret) + } + + bufferSlice := buffer[:] + + msg := &dnsmessage.Message{} + + err := msg.Unpack(bufferSlice) + if err != nil { + fmt.Println(err) + } + + fmt.Println("\n\n\n\n") + fmt.Println(msg.Answers[0].Body) +} From 6fb0200dd476ddba23882d24242d93c6f547e79f Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 8 Mar 2019 11:12:04 -0500 Subject: [PATCH 11/36] Remove accidentally added demo file Signed-off-by: grant --- src/test.go | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 src/test.go diff --git a/src/test.go b/src/test.go deleted file mode 100644 index 9829213253f807..00000000000000 --- a/src/test.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "fmt" - "os" - "runtime" - - "golang.org/x/net/dns/dnsmessage" -) - -func main() { - - name := []byte(os.Args[1]) - - var buffer = [512]byte{} - ret := runtime.Res_search(&name[0], 1, 1, &buffer[0], 512) - if ret != 0 { - fmt.Println(ret) - } - - bufferSlice := buffer[:] - - msg := &dnsmessage.Message{} - - err := msg.Unpack(bufferSlice) - if err != nil { - fmt.Println(err) - } - - fmt.Println("\n\n\n\n") - fmt.Println(msg.Answers[0].Body) -} From 82fd805941ec88985310b83e9b7113c64b1e944a Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 8 Mar 2019 12:22:17 -0500 Subject: [PATCH 12/36] Fix inconsistent whitespace in assembly files Signed-off-by: grant --- src/net/lookup_darwin_386.s | 4 ++-- src/net/lookup_darwin_amd64.s | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/net/lookup_darwin_386.s b/src/net/lookup_darwin_386.s index c95d71879354ff..0da820c5fafd59 100644 --- a/src/net/lookup_darwin_386.s +++ b/src/net/lookup_darwin_386.s @@ -17,8 +17,8 @@ TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 MOVL AX, 12(SP) MOVL 4(CX), AX // arg 2 class MOVL AX, 4(SP) - MOVL 8(CX), AX // arg 3 type - MOVL AX, 8(SP) + MOVL 8(CX), AX // arg 3 type + MOVL AX, 8(SP) MOVL 0(CX), AX // arg 1 name MOVL AX, 0(SP) CALL libc_res_search(SB) diff --git a/src/net/lookup_darwin_amd64.s b/src/net/lookup_darwin_amd64.s index b699108b8e88b7..321fc0059b81be 100644 --- a/src/net/lookup_darwin_amd64.s +++ b/src/net/lookup_darwin_amd64.s @@ -7,13 +7,13 @@ #include "textflag.h" TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 - PUSHQ BP - MOVQ SP, BP - MOVL (DI), R8 // arg 5 anslen - MOVQ 16(DI), CX // arg 4 answer - MOVL 8(DI), SI // arg 2 class - MOVQ 12(DI), DX // arg 3 type - MOVQ 0(DI), DI // arg 1 name - CALL libc_res_search(SB) - POPQ BP - RET + PUSHQ BP + MOVQ SP, BP + MOVL (DI), R8 // arg 5 anslen + MOVQ 16(DI), CX // arg 4 answer + MOVL 8(DI), SI // arg 2 class + MOVQ 12(DI), DX // arg 3 type + MOVQ 0(DI), DI // arg 1 name + CALL libc_res_search(SB) + POPQ BP + RET From f36b06550d61e726aec01557478fcab37c53e65c Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 8 Mar 2019 13:11:04 -0500 Subject: [PATCH 13/36] Add back wrongly removed arg offset Signed-off-by: grant --- src/net/lookup_darwin_amd64.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/net/lookup_darwin_amd64.s b/src/net/lookup_darwin_amd64.s index 321fc0059b81be..80f6858ed69c98 100644 --- a/src/net/lookup_darwin_amd64.s +++ b/src/net/lookup_darwin_amd64.s @@ -7,9 +7,9 @@ #include "textflag.h" TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 - PUSHQ BP + PUSHQ BP MOVQ SP, BP - MOVL (DI), R8 // arg 5 anslen + MOVL 24(DI), R8 // arg 5 anslen MOVQ 16(DI), CX // arg 4 answer MOVL 8(DI), SI // arg 2 class MOVQ 12(DI), DX // arg 3 type From ed3ed8da9356f4c2a541a7b2ad10baf916d7f7fc Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 8 Mar 2019 13:38:16 -0500 Subject: [PATCH 14/36] add arm bindings for res_search Signed-off-by: grant --- src/net/lookup_darwin_arm.s | 20 ++++++++++++++++++++ src/net/lookup_darwin_arm64.s | 17 +++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 src/net/lookup_darwin_arm.s create mode 100644 src/net/lookup_darwin_arm64.s diff --git a/src/net/lookup_darwin_arm.s b/src/net/lookup_darwin_arm.s new file mode 100644 index 00000000000000..952eb02015921b --- /dev/null +++ b/src/net/lookup_darwin_arm.s @@ -0,0 +1,20 @@ +// 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. + +// System calls and other sys.stuff for ARM64, Darwin +// System calls are implemented in libSystem, this file contains +// trampolines that convert from Go to C calling convention. + +#include "go_asm.h" +#include "go_tls.h" +#include "textflag.h" + +TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 + MOVW 16(R0). R4 // arg 5 anslen + MOVW 12(R0), R3 // arg 4 answer + MOVW 4(R0), R1 // arg 2 class + MOVW 8(R0), R2 // arg 3 type + MOVW 0(R0), R0 // arg 1 name + BL libc_res_search + RET \ No newline at end of file diff --git a/src/net/lookup_darwin_arm64.s b/src/net/lookup_darwin_arm64.s new file mode 100644 index 00000000000000..8cfee1e6c72ef6 --- /dev/null +++ b/src/net/lookup_darwin_arm64.s @@ -0,0 +1,17 @@ +// Copyright 2019 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. + +#include "go_asm.h" +#include "go_tls.h" +#include "textflag.h" + +TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 + SUB $16, RSP + MOVW 24(R0), R4 // arg 5 anslen + MOVD 16(R0), R3 // arg 4 answer + MOVW 8(R0), R1 // arg 2 class + MOVD 12(R0), R2 // arg 3 type + MOVD 0(R0), R0 // arg 1 name + BL libc_res_search(SB) + RET \ No newline at end of file From 834f4b35da9f18dce66d31ec540194d734a6c68e Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 8 Mar 2019 15:52:19 -0500 Subject: [PATCH 15/36] Replace arm routines with stubs Signed-off-by: grant --- src/net/lookup_darwin_arm.s | 14 +++++++------- src/net/lookup_darwin_arm64.s | 15 +++++++-------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/net/lookup_darwin_arm.s b/src/net/lookup_darwin_arm.s index 952eb02015921b..15ae2c6d90eae9 100644 --- a/src/net/lookup_darwin_arm.s +++ b/src/net/lookup_darwin_arm.s @@ -10,11 +10,11 @@ #include "go_tls.h" #include "textflag.h" +// On darwin/arm, the runtime always use runtime/cgo +// for resolution. This will just exit with nominal +// exit code + TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 - MOVW 16(R0). R4 // arg 5 anslen - MOVW 12(R0), R3 // arg 4 answer - MOVW 4(R0), R1 // arg 2 class - MOVW 8(R0), R2 // arg 3 type - MOVW 0(R0), R0 // arg 1 name - BL libc_res_search - RET \ No newline at end of file + MOVW $98, R0 + BL libc_exit(SB) + RET diff --git a/src/net/lookup_darwin_arm64.s b/src/net/lookup_darwin_arm64.s index 8cfee1e6c72ef6..92e34a30ee6e69 100644 --- a/src/net/lookup_darwin_arm64.s +++ b/src/net/lookup_darwin_arm64.s @@ -6,12 +6,11 @@ #include "go_tls.h" #include "textflag.h" +// On darwin/arm, the runtime always use runtime/cgo +// for resolution. This will just exit with nominal +// exit code + TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 - SUB $16, RSP - MOVW 24(R0), R4 // arg 5 anslen - MOVD 16(R0), R3 // arg 4 answer - MOVW 8(R0), R1 // arg 2 class - MOVD 12(R0), R2 // arg 3 type - MOVD 0(R0), R0 // arg 1 name - BL libc_res_search(SB) - RET \ No newline at end of file + MOVW $1, R0 + BL libc_exit(SB) + RET From edbad08398f70ecbb06431e1854bb26182932aed Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 8 Mar 2019 16:13:56 -0500 Subject: [PATCH 16/36] Fix first set of undefined errors... Signed-off-by: grant --- src/net/lookup_unix.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index 5b0bce1e50a3c1..5fdc4378306339 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -92,7 +92,7 @@ func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, // darwin has unique resolution files, use libSystem binding if cgo is disabled. if runtime.GOOS == "darwin" { - addrs, err := resSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) + addrs, err := resolverSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) if err == nil { return addrs, nil } @@ -114,7 +114,7 @@ func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs [] // darwin has unique resolution files, use libSystem binding if cgo is disabled. if runtime.GOOS == "darwin" { - addrs, err := resSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) + addrs, err := resolverSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) if err == nil { return addrs, nil } @@ -152,7 +152,7 @@ func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) // darwin has unique resolution files, use libSystem binding if cgo is not an option. if runtime.GOOS == "darwin" { - addrs, err := resSearch(ctx, host, int32(dnsmessage.TypeCNAME), int32(dnsmessage.ClassINET)) + addrs, err := resolverSearch(ctx, name, int32(dnsmessage.TypeCNAME), int32(dnsmessage.ClassINET)) if err == nil { return addrs, nil } @@ -405,7 +405,7 @@ func resolverSearch(ctx context.Context, hostname string, rtype, class int32) ([ } // parse received answers - var dnsParser dnsmessage.Parserw + var dnsParser dnsmessage.Parser if _, err := dnsParser.Start(responseBuffer); err != nil { return nil, err @@ -422,7 +422,7 @@ func resolverSearch(ctx context.Context, hostname string, rtype, class int32) ([ } if !strings.EqualFold(h.Name.String(), hostname) { - if err := p.SkipAnswer(); err != nil { + if err := dnsParser.SkipAnswer(); err != nil { return nil, err } continue @@ -434,20 +434,20 @@ func resolverSearch(ctx context.Context, hostname string, rtype, class int32) ([ if err != nil { return nil, err } - answers = append(answers, fmt.Strinf("%s", r.A)) + answers = append(answers, fmt.Stringf("%s", r.A)) case dnsmessage.TypeAAAA: r, err := dnsParser.AAAAResource() if err != nil { return nil, err } - answers = append(answers, fmt.Strinf("%s", r.AAAA)) + answers = append(answers, fmt.Stringf("%s", r.AAAA)) case dnsmessage.TypeCNAME: r, err := dnsParser.CNAMEResource() if err != nil { return nil, err } - answers = append(answers, fmt.Strinf("%s", r.Name)) + answers = append(answers, fmt.Stringf("%s", r.Name)) } } return answers, nil From 5597c4504bce5c3a1338e80e9a33bcfbc850aa24 Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 8 Mar 2019 17:28:33 -0500 Subject: [PATCH 17/36] Create unique lookup file in net for darwin, move libSystem bindings for res_search into runtime package Signed-off-by: grant --- src/net/lookup_darwin.go | 376 +++++++++++++++++++++ src/net/lookup_unix.go | 116 +------ src/runtime/lookup_darwin.go | 86 +++++ src/{net => runtime}/lookup_darwin_386.s | 0 src/{net => runtime}/lookup_darwin_amd64.s | 0 src/{net => runtime}/lookup_darwin_arm.s | 0 src/{net => runtime}/lookup_darwin_arm64.s | 0 7 files changed, 465 insertions(+), 113 deletions(-) create mode 100644 src/net/lookup_darwin.go create mode 100644 src/runtime/lookup_darwin.go rename src/{net => runtime}/lookup_darwin_386.s (100%) rename src/{net => runtime}/lookup_darwin_amd64.s (100%) rename src/{net => runtime}/lookup_darwin_arm.s (100%) rename src/{net => runtime}/lookup_darwin_arm64.s (100%) diff --git a/src/net/lookup_darwin.go b/src/net/lookup_darwin.go new file mode 100644 index 00000000000000..5c6175ee93462b --- /dev/null +++ b/src/net/lookup_darwin.go @@ -0,0 +1,376 @@ +// Copyright 2011 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 darwin + +package net + +import ( + "context" + "internal/bytealg" + "sync" + "syscall" + + "internal/x/net/dns/dnsmessage" +) + +var onceReadProtocols sync.Once + +// readProtocols loads contents of /etc/protocols into protocols map +// for quick access. +func readProtocols() { + file, err := open("/etc/protocols") + if err != nil { + return + } + defer file.close() + + for line, ok := file.readLine(); ok; line, ok = file.readLine() { + // tcp 6 TCP # transmission control protocol + if i := bytealg.IndexByteString(line, '#'); i >= 0 { + line = line[0:i] + } + f := getFields(line) + if len(f) < 2 { + continue + } + if proto, _, ok := dtoi(f[1]); ok { + if _, ok := protocols[f[0]]; !ok { + protocols[f[0]] = proto + } + for _, alias := range f[2:] { + if _, ok := protocols[alias]; !ok { + protocols[alias] = proto + } + } + } + } +} + +// lookupProtocol looks up IP protocol name in /etc/protocols and +// returns correspondent protocol number. +func lookupProtocol(_ context.Context, name string) (int, error) { + onceReadProtocols.Do(readProtocols) + return lookupProtocolMap(name) +} + +func (r *Resolver) dial(ctx context.Context, network, server string) (Conn, error) { + // Calling Dial here is scary -- we have to be sure not to + // dial a name that will require a DNS lookup, or Dial will + // call back here to translate it. The DNS config parser has + // already checked that all the cfg.servers are IP + // addresses, which Dial will use without a DNS lookup. + var c Conn + var err error + if r != nil && r.Dial != nil { + c, err = r.Dial(ctx, network, server) + } else { + var d Dialer + c, err = d.DialContext(ctx, network, server) + } + if err != nil { + return nil, mapErr(err) + } + return c, nil +} + +func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) { + order := systemConf().hostLookupOrder(r, host) + if !r.preferGo() && order == hostLookupCgo { + if addrs, err, ok := cgoLookupHost(ctx, host); ok { + return addrs, err + } + // cgo not available (or netgo); fall back to linked bindings + order = hostLookupFilesDNS + } + + // darwin has unique resolution files, use libSystem binding if cgo is disabled. + addrs, err := resolverSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) + if err == nil { + return addrs, nil + } + // something went wrong, fallback to Go's DNS resolver + + return r.goLookupHostOrder(ctx, host, order) +} + +func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs []IPAddr, err error) { + if r.preferGo() { + return r.goLookupIP(ctx, host) + } + order := systemConf().hostLookupOrder(r, host) + if order == hostLookupCgo { + if addrs, err, ok := cgoLookupIP(ctx, network, host); ok { + return addrs, err + } + + // darwin has unique resolution files, use libSystem binding if cgo is disabled. + addrs, err := resolverSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) + if err == nil { + return addrs, nil + } + // something went wrong, fallback to Go's DNS resolver + + order = hostLookupFilesDNS + } + ips, _, err := r.goLookupIPCNAMEOrder(ctx, host, order) + return ips, err +} + +func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) { + if !r.preferGo() && systemConf().canUseCgo() { + if port, err, ok := cgoLookupPort(ctx, network, service); ok { + if err != nil { + // Issue 18213: if cgo fails, first check to see whether we + // have the answer baked-in to the net package. + if port, err := goLookupPort(network, service); err == nil { + return port, nil + } + } + return port, err + } + } + return goLookupPort(network, service) +} + +func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) { + if !r.preferGo() && systemConf().canUseCgo() { + if cname, err, ok := cgoLookupCNAME(ctx, name); ok { + return cname, err + } + } + + // darwin has unique resolution files, use libSystem binding if cgo is not an option. + addrs, err := resolverSearch(ctx, name, int32(dnsmessage.TypeCNAME), int32(dnsmessage.ClassINET)) + if err == nil { + return addrs, nil + } + + // something went wrong, fallback to Go's DNS resolver + return r.goLookupCNAME(ctx, name) +} + +func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { + var target string + if service == "" && proto == "" { + target = name + } else { + target = "_" + service + "._" + proto + "." + name + } + p, server, err := r.lookup(ctx, target, dnsmessage.TypeSRV) + if err != nil { + return "", nil, err + } + var srvs []*SRV + var cname dnsmessage.Name + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return "", nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeSRV { + if err := p.SkipAnswer(); err != nil { + return "", nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + if cname.Length == 0 && h.Name.Length != 0 { + cname = h.Name + } + srv, err := p.SRVResource() + if err != nil { + return "", nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + srvs = append(srvs, &SRV{Target: srv.Target.String(), Port: srv.Port, Priority: srv.Priority, Weight: srv.Weight}) + } + byPriorityWeight(srvs).sort() + return cname.String(), srvs, nil +} + +func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { + p, server, err := r.lookup(ctx, name, dnsmessage.TypeMX) + if err != nil { + return nil, err + } + var mxs []*MX + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeMX { + if err := p.SkipAnswer(); err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + mx, err := p.MXResource() + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + mxs = append(mxs, &MX{Host: mx.MX.String(), Pref: mx.Pref}) + + } + byPref(mxs).sort() + return mxs, nil +} + +func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { + p, server, err := r.lookup(ctx, name, dnsmessage.TypeNS) + if err != nil { + return nil, err + } + var nss []*NS + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeNS { + if err := p.SkipAnswer(); err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + ns, err := p.NSResource() + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + nss = append(nss, &NS{Host: ns.NS.String()}) + } + return nss, nil +} + +func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) { + p, server, err := r.lookup(ctx, name, dnsmessage.TypeTXT) + if err != nil { + return nil, err + } + var txts []string + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeTXT { + if err := p.SkipAnswer(); err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + txt, err := p.TXTResource() + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + // Multiple strings in one TXT record need to be + // concatenated without separator to be consistent + // with previous Go resolver. + n := 0 + for _, s := range txt.TXT { + n += len(s) + } + txtJoin := make([]byte, 0, n) + for _, s := range txt.TXT { + txtJoin = append(txtJoin, s...) + } + if len(txts) == 0 { + txts = make([]string, 0, 1) + } + txts = append(txts, string(txtJoin)) + } + return txts, nil +} + +func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) { + if !r.preferGo() && systemConf().canUseCgo() { + if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok { + return ptrs, err + } + } + return r.goLookupPTR(ctx, addr) +} + +// concurrentThreadsLimit returns the number of threads we permit to +// run concurrently doing DNS lookups via cgo. A DNS lookup may use a +// file descriptor so we limit this to less than the number of +// permitted open files. On some systems, notably Darwin, if +// getaddrinfo is unable to open a file descriptor it simply returns +// EAI_NONAME rather than a useful error. Limiting the number of +// concurrent getaddrinfo calls to less than the permitted number of +// file descriptors makes that error less likely. We don't bother to +// apply the same limit to DNS lookups run directly from Go, because +// there we will return a meaningful "too many open files" error. +func concurrentThreadsLimit() int { + var rlim syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil { + return 500 + } + r := int(rlim.Cur) + if r > 500 { + r = 500 + } else if r > 30 { + r -= 30 + } + return r +} diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index 5fdc4378306339..f57fdc4ea28453 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -2,20 +2,15 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +// +build aix dragonfly freebsd linux netbsd openbsd solaris package net import ( "context" - "errors" - "fmt" "internal/bytealg" - "runtime" - "strings" "sync" "syscall" - "unsafe" "golang.org/x/net/dns/dnsmessage" ) @@ -86,19 +81,9 @@ func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, if addrs, err, ok := cgoLookupHost(ctx, host); ok { return addrs, err } - // cgo not available (or netgo); fall back to linked bindings + // cgo not available (or netgo); fall back to Go's DNS resolver order = hostLookupFilesDNS } - - // darwin has unique resolution files, use libSystem binding if cgo is disabled. - if runtime.GOOS == "darwin" { - addrs, err := resolverSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) - if err == nil { - return addrs, nil - } - // something went wrong, fallback to Go's DNS resolver - } - return r.goLookupHostOrder(ctx, host, order) } @@ -111,16 +96,7 @@ func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs [] if addrs, err, ok := cgoLookupIP(ctx, network, host); ok { return addrs, err } - - // darwin has unique resolution files, use libSystem binding if cgo is disabled. - if runtime.GOOS == "darwin" { - addrs, err := resolverSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) - if err == nil { - return addrs, nil - } - // something went wrong, fallback to Go's DNS resolver - } - + // cgo not available (or netgo); fall back to Go's DNS resolver order = hostLookupFilesDNS } ips, _, err := r.goLookupIPCNAMEOrder(ctx, host, order) @@ -149,16 +125,6 @@ func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) return cname, err } } - - // darwin has unique resolution files, use libSystem binding if cgo is not an option. - if runtime.GOOS == "darwin" { - addrs, err := resolverSearch(ctx, name, int32(dnsmessage.TypeCNAME), int32(dnsmessage.ClassINET)) - if err == nil { - return addrs, nil - } - // something went wrong, fallback to Go's DNS resolver - } - return r.goLookupCNAME(ctx, name) } @@ -385,79 +351,3 @@ func concurrentThreadsLimit() int { } return r } - -// resolverSearch is a darwin specific function. It will make a call to the 'res_search' routine in libSystem -// and parse the output as a slice of IPAddr's -func resolverSearch(ctx context.Context, hostname string, rtype, class int32) ([]string, error) { - - var byteHostname = []byte(hostname) - var responseBuffer = [512]byte{} - - retcode := res_search(&byteHostname[0], class, rtype, &responseBuffer[0], 512) - if retcode < 0 { - return nil, errors.New("could not complete domain resolution") - } - - msg := &dnsmessage.Message{} - err := msg.Unpack(responseBuffer[:]) - if err != nil { - return nil, fmt.Errorf("could not parse dns response: %s", err.Error()) - } - - // parse received answers - var dnsParser dnsmessage.Parser - - if _, err := dnsParser.Start(responseBuffer); err != nil { - return nil, err - } - - var answers []string - for { - h, err := dnsParser.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, err - } - - if !strings.EqualFold(h.Name.String(), hostname) { - if err := dnsParser.SkipAnswer(); err != nil { - return nil, err - } - continue - } - - switch h.Type { - case dnsmessage.TypeA: - r, err := dnsParser.AResource() - if err != nil { - return nil, err - } - answers = append(answers, fmt.Stringf("%s", r.A)) - case dnsmessage.TypeAAAA: - r, err := dnsParser.AAAAResource() - if err != nil { - return nil, err - } - answers = append(answers, fmt.Stringf("%s", r.AAAA)) - - case dnsmessage.TypeCNAME: - r, err := dnsParser.CNAMEResource() - if err != nil { - return nil, err - } - answers = append(answers, fmt.Stringf("%s", r.Name)) - } - } - return answers, nil -} - -//go:nosplit -//go:cgo_unsafe_args -func res_search(name *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { - return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&name)) -} -func res_search_trampoline() - -//go:cgo_import_dynamic libc_res_search res_search "/usr/lib/libSystem.B.dylib" diff --git a/src/runtime/lookup_darwin.go b/src/runtime/lookup_darwin.go new file mode 100644 index 00000000000000..388ac13874d401 --- /dev/null +++ b/src/runtime/lookup_darwin.go @@ -0,0 +1,86 @@ +package runtime + +import ( + "context" + "errors" + "strings" + "unsafe" + + "internal/x/net/dns/dnsmessage" +) + +// ResolverSearch is a darwin specific function. It will make a call to the 'res_search' routine in libSystem +// and parse the output as a slice of IPAddr's +func ResolverSearch(ctx context.Context, hostname string, rtype, class int32) ([]string, error) { + + var byteHostname = []byte(hostname) + var responseBuffer = [512]byte{} + + retcode := res_search(&byteHostname[0], class, rtype, &responseBuffer[0], 512) + if retcode < 0 { + return nil, errors.New("could not complete domain resolution") + } + + msg := &dnsmessage.Message{} + err := msg.Unpack(responseBuffer[:]) + if err != nil { + return nil, fmt.Errorf("could not parse dns response: %s", err.Error()) + } + + // parse received answers + var dnsParser dnsmessage.Parser + + if _, err := dnsParser.Start(responseBuffer); err != nil { + return nil, err + } + + var answers []string + for { + h, err := dnsParser.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, err + } + + if !strings.EqualFold(h.Name.String(), hostname) { + if err := dnsParser.SkipAnswer(); err != nil { + return nil, err + } + continue + } + + switch h.Type { + case dnsmessage.TypeA: + r, err := dnsParser.AResource() + if err != nil { + return nil, err + } + answers = append(answers, fmt.Stringf("%s", r.A)) + case dnsmessage.TypeAAAA: + r, err := dnsParser.AAAAResource() + if err != nil { + return nil, err + } + answers = append(answers, fmt.Stringf("%s", r.AAAA)) + + case dnsmessage.TypeCNAME: + r, err := dnsParser.CNAMEResource() + if err != nil { + return nil, err + } + answers = append(answers, fmt.Stringf("%s", r.Name)) + } + } + return answers, nil +} + +//go:nosplit +//go:cgo_unsafe_args +func res_search(name *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { + return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&name)) +} +func res_search_trampoline() + +//go:cgo_import_dynamic libc_res_search res_search "/usr/lib/libSystem.B.dylib" diff --git a/src/net/lookup_darwin_386.s b/src/runtime/lookup_darwin_386.s similarity index 100% rename from src/net/lookup_darwin_386.s rename to src/runtime/lookup_darwin_386.s diff --git a/src/net/lookup_darwin_amd64.s b/src/runtime/lookup_darwin_amd64.s similarity index 100% rename from src/net/lookup_darwin_amd64.s rename to src/runtime/lookup_darwin_amd64.s diff --git a/src/net/lookup_darwin_arm.s b/src/runtime/lookup_darwin_arm.s similarity index 100% rename from src/net/lookup_darwin_arm.s rename to src/runtime/lookup_darwin_arm.s diff --git a/src/net/lookup_darwin_arm64.s b/src/runtime/lookup_darwin_arm64.s similarity index 100% rename from src/net/lookup_darwin_arm64.s rename to src/runtime/lookup_darwin_arm64.s From 931c26b1e0657bfdf07a0d85a19a76c68676c008 Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 8 Mar 2019 17:39:06 -0500 Subject: [PATCH 18/36] Remove redundant build tag Signed-off-by: grant --- src/net/lookup_darwin.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/net/lookup_darwin.go b/src/net/lookup_darwin.go index 5c6175ee93462b..28d2b0c2672c81 100644 --- a/src/net/lookup_darwin.go +++ b/src/net/lookup_darwin.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin - package net import ( From 88fb0bc15b969cc4225731c0b1b4a26174066070 Mon Sep 17 00:00:00 2001 From: grant Date: Sat, 9 Mar 2019 16:50:24 -0500 Subject: [PATCH 19/36] Move the res_search function to runtime package while linking in net Signed-off-by: grant --- src/net/lookup_darwin.go | 73 ++++++++++++++++++++++++++++++++++++ src/runtime/lookup_darwin.go | 73 +----------------------------------- 2 files changed, 74 insertions(+), 72 deletions(-) diff --git a/src/net/lookup_darwin.go b/src/net/lookup_darwin.go index 28d2b0c2672c81..e4232bb637365e 100644 --- a/src/net/lookup_darwin.go +++ b/src/net/lookup_darwin.go @@ -6,7 +6,9 @@ package net import ( "context" + "errors" "internal/bytealg" + "strings" "sync" "syscall" @@ -372,3 +374,74 @@ func concurrentThreadsLimit() int { } return r } + +// resolverSearch will make a call to the 'res_search' routine in libSystem +// and parse the output as a slice of IPAddr's +func resolverSearch(ctx context.Context, hostname string, rtype, class int32) ([]string, error) { + + var byteHostname = []byte(hostname) + var responseBuffer = [512]byte{} + + retcode := res_search(&byteHostname[0], class, rtype, &responseBuffer[0], 512) + if retcode < 0 { + return nil, errors.New("could not complete domain resolution") + } + + msg := &dnsmessage.Message{} + err := msg.Unpack(responseBuffer[:]) + if err != nil { + return nil, fmt.Errorf("could not parse dns response: %s", err.Error()) + } + + // parse received answers + var dnsParser dnsmessage.Parser + + if _, err := dnsParser.Start(responseBuffer); err != nil { + return nil, err + } + + var answers []string + for { + h, err := dnsParser.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, err + } + + if !strings.EqualFold(h.Name.String(), hostname) { + if err := dnsParser.SkipAnswer(); err != nil { + return nil, err + } + continue + } + + switch h.Type { + case dnsmessage.TypeA: + r, err := dnsParser.AResource() + if err != nil { + return nil, err + } + answers = append(answers, fmt.Stringf("%s", r.A)) + case dnsmessage.TypeAAAA: + r, err := dnsParser.AAAAResource() + if err != nil { + return nil, err + } + answers = append(answers, fmt.Stringf("%s", r.AAAA)) + + case dnsmessage.TypeCNAME: + r, err := dnsParser.CNAMEResource() + if err != nil { + return nil, err + } + answers = append(answers, fmt.Stringf("%s", r.Name)) + } + } + return answers, nil +} + +// res_search is defined in runtimne/lookup_darwin.go + +func res_search(name *byte, class int32, rtype int32, answer *byte, anslen int32) int32 diff --git a/src/runtime/lookup_darwin.go b/src/runtime/lookup_darwin.go index 388ac13874d401..d29551188b32b8 100644 --- a/src/runtime/lookup_darwin.go +++ b/src/runtime/lookup_darwin.go @@ -1,81 +1,10 @@ package runtime import ( - "context" - "errors" - "strings" "unsafe" - - "internal/x/net/dns/dnsmessage" ) -// ResolverSearch is a darwin specific function. It will make a call to the 'res_search' routine in libSystem -// and parse the output as a slice of IPAddr's -func ResolverSearch(ctx context.Context, hostname string, rtype, class int32) ([]string, error) { - - var byteHostname = []byte(hostname) - var responseBuffer = [512]byte{} - - retcode := res_search(&byteHostname[0], class, rtype, &responseBuffer[0], 512) - if retcode < 0 { - return nil, errors.New("could not complete domain resolution") - } - - msg := &dnsmessage.Message{} - err := msg.Unpack(responseBuffer[:]) - if err != nil { - return nil, fmt.Errorf("could not parse dns response: %s", err.Error()) - } - - // parse received answers - var dnsParser dnsmessage.Parser - - if _, err := dnsParser.Start(responseBuffer); err != nil { - return nil, err - } - - var answers []string - for { - h, err := dnsParser.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, err - } - - if !strings.EqualFold(h.Name.String(), hostname) { - if err := dnsParser.SkipAnswer(); err != nil { - return nil, err - } - continue - } - - switch h.Type { - case dnsmessage.TypeA: - r, err := dnsParser.AResource() - if err != nil { - return nil, err - } - answers = append(answers, fmt.Stringf("%s", r.A)) - case dnsmessage.TypeAAAA: - r, err := dnsParser.AAAAResource() - if err != nil { - return nil, err - } - answers = append(answers, fmt.Stringf("%s", r.AAAA)) - - case dnsmessage.TypeCNAME: - r, err := dnsParser.CNAMEResource() - if err != nil { - return nil, err - } - answers = append(answers, fmt.Stringf("%s", r.Name)) - } - } - return answers, nil -} - +//go:linkname res_search net.res_search //go:nosplit //go:cgo_unsafe_args func res_search(name *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { From 0e90bc3b11edac0fbee2e932cdea0eb5facfaa1f Mon Sep 17 00:00:00 2001 From: grant Date: Mon, 11 Mar 2019 13:46:59 -0400 Subject: [PATCH 20/36] create generic file for resolver methods that are shared between darwin and non-darwin unix platforms Signed-off-by: grant --- src/net/lookup_darwin.go | 303 ------------------------------- src/net/lookup_unix.go | 305 ------------------------------- src/net/lookup_unix_generic.go | 315 +++++++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+), 608 deletions(-) create mode 100644 src/net/lookup_unix_generic.go diff --git a/src/net/lookup_darwin.go b/src/net/lookup_darwin.go index e4232bb637365e..11ddb1d4394b8b 100644 --- a/src/net/lookup_darwin.go +++ b/src/net/lookup_darwin.go @@ -7,74 +7,11 @@ package net import ( "context" "errors" - "internal/bytealg" "strings" - "sync" - "syscall" "internal/x/net/dns/dnsmessage" ) -var onceReadProtocols sync.Once - -// readProtocols loads contents of /etc/protocols into protocols map -// for quick access. -func readProtocols() { - file, err := open("/etc/protocols") - if err != nil { - return - } - defer file.close() - - for line, ok := file.readLine(); ok; line, ok = file.readLine() { - // tcp 6 TCP # transmission control protocol - if i := bytealg.IndexByteString(line, '#'); i >= 0 { - line = line[0:i] - } - f := getFields(line) - if len(f) < 2 { - continue - } - if proto, _, ok := dtoi(f[1]); ok { - if _, ok := protocols[f[0]]; !ok { - protocols[f[0]] = proto - } - for _, alias := range f[2:] { - if _, ok := protocols[alias]; !ok { - protocols[alias] = proto - } - } - } - } -} - -// lookupProtocol looks up IP protocol name in /etc/protocols and -// returns correspondent protocol number. -func lookupProtocol(_ context.Context, name string) (int, error) { - onceReadProtocols.Do(readProtocols) - return lookupProtocolMap(name) -} - -func (r *Resolver) dial(ctx context.Context, network, server string) (Conn, error) { - // Calling Dial here is scary -- we have to be sure not to - // dial a name that will require a DNS lookup, or Dial will - // call back here to translate it. The DNS config parser has - // already checked that all the cfg.servers are IP - // addresses, which Dial will use without a DNS lookup. - var c Conn - var err error - if r != nil && r.Dial != nil { - c, err = r.Dial(ctx, network, server) - } else { - var d Dialer - c, err = d.DialContext(ctx, network, server) - } - if err != nil { - return nil, mapErr(err) - } - return c, nil -} - func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) { order := systemConf().hostLookupOrder(r, host) if !r.preferGo() && order == hostLookupCgo { @@ -118,22 +55,6 @@ func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs [] return ips, err } -func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) { - if !r.preferGo() && systemConf().canUseCgo() { - if port, err, ok := cgoLookupPort(ctx, network, service); ok { - if err != nil { - // Issue 18213: if cgo fails, first check to see whether we - // have the answer baked-in to the net package. - if port, err := goLookupPort(network, service); err == nil { - return port, nil - } - } - return port, err - } - } - return goLookupPort(network, service) -} - func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) { if !r.preferGo() && systemConf().canUseCgo() { if cname, err, ok := cgoLookupCNAME(ctx, name); ok { @@ -151,230 +72,6 @@ func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) return r.goLookupCNAME(ctx, name) } -func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { - var target string - if service == "" && proto == "" { - target = name - } else { - target = "_" + service + "._" + proto + "." + name - } - p, server, err := r.lookup(ctx, target, dnsmessage.TypeSRV) - if err != nil { - return "", nil, err - } - var srvs []*SRV - var cname dnsmessage.Name - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return "", nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeSRV { - if err := p.SkipAnswer(); err != nil { - return "", nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - if cname.Length == 0 && h.Name.Length != 0 { - cname = h.Name - } - srv, err := p.SRVResource() - if err != nil { - return "", nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - srvs = append(srvs, &SRV{Target: srv.Target.String(), Port: srv.Port, Priority: srv.Priority, Weight: srv.Weight}) - } - byPriorityWeight(srvs).sort() - return cname.String(), srvs, nil -} - -func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { - p, server, err := r.lookup(ctx, name, dnsmessage.TypeMX) - if err != nil { - return nil, err - } - var mxs []*MX - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeMX { - if err := p.SkipAnswer(); err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - mx, err := p.MXResource() - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - mxs = append(mxs, &MX{Host: mx.MX.String(), Pref: mx.Pref}) - - } - byPref(mxs).sort() - return mxs, nil -} - -func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { - p, server, err := r.lookup(ctx, name, dnsmessage.TypeNS) - if err != nil { - return nil, err - } - var nss []*NS - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeNS { - if err := p.SkipAnswer(); err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - ns, err := p.NSResource() - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - nss = append(nss, &NS{Host: ns.NS.String()}) - } - return nss, nil -} - -func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) { - p, server, err := r.lookup(ctx, name, dnsmessage.TypeTXT) - if err != nil { - return nil, err - } - var txts []string - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeTXT { - if err := p.SkipAnswer(); err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - txt, err := p.TXTResource() - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - // Multiple strings in one TXT record need to be - // concatenated without separator to be consistent - // with previous Go resolver. - n := 0 - for _, s := range txt.TXT { - n += len(s) - } - txtJoin := make([]byte, 0, n) - for _, s := range txt.TXT { - txtJoin = append(txtJoin, s...) - } - if len(txts) == 0 { - txts = make([]string, 0, 1) - } - txts = append(txts, string(txtJoin)) - } - return txts, nil -} - -func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) { - if !r.preferGo() && systemConf().canUseCgo() { - if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok { - return ptrs, err - } - } - return r.goLookupPTR(ctx, addr) -} - -// concurrentThreadsLimit returns the number of threads we permit to -// run concurrently doing DNS lookups via cgo. A DNS lookup may use a -// file descriptor so we limit this to less than the number of -// permitted open files. On some systems, notably Darwin, if -// getaddrinfo is unable to open a file descriptor it simply returns -// EAI_NONAME rather than a useful error. Limiting the number of -// concurrent getaddrinfo calls to less than the permitted number of -// file descriptors makes that error less likely. We don't bother to -// apply the same limit to DNS lookups run directly from Go, because -// there we will return a meaningful "too many open files" error. -func concurrentThreadsLimit() int { - var rlim syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil { - return 500 - } - r := int(rlim.Cur) - if r > 500 { - r = 500 - } else if r > 30 { - r -= 30 - } - return r -} - // resolverSearch will make a call to the 'res_search' routine in libSystem // and parse the output as a slice of IPAddr's func resolverSearch(ctx context.Context, hostname string, rtype, class int32) ([]string, error) { diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index f57fdc4ea28453..0de32730c3351e 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -8,73 +8,8 @@ package net import ( "context" - "internal/bytealg" - "sync" - "syscall" - - "golang.org/x/net/dns/dnsmessage" ) -var onceReadProtocols sync.Once - -// readProtocols loads contents of /etc/protocols into protocols map -// for quick access. -func readProtocols() { - file, err := open("/etc/protocols") - if err != nil { - return - } - defer file.close() - - for line, ok := file.readLine(); ok; line, ok = file.readLine() { - // tcp 6 TCP # transmission control protocol - if i := bytealg.IndexByteString(line, '#'); i >= 0 { - line = line[0:i] - } - f := getFields(line) - if len(f) < 2 { - continue - } - if proto, _, ok := dtoi(f[1]); ok { - if _, ok := protocols[f[0]]; !ok { - protocols[f[0]] = proto - } - for _, alias := range f[2:] { - if _, ok := protocols[alias]; !ok { - protocols[alias] = proto - } - } - } - } -} - -// lookupProtocol looks up IP protocol name in /etc/protocols and -// returns correspondent protocol number. -func lookupProtocol(_ context.Context, name string) (int, error) { - onceReadProtocols.Do(readProtocols) - return lookupProtocolMap(name) -} - -func (r *Resolver) dial(ctx context.Context, network, server string) (Conn, error) { - // Calling Dial here is scary -- we have to be sure not to - // dial a name that will require a DNS lookup, or Dial will - // call back here to translate it. The DNS config parser has - // already checked that all the cfg.servers are IP - // addresses, which Dial will use without a DNS lookup. - var c Conn - var err error - if r != nil && r.Dial != nil { - c, err = r.Dial(ctx, network, server) - } else { - var d Dialer - c, err = d.DialContext(ctx, network, server) - } - if err != nil { - return nil, mapErr(err) - } - return c, nil -} - func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) { order := systemConf().hostLookupOrder(r, host) if !r.preferGo() && order == hostLookupCgo { @@ -103,22 +38,6 @@ func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs [] return ips, err } -func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) { - if !r.preferGo() && systemConf().canUseCgo() { - if port, err, ok := cgoLookupPort(ctx, network, service); ok { - if err != nil { - // Issue 18213: if cgo fails, first check to see whether we - // have the answer baked-in to the net package. - if port, err := goLookupPort(network, service); err == nil { - return port, nil - } - } - return port, err - } - } - return goLookupPort(network, service) -} - func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) { if !r.preferGo() && systemConf().canUseCgo() { if cname, err, ok := cgoLookupCNAME(ctx, name); ok { @@ -127,227 +46,3 @@ func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) } return r.goLookupCNAME(ctx, name) } - -func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { - var target string - if service == "" && proto == "" { - target = name - } else { - target = "_" + service + "._" + proto + "." + name - } - p, server, err := r.lookup(ctx, target, dnsmessage.TypeSRV) - if err != nil { - return "", nil, err - } - var srvs []*SRV - var cname dnsmessage.Name - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return "", nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeSRV { - if err := p.SkipAnswer(); err != nil { - return "", nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - if cname.Length == 0 && h.Name.Length != 0 { - cname = h.Name - } - srv, err := p.SRVResource() - if err != nil { - return "", nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - srvs = append(srvs, &SRV{Target: srv.Target.String(), Port: srv.Port, Priority: srv.Priority, Weight: srv.Weight}) - } - byPriorityWeight(srvs).sort() - return cname.String(), srvs, nil -} - -func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { - p, server, err := r.lookup(ctx, name, dnsmessage.TypeMX) - if err != nil { - return nil, err - } - var mxs []*MX - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeMX { - if err := p.SkipAnswer(); err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - mx, err := p.MXResource() - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - mxs = append(mxs, &MX{Host: mx.MX.String(), Pref: mx.Pref}) - - } - byPref(mxs).sort() - return mxs, nil -} - -func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { - p, server, err := r.lookup(ctx, name, dnsmessage.TypeNS) - if err != nil { - return nil, err - } - var nss []*NS - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeNS { - if err := p.SkipAnswer(); err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - ns, err := p.NSResource() - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - nss = append(nss, &NS{Host: ns.NS.String()}) - } - return nss, nil -} - -func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) { - p, server, err := r.lookup(ctx, name, dnsmessage.TypeTXT) - if err != nil { - return nil, err - } - var txts []string - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeTXT { - if err := p.SkipAnswer(); err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - txt, err := p.TXTResource() - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - // Multiple strings in one TXT record need to be - // concatenated without separator to be consistent - // with previous Go resolver. - n := 0 - for _, s := range txt.TXT { - n += len(s) - } - txtJoin := make([]byte, 0, n) - for _, s := range txt.TXT { - txtJoin = append(txtJoin, s...) - } - if len(txts) == 0 { - txts = make([]string, 0, 1) - } - txts = append(txts, string(txtJoin)) - } - return txts, nil -} - -func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) { - if !r.preferGo() && systemConf().canUseCgo() { - if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok { - return ptrs, err - } - } - return r.goLookupPTR(ctx, addr) -} - -// concurrentThreadsLimit returns the number of threads we permit to -// run concurrently doing DNS lookups via cgo. A DNS lookup may use a -// file descriptor so we limit this to less than the number of -// permitted open files. On some systems, notably Darwin, if -// getaddrinfo is unable to open a file descriptor it simply returns -// EAI_NONAME rather than a useful error. Limiting the number of -// concurrent getaddrinfo calls to less than the permitted number of -// file descriptors makes that error less likely. We don't bother to -// apply the same limit to DNS lookups run directly from Go, because -// there we will return a meaningful "too many open files" error. -func concurrentThreadsLimit() int { - var rlim syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil { - return 500 - } - r := int(rlim.Cur) - if r > 500 { - r = 500 - } else if r > 30 { - r -= 30 - } - return r -} diff --git a/src/net/lookup_unix_generic.go b/src/net/lookup_unix_generic.go new file mode 100644 index 00000000000000..33578cdcc5e01b --- /dev/null +++ b/src/net/lookup_unix_generic.go @@ -0,0 +1,315 @@ +// Copyright 2019 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris + +package net + +import ( + "context" + "internal/bytealg" + "internal/x/net/dns/dnsmessage" + "sync" + "syscall" +) + +var onceReadProtocols sync.Once + +// readProtocols loads contents of /etc/protocols into protocols map +// for quick access. +func readProtocols() { + file, err := open("/etc/protocols") + if err != nil { + return + } + defer file.close() + + for line, ok := file.readLine(); ok; line, ok = file.readLine() { + // tcp 6 TCP # transmission control protocol + if i := bytealg.IndexByteString(line, '#'); i >= 0 { + line = line[0:i] + } + f := getFields(line) + if len(f) < 2 { + continue + } + if proto, _, ok := dtoi(f[1]); ok { + if _, ok := protocols[f[0]]; !ok { + protocols[f[0]] = proto + } + for _, alias := range f[2:] { + if _, ok := protocols[alias]; !ok { + protocols[alias] = proto + } + } + } + } +} + +func (r *Resolver) dial(ctx context.Context, network, server string) (Conn, error) { + // Calling Dial here is scary -- we have to be sure not to + // dial a name that will require a DNS lookup, or Dial will + // call back here to translate it. The DNS config parser has + // already checked that all the cfg.servers are IP + // addresses, which Dial will use without a DNS lookup. + var c Conn + var err error + if r != nil && r.Dial != nil { + c, err = r.Dial(ctx, network, server) + } else { + var d Dialer + c, err = d.DialContext(ctx, network, server) + } + if err != nil { + return nil, mapErr(err) + } + return c, nil +} + +func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) { + if !r.preferGo() && systemConf().canUseCgo() { + if port, err, ok := cgoLookupPort(ctx, network, service); ok { + if err != nil { + // Issue 18213: if cgo fails, first check to see whether we + // have the answer baked-in to the net package. + if port, err := goLookupPort(network, service); err == nil { + return port, nil + } + } + return port, err + } + } + return goLookupPort(network, service) +} + +func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { + var target string + if service == "" && proto == "" { + target = name + } else { + target = "_" + service + "._" + proto + "." + name + } + p, server, err := r.lookup(ctx, target, dnsmessage.TypeSRV) + if err != nil { + return "", nil, err + } + var srvs []*SRV + var cname dnsmessage.Name + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return "", nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeSRV { + if err := p.SkipAnswer(); err != nil { + return "", nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + if cname.Length == 0 && h.Name.Length != 0 { + cname = h.Name + } + srv, err := p.SRVResource() + if err != nil { + return "", nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + srvs = append(srvs, &SRV{Target: srv.Target.String(), Port: srv.Port, Priority: srv.Priority, Weight: srv.Weight}) + } + byPriorityWeight(srvs).sort() + return cname.String(), srvs, nil +} + +func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { + p, server, err := r.lookup(ctx, name, dnsmessage.TypeMX) + if err != nil { + return nil, err + } + var mxs []*MX + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeMX { + if err := p.SkipAnswer(); err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + mx, err := p.MXResource() + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + mxs = append(mxs, &MX{Host: mx.MX.String(), Pref: mx.Pref}) + + } + byPref(mxs).sort() + return mxs, nil +} + +func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { + p, server, err := r.lookup(ctx, name, dnsmessage.TypeNS) + if err != nil { + return nil, err + } + var nss []*NS + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeNS { + if err := p.SkipAnswer(); err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + ns, err := p.NSResource() + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + nss = append(nss, &NS{Host: ns.NS.String()}) + } + return nss, nil +} + +func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) { + p, server, err := r.lookup(ctx, name, dnsmessage.TypeTXT) + if err != nil { + return nil, err + } + var txts []string + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeTXT { + if err := p.SkipAnswer(); err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + txt, err := p.TXTResource() + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + // Multiple strings in one TXT record need to be + // concatenated without separator to be consistent + // with previous Go resolver. + n := 0 + for _, s := range txt.TXT { + n += len(s) + } + txtJoin := make([]byte, 0, n) + for _, s := range txt.TXT { + txtJoin = append(txtJoin, s...) + } + if len(txts) == 0 { + txts = make([]string, 0, 1) + } + txts = append(txts, string(txtJoin)) + } + return txts, nil +} + +func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) { + if !r.preferGo() && systemConf().canUseCgo() { + if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok { + return ptrs, err + } + } + return r.goLookupPTR(ctx, addr) +} + +// lookupProtocol looks up IP protocol name in /etc/protocols and +// returns correspondent protocol number. +func lookupProtocol(_ context.Context, name string) (int, error) { + onceReadProtocols.Do(readProtocols) + return lookupProtocolMap(name) +} + +// concurrentThreadsLimit returns the number of threads we permit to +// run concurrently doing DNS lookups via cgo. A DNS lookup may use a +// file descriptor so we limit this to less than the number of +// permitted open files. On some systems, notably Darwin, if +// getaddrinfo is unable to open a file descriptor it simply returns +// EAI_NONAME rather than a useful error. Limiting the number of +// concurrent getaddrinfo calls to less than the permitted number of +// file descriptors makes that error less likely. We don't bother to +// apply the same limit to DNS lookups run directly from Go, because +// there we will return a meaningful "too many open files" error. +func concurrentThreadsLimit() int { + var rlim syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil { + return 500 + } + r := int(rlim.Cur) + if r > 500 { + r = 500 + } else if r > 30 { + r -= 30 + } + return r +} From 6155aa3f8a534872fb3ca75b51085a696b218aed Mon Sep 17 00:00:00 2001 From: grant Date: Tue, 12 Mar 2019 14:43:00 -0400 Subject: [PATCH 21/36] Add error checking to res_search assembly routines Signed-off-by: grant --- src/runtime/lookup_darwin_386.s | 7 +++++++ src/runtime/lookup_darwin_amd64.s | 23 +++++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/runtime/lookup_darwin_386.s b/src/runtime/lookup_darwin_386.s index 0da820c5fafd59..152ad66aa88bb7 100644 --- a/src/runtime/lookup_darwin_386.s +++ b/src/runtime/lookup_darwin_386.s @@ -22,6 +22,13 @@ TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 MOVL 0(CX), AX // arg 1 name MOVL AX, 0(SP) CALL libc_res_search(SB) + XORL DX, DX + CMPL AX, $-1 + JNE ok + CALL libc_error(SB) + MOVL (AX), DX // errno + XORL AX, AX +ok: MOVL BP, SP POPL BP RET diff --git a/src/runtime/lookup_darwin_amd64.s b/src/runtime/lookup_darwin_amd64.s index 80f6858ed69c98..a401d2b28903cd 100644 --- a/src/runtime/lookup_darwin_amd64.s +++ b/src/runtime/lookup_darwin_amd64.s @@ -7,13 +7,20 @@ #include "textflag.h" TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 - PUSHQ BP - MOVQ SP, BP - MOVL 24(DI), R8 // arg 5 anslen - MOVQ 16(DI), CX // arg 4 answer - MOVL 8(DI), SI // arg 2 class - MOVQ 12(DI), DX // arg 3 type - MOVQ 0(DI), DI // arg 1 name - CALL libc_res_search(SB) + PUSHQ BP + MOVQ SP, BP + MOVL 24(DI), R8 // arg 5 anslen + MOVQ 16(DI), CX // arg 4 answer + MOVL 8(DI), SI // arg 2 class + MOVQ 12(DI), DX // arg 3 type + MOVQ 0(DI), DI // arg 1 name + CALL libc_res_search(SB) + XORL DX, DX + CMPQ AX, $-1 + JNE ok + CALL libc_error(SB) + MOVLQSX (AX), DX // errno + XORL AX, AX +ok: POPQ BP RET From 4de3446aede35f74f077b62ac011a6e02cc6e49a Mon Sep 17 00:00:00 2001 From: grant Date: Mon, 18 Mar 2019 17:38:52 -0400 Subject: [PATCH 22/36] define new cgo_stub for darwin which uses libSystem bindings Signed-off-by: grant --- src/net/conf.go | 8 + src/net/lookup_darwin.go | 144 --------------- src/net/lookup_unix.go | 307 +++++++++++++++++++++++++++++++- src/net/lookup_unix_generic.go | 315 --------------------------------- 4 files changed, 314 insertions(+), 460 deletions(-) delete mode 100644 src/net/lookup_darwin.go delete mode 100644 src/net/lookup_unix_generic.go diff --git a/src/net/conf.go b/src/net/conf.go index 971b1a399a1bb8..7906190eb01aee 100644 --- a/src/net/conf.go +++ b/src/net/conf.go @@ -70,6 +70,14 @@ func initConfVal() { // their own DNS requests. So always use cgo instead, which // avoids that. if runtime.GOOS == "darwin" { + + // only use netgo if user specifies to + if dnsMode == "go" { + confVal.netGo = true + } else { + confVal.netGo = false + } + confVal.forceCgoLookupHost = true return } diff --git a/src/net/lookup_darwin.go b/src/net/lookup_darwin.go deleted file mode 100644 index 11ddb1d4394b8b..00000000000000 --- a/src/net/lookup_darwin.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2011 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 net - -import ( - "context" - "errors" - "strings" - - "internal/x/net/dns/dnsmessage" -) - -func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) { - order := systemConf().hostLookupOrder(r, host) - if !r.preferGo() && order == hostLookupCgo { - if addrs, err, ok := cgoLookupHost(ctx, host); ok { - return addrs, err - } - // cgo not available (or netgo); fall back to linked bindings - order = hostLookupFilesDNS - } - - // darwin has unique resolution files, use libSystem binding if cgo is disabled. - addrs, err := resolverSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) - if err == nil { - return addrs, nil - } - // something went wrong, fallback to Go's DNS resolver - - return r.goLookupHostOrder(ctx, host, order) -} - -func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs []IPAddr, err error) { - if r.preferGo() { - return r.goLookupIP(ctx, host) - } - order := systemConf().hostLookupOrder(r, host) - if order == hostLookupCgo { - if addrs, err, ok := cgoLookupIP(ctx, network, host); ok { - return addrs, err - } - - // darwin has unique resolution files, use libSystem binding if cgo is disabled. - addrs, err := resolverSearch(ctx, host, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) - if err == nil { - return addrs, nil - } - // something went wrong, fallback to Go's DNS resolver - - order = hostLookupFilesDNS - } - ips, _, err := r.goLookupIPCNAMEOrder(ctx, host, order) - return ips, err -} - -func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) { - if !r.preferGo() && systemConf().canUseCgo() { - if cname, err, ok := cgoLookupCNAME(ctx, name); ok { - return cname, err - } - } - - // darwin has unique resolution files, use libSystem binding if cgo is not an option. - addrs, err := resolverSearch(ctx, name, int32(dnsmessage.TypeCNAME), int32(dnsmessage.ClassINET)) - if err == nil { - return addrs, nil - } - - // something went wrong, fallback to Go's DNS resolver - return r.goLookupCNAME(ctx, name) -} - -// resolverSearch will make a call to the 'res_search' routine in libSystem -// and parse the output as a slice of IPAddr's -func resolverSearch(ctx context.Context, hostname string, rtype, class int32) ([]string, error) { - - var byteHostname = []byte(hostname) - var responseBuffer = [512]byte{} - - retcode := res_search(&byteHostname[0], class, rtype, &responseBuffer[0], 512) - if retcode < 0 { - return nil, errors.New("could not complete domain resolution") - } - - msg := &dnsmessage.Message{} - err := msg.Unpack(responseBuffer[:]) - if err != nil { - return nil, fmt.Errorf("could not parse dns response: %s", err.Error()) - } - - // parse received answers - var dnsParser dnsmessage.Parser - - if _, err := dnsParser.Start(responseBuffer); err != nil { - return nil, err - } - - var answers []string - for { - h, err := dnsParser.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, err - } - - if !strings.EqualFold(h.Name.String(), hostname) { - if err := dnsParser.SkipAnswer(); err != nil { - return nil, err - } - continue - } - - switch h.Type { - case dnsmessage.TypeA: - r, err := dnsParser.AResource() - if err != nil { - return nil, err - } - answers = append(answers, fmt.Stringf("%s", r.A)) - case dnsmessage.TypeAAAA: - r, err := dnsParser.AAAAResource() - if err != nil { - return nil, err - } - answers = append(answers, fmt.Stringf("%s", r.AAAA)) - - case dnsmessage.TypeCNAME: - r, err := dnsParser.CNAMEResource() - if err != nil { - return nil, err - } - answers = append(answers, fmt.Stringf("%s", r.Name)) - } - } - return answers, nil -} - -// res_search is defined in runtimne/lookup_darwin.go - -func res_search(name *byte, class int32, rtype int32, answer *byte, anslen int32) int32 diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index 0de32730c3351e..6543f121a738f2 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -2,14 +2,79 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix dragonfly freebsd linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net import ( "context" + "internal/bytealg" + "sync" + "syscall" + + "internal/x/net/dns/dnsmessage" ) +var onceReadProtocols sync.Once + +// readProtocols loads contents of /etc/protocols into protocols map +// for quick access. +func readProtocols() { + file, err := open("/etc/protocols") + if err != nil { + return + } + defer file.close() + + for line, ok := file.readLine(); ok; line, ok = file.readLine() { + // tcp 6 TCP # transmission control protocol + if i := bytealg.IndexByteString(line, '#'); i >= 0 { + line = line[0:i] + } + f := getFields(line) + if len(f) < 2 { + continue + } + if proto, _, ok := dtoi(f[1]); ok { + if _, ok := protocols[f[0]]; !ok { + protocols[f[0]] = proto + } + for _, alias := range f[2:] { + if _, ok := protocols[alias]; !ok { + protocols[alias] = proto + } + } + } + } +} + +// lookupProtocol looks up IP protocol name in /etc/protocols and +// returns correspondent protocol number. +func lookupProtocol(_ context.Context, name string) (int, error) { + onceReadProtocols.Do(readProtocols) + return lookupProtocolMap(name) +} + +func (r *Resolver) dial(ctx context.Context, network, server string) (Conn, error) { + // Calling Dial here is scary -- we have to be sure not to + // dial a name that will require a DNS lookup, or Dial will + // call back here to translate it. The DNS config parser has + // already checked that all the cfg.servers are IP + // addresses, which Dial will use without a DNS lookup. + var c Conn + var err error + if r != nil && r.Dial != nil { + c, err = r.Dial(ctx, network, server) + } else { + var d Dialer + c, err = d.DialContext(ctx, network, server) + } + if err != nil { + return nil, mapErr(err) + } + return c, nil +} + func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) { order := systemConf().hostLookupOrder(r, host) if !r.preferGo() && order == hostLookupCgo { @@ -38,6 +103,22 @@ func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs [] return ips, err } +func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) { + if !r.preferGo() && systemConf().canUseCgo() { + if port, err, ok := cgoLookupPort(ctx, network, service); ok { + if err != nil { + // Issue 18213: if cgo fails, first check to see whether we + // have the answer baked-in to the net package. + if port, err := goLookupPort(network, service); err == nil { + return port, nil + } + } + return port, err + } + } + return goLookupPort(network, service) +} + func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) { if !r.preferGo() && systemConf().canUseCgo() { if cname, err, ok := cgoLookupCNAME(ctx, name); ok { @@ -46,3 +127,227 @@ func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) } return r.goLookupCNAME(ctx, name) } + +func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { + var target string + if service == "" && proto == "" { + target = name + } else { + target = "_" + service + "._" + proto + "." + name + } + p, server, err := r.lookup(ctx, target, dnsmessage.TypeSRV) + if err != nil { + return "", nil, err + } + var srvs []*SRV + var cname dnsmessage.Name + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return "", nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeSRV { + if err := p.SkipAnswer(); err != nil { + return "", nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + if cname.Length == 0 && h.Name.Length != 0 { + cname = h.Name + } + srv, err := p.SRVResource() + if err != nil { + return "", nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + srvs = append(srvs, &SRV{Target: srv.Target.String(), Port: srv.Port, Priority: srv.Priority, Weight: srv.Weight}) + } + byPriorityWeight(srvs).sort() + return cname.String(), srvs, nil +} + +func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { + p, server, err := r.lookup(ctx, name, dnsmessage.TypeMX) + if err != nil { + return nil, err + } + var mxs []*MX + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeMX { + if err := p.SkipAnswer(); err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + mx, err := p.MXResource() + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + mxs = append(mxs, &MX{Host: mx.MX.String(), Pref: mx.Pref}) + + } + byPref(mxs).sort() + return mxs, nil +} + +func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { + p, server, err := r.lookup(ctx, name, dnsmessage.TypeNS) + if err != nil { + return nil, err + } + var nss []*NS + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeNS { + if err := p.SkipAnswer(); err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + ns, err := p.NSResource() + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + nss = append(nss, &NS{Host: ns.NS.String()}) + } + return nss, nil +} + +func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) { + p, server, err := r.lookup(ctx, name, dnsmessage.TypeTXT) + if err != nil { + return nil, err + } + var txts []string + for { + h, err := p.AnswerHeader() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + if h.Type != dnsmessage.TypeTXT { + if err := p.SkipAnswer(); err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + continue + } + txt, err := p.TXTResource() + if err != nil { + return nil, &DNSError{ + Err: "cannot unmarshal DNS message", + Name: name, + Server: server, + } + } + // Multiple strings in one TXT record need to be + // concatenated without separator to be consistent + // with previous Go resolver. + n := 0 + for _, s := range txt.TXT { + n += len(s) + } + txtJoin := make([]byte, 0, n) + for _, s := range txt.TXT { + txtJoin = append(txtJoin, s...) + } + if len(txts) == 0 { + txts = make([]string, 0, 1) + } + txts = append(txts, string(txtJoin)) + } + return txts, nil +} + +func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) { + if !r.preferGo() && systemConf().canUseCgo() { + if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok { + return ptrs, err + } + } + return r.goLookupPTR(ctx, addr) +} + +// concurrentThreadsLimit returns the number of threads we permit to +// run concurrently doing DNS lookups via cgo. A DNS lookup may use a +// file descriptor so we limit this to less than the number of +// permitted open files. On some systems, notably Darwin, if +// getaddrinfo is unable to open a file descriptor it simply returns +// EAI_NONAME rather than a useful error. Limiting the number of +// concurrent getaddrinfo calls to less than the permitted number of +// file descriptors makes that error less likely. We don't bother to +// apply the same limit to DNS lookups run directly from Go, because +// there we will return a meaningful "too many open files" error. +func concurrentThreadsLimit() int { + var rlim syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil { + return 500 + } + r := int(rlim.Cur) + if r > 500 { + r = 500 + } else if r > 30 { + r -= 30 + } + return r +} diff --git a/src/net/lookup_unix_generic.go b/src/net/lookup_unix_generic.go deleted file mode 100644 index 33578cdcc5e01b..00000000000000 --- a/src/net/lookup_unix_generic.go +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright 2019 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package net - -import ( - "context" - "internal/bytealg" - "internal/x/net/dns/dnsmessage" - "sync" - "syscall" -) - -var onceReadProtocols sync.Once - -// readProtocols loads contents of /etc/protocols into protocols map -// for quick access. -func readProtocols() { - file, err := open("/etc/protocols") - if err != nil { - return - } - defer file.close() - - for line, ok := file.readLine(); ok; line, ok = file.readLine() { - // tcp 6 TCP # transmission control protocol - if i := bytealg.IndexByteString(line, '#'); i >= 0 { - line = line[0:i] - } - f := getFields(line) - if len(f) < 2 { - continue - } - if proto, _, ok := dtoi(f[1]); ok { - if _, ok := protocols[f[0]]; !ok { - protocols[f[0]] = proto - } - for _, alias := range f[2:] { - if _, ok := protocols[alias]; !ok { - protocols[alias] = proto - } - } - } - } -} - -func (r *Resolver) dial(ctx context.Context, network, server string) (Conn, error) { - // Calling Dial here is scary -- we have to be sure not to - // dial a name that will require a DNS lookup, or Dial will - // call back here to translate it. The DNS config parser has - // already checked that all the cfg.servers are IP - // addresses, which Dial will use without a DNS lookup. - var c Conn - var err error - if r != nil && r.Dial != nil { - c, err = r.Dial(ctx, network, server) - } else { - var d Dialer - c, err = d.DialContext(ctx, network, server) - } - if err != nil { - return nil, mapErr(err) - } - return c, nil -} - -func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) { - if !r.preferGo() && systemConf().canUseCgo() { - if port, err, ok := cgoLookupPort(ctx, network, service); ok { - if err != nil { - // Issue 18213: if cgo fails, first check to see whether we - // have the answer baked-in to the net package. - if port, err := goLookupPort(network, service); err == nil { - return port, nil - } - } - return port, err - } - } - return goLookupPort(network, service) -} - -func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { - var target string - if service == "" && proto == "" { - target = name - } else { - target = "_" + service + "._" + proto + "." + name - } - p, server, err := r.lookup(ctx, target, dnsmessage.TypeSRV) - if err != nil { - return "", nil, err - } - var srvs []*SRV - var cname dnsmessage.Name - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return "", nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeSRV { - if err := p.SkipAnswer(); err != nil { - return "", nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - if cname.Length == 0 && h.Name.Length != 0 { - cname = h.Name - } - srv, err := p.SRVResource() - if err != nil { - return "", nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - srvs = append(srvs, &SRV{Target: srv.Target.String(), Port: srv.Port, Priority: srv.Priority, Weight: srv.Weight}) - } - byPriorityWeight(srvs).sort() - return cname.String(), srvs, nil -} - -func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { - p, server, err := r.lookup(ctx, name, dnsmessage.TypeMX) - if err != nil { - return nil, err - } - var mxs []*MX - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeMX { - if err := p.SkipAnswer(); err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - mx, err := p.MXResource() - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - mxs = append(mxs, &MX{Host: mx.MX.String(), Pref: mx.Pref}) - - } - byPref(mxs).sort() - return mxs, nil -} - -func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { - p, server, err := r.lookup(ctx, name, dnsmessage.TypeNS) - if err != nil { - return nil, err - } - var nss []*NS - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeNS { - if err := p.SkipAnswer(); err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - ns, err := p.NSResource() - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - nss = append(nss, &NS{Host: ns.NS.String()}) - } - return nss, nil -} - -func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) { - p, server, err := r.lookup(ctx, name, dnsmessage.TypeTXT) - if err != nil { - return nil, err - } - var txts []string - for { - h, err := p.AnswerHeader() - if err == dnsmessage.ErrSectionDone { - break - } - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - if h.Type != dnsmessage.TypeTXT { - if err := p.SkipAnswer(); err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - continue - } - txt, err := p.TXTResource() - if err != nil { - return nil, &DNSError{ - Err: "cannot unmarshal DNS message", - Name: name, - Server: server, - } - } - // Multiple strings in one TXT record need to be - // concatenated without separator to be consistent - // with previous Go resolver. - n := 0 - for _, s := range txt.TXT { - n += len(s) - } - txtJoin := make([]byte, 0, n) - for _, s := range txt.TXT { - txtJoin = append(txtJoin, s...) - } - if len(txts) == 0 { - txts = make([]string, 0, 1) - } - txts = append(txts, string(txtJoin)) - } - return txts, nil -} - -func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) { - if !r.preferGo() && systemConf().canUseCgo() { - if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok { - return ptrs, err - } - } - return r.goLookupPTR(ctx, addr) -} - -// lookupProtocol looks up IP protocol name in /etc/protocols and -// returns correspondent protocol number. -func lookupProtocol(_ context.Context, name string) (int, error) { - onceReadProtocols.Do(readProtocols) - return lookupProtocolMap(name) -} - -// concurrentThreadsLimit returns the number of threads we permit to -// run concurrently doing DNS lookups via cgo. A DNS lookup may use a -// file descriptor so we limit this to less than the number of -// permitted open files. On some systems, notably Darwin, if -// getaddrinfo is unable to open a file descriptor it simply returns -// EAI_NONAME rather than a useful error. Limiting the number of -// concurrent getaddrinfo calls to less than the permitted number of -// file descriptors makes that error less likely. We don't bother to -// apply the same limit to DNS lookups run directly from Go, because -// there we will return a meaningful "too many open files" error. -func concurrentThreadsLimit() int { - var rlim syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil { - return 500 - } - r := int(rlim.Cur) - if r > 500 { - r = 500 - } else if r > 30 { - r -= 30 - } - return r -} From 046d71715253c8a57d75a29f2eb43eae1feed22e Mon Sep 17 00:00:00 2001 From: grant Date: Wed, 20 Mar 2019 17:18:14 -0400 Subject: [PATCH 23/36] Fix build tags. Add res_ninit and res_nsearch Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 206 ++++++++++++++++++++++++++++++ src/net/cgo_stub.go | 3 +- src/runtime/lookup_darwin.go | 19 ++- src/runtime/lookup_darwin_amd64.s | 30 ++++- 4 files changed, 245 insertions(+), 13 deletions(-) create mode 100644 src/net/cgo_darwin_stub.go diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go new file mode 100644 index 00000000000000..d265188656a0cb --- /dev/null +++ b/src/net/cgo_darwin_stub.go @@ -0,0 +1,206 @@ +// Copyright 2019 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 !netgo,!cgo +// +build darwin + +package net + +import ( + "context" + "errors" + + "internal/x/net/dns/dnsmessage" +) + +func cgoLookupHost(ctx context.Context, name string) (addrs []string, err error, completed bool) { + resources, err := resolverGetResources(ctx, name, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) + if err != nil { + return + } + addrs, err = parseHostsFromResources(resources) + if err != nil { + return + } + return addrs, nil, true +} + +func cgoLookupPort(ctx context.Context, network, service string) (port int, err error, completed bool) { + port, err = goLookupPort(network, service) // just use netgo lookup + return port, err, err == nil +} + +func cgoLookupIP(ctx context.Context, network, name string) (addrs []IPAddr, err error, completed bool) { + + var resources []dnsmessage.Resource + switch ipVersion(network) { + case '4': + resources, err = resolverGetResources(ctx, name, int32(dnsmessage.TypeA), int32(dnsmessage.ClassINET)) + case '6': + resources, err = resolverGetResources(ctx, name, int32(dnsmessage.TypeAAAA), int32(dnsmessage.ClassINET)) + default: + resources, err = resolverGetResources(ctx, name, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) + } + if err != nil { + return + } + + addrs, err = parseIPsFromResources(resources) + if err != nil { + return + } + + return addrs, nil, true +} + +func cgoLookupCNAME(ctx context.Context, name string) (cname string, err error, completed bool) { + resources, err := resolverGetResources(ctx, name, int32(dnsmessage.TypeCNAME), int32(dnsmessage.ClassINET)) + if err != nil { + return + } + cname, err = parseCNAMEFromResources(resources) + if err != nil { + return "", err, false + } + return cname, nil, true +} + +func cgoLookupPTR(ctx context.Context, addr string) (ptrs []string, err error, completed bool) { + resources, err := resolverGetResources(ctx, addr, int32(dnsmessage.TypePTR), int32(dnsmessage.ClassINET)) + if err != nil { + return + } + ptrs, err = parsePTRsFromResources(resources) + if err != nil { + return + } + return ptrs, nil, true +} + +// resolverGetResources will make a call to the 'res_search' routine in libSystem +// and parse the output as a slice of resource resources which can then be parsed +func resolverGetResources(ctx context.Context, hostname string, rtype, class int32) ([]dnsmessage.Resource, error) { + var byteHostname = []byte(hostname) + var responseBuffer = [512]byte{} + var statp [71]uint64 + + retcode := res_ninit(&statp) + if retcode < 0 { + return nil, errors.New("could not initialize resolution data") + } + + retcode = res_nsearch(&statp, &byteHostname[0], class, rtype, &responseBuffer[0], 512) + if retcode < 0 { + return nil, errors.New("could not complete domain resolution") + } + + msg := &dnsmessage.Message{} + err := msg.Unpack(responseBuffer[:]) + if err != nil { + return nil, err + } + + var dnsParser dnsmessage.Parser + if _, err := dnsParser.Start(responseBuffer[:]); err != nil { + return nil, err + } + + var resources []dnsmessage.Resource + for { + r, err := dnsParser.Answer() + if err == dnsmessage.ErrSectionDone { + break + } + if err != nil { + return nil, err + } + resources = append(resources, r) + } + return resources, nil +} + +func parseHostsFromResources(resources []dnsmessage.Resource) ([]string, error) { + var answers []string + + for i := range resources { + switch resources[i].Header.Type { + case dnsmessage.TypeA: + b, ok := resources[i].Body.(*dnsmessage.AResource) + if !ok { + return nil, errors.New("could not parse A resource record") + } + answers = append(answers, string(b.A)) + case dnsmessage.TypeAAAA: + b, ok := resources[i].Body.(*dnsmessage.AAAAResource) + if !ok { + return nil, errors.New("could not parse AAAA resource record") + } + answers = append(answers, string("%s", b.AAAA)) + default: + return nil, errors.New("could not parse an A or AAAA response from message buffer") + } + } + return answers, nil +} + +func parseIPsFromResources(resources []dnsmessage.Resource) ([]IPAddr, error) { + var answers []IPAddr + + for i := range resources { + switch resources[i].Header.Type { + case dnsmessage.TypeA: + b, ok := resources[i].Body.(*dnsmessage.AResource) + if !ok { + return nil, errors.New("could not parse A resource record") + } + ip := parseIPv4(string(b.A[:])) + answers = append(answers, IPAddr{IP: ip}) + case dnsmessage.TypeAAAA: + b, ok := resources[i].Body.(*dnsmessage.AAAAResource) + if !ok { + return nil, errors.New("could not parse AAAA resource record") + } + ip, zone := parseIPv6Zone(string(b.AAAA[:])) + answers = append(answers, IPAddr{IP: ip, Zone: zone}) + default: + return nil, errors.New("could not parse an A or AAAA response from message buffer") + } + } + return answers, nil +} + +func parseCNAMEFromResources(resources []dnsmessage.Resource) (string, error) { + if len(resources) == 0 { + return "", errors.New("no CNAME record received") + } + c, ok := resources[0].Body.(*dnsmessage.CNAMEResource) + if !ok { + return "", errors.New("could not parse CNAME record") + } + return c.CNAME.String(), nil +} + +func parsePTRsFromResources(resources []dnsmessage.Resource) ([]string, error) { + var answers []string + for i := range resources { + switch resources[i].Header.Type { + case dnsmessage.TypePTR: + p, ok := resources[0].Body.(*dnsmessage.PTRResource) + if !ok { + return nil, errors.New("could not parse PTR record") + } + answers = append(answers, p.PTR.String()) + default: + return nil, errors.New("could not parse a PTR response from message buffer") + + } + } + return answers, nil +} + +// res_ninit and res_nsearch are defined in runtimne/lookup_darwin.go + +func res_ninit(statp *[71]uint64) int32 + +func res_nsearch(statp *[71]uint64, dname *byte, class int32, rtype int32, answer *byte, anslen int32) int32 diff --git a/src/net/cgo_stub.go b/src/net/cgo_stub.go index 041f8af12966a4..7812639659113d 100644 --- a/src/net/cgo_stub.go +++ b/src/net/cgo_stub.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !cgo netgo +// +build netgo !cgo +// +build !darwin package net diff --git a/src/runtime/lookup_darwin.go b/src/runtime/lookup_darwin.go index d29551188b32b8..7f64a9a85b48f7 100644 --- a/src/runtime/lookup_darwin.go +++ b/src/runtime/lookup_darwin.go @@ -4,12 +4,21 @@ import ( "unsafe" ) -//go:linkname res_search net.res_search +//go:linkname res_ninit net.res_ninit //go:nosplit //go:cgo_unsafe_args -func res_search(name *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { - return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&name)) +func res_ninit(statp *[71]uint64) int32 { + return libcCall(unsafe.Pointer(funcPC(res_ninit_trampoline)), unsafe.Pointer(&statp)) } -func res_search_trampoline() +func res_ninit_trampoline() -//go:cgo_import_dynamic libc_res_search res_search "/usr/lib/libSystem.B.dylib" +//go:linkname res_nsearch net.res_nsearch +//go:nosplit +//go:cgo_unsafe_args +func res_nsearch(statp *[71]uint64, dname *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { + return libcCall(unsafe.Pointer(funcPC(res_nsearch_trampoline)), unsafe.Pointer(&statp)) +} +func res_nsearch_trampoline() + +//go:cgo_import_dynamic libc_res_nsearch res_nsearch "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_res_ninit res_ninit "/usr/lib/libSystem.B.dylib" diff --git a/src/runtime/lookup_darwin_amd64.s b/src/runtime/lookup_darwin_amd64.s index a401d2b28903cd..85b363d5bdf8ac 100644 --- a/src/runtime/lookup_darwin_amd64.s +++ b/src/runtime/lookup_darwin_amd64.s @@ -6,15 +6,31 @@ #include "go_tls.h" #include "textflag.h" -TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 +TEXT runtime·res_ninit_trampoline(SB),NOSPLIT,$0 PUSHQ BP MOVQ SP, BP - MOVL 24(DI), R8 // arg 5 anslen - MOVQ 16(DI), CX // arg 4 answer - MOVL 8(DI), SI // arg 2 class - MOVQ 12(DI), DX // arg 3 type - MOVQ 0(DI), DI // arg 1 name - CALL libc_res_search(SB) + MOVQ 0(DI), DI // arg 1 statp + CALL libc_res_ninit(SB) + XORL DX, DX + CMPQ AX, $-1 + JNE ok + CALL libc_error(SB) + MOVLQSX (AX), DX // errno + XORL AX, AX +ok: + POPQ BP + RET + +TEXT runtime·res_nsearch_trampoline(SB),NOSPLIT,$0 + PUSHQ BP + MOVQ SP, BP + MOVL 32(DI), R9 // arg 6 anslen + MOVQ 24(DI), R8 // arg 5 answer + MOVL 12(DI), DX // arg 3 class + MOVQ 16(DI), CX // arg 4 type + MOVQ 8(DI), SI // arg 2 name + MOVQ 0(DI), DI // arg 1 statp + CALL libc_res_nsearch(SB) XORL DX, DX CMPQ AX, $-1 JNE ok From 966dd03809ebc73612b3f72a647648603e14d426 Mon Sep 17 00:00:00 2001 From: grant Date: Thu, 21 Mar 2019 11:28:59 -0400 Subject: [PATCH 24/36] fix typo Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go index d265188656a0cb..043a4f42e9f53c 100644 --- a/src/net/cgo_darwin_stub.go +++ b/src/net/cgo_darwin_stub.go @@ -130,13 +130,13 @@ func parseHostsFromResources(resources []dnsmessage.Resource) ([]string, error) if !ok { return nil, errors.New("could not parse A resource record") } - answers = append(answers, string(b.A)) + answers = append(answers, string(b.A[:])) case dnsmessage.TypeAAAA: b, ok := resources[i].Body.(*dnsmessage.AAAAResource) if !ok { return nil, errors.New("could not parse AAAA resource record") } - answers = append(answers, string("%s", b.AAAA)) + answers = append(answers, string(b.AAAA[:])) default: return nil, errors.New("could not parse an A or AAAA response from message buffer") } From 14cc8eddbd75254bf4c0d3a56c1a22ceee3868c0 Mon Sep 17 00:00:00 2001 From: grant Date: Thu, 21 Mar 2019 14:49:31 -0400 Subject: [PATCH 25/36] Update 32 bit and arm assembly for ninit and nsearch Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 6 ++-- src/net/cgo_stub.go | 8 +++-- src/runtime/lookup_darwin.go | 10 +++--- src/runtime/lookup_darwin_386.s | 53 ++++++++++++++++++++++--------- src/runtime/lookup_darwin_amd64.s | 4 +-- src/runtime/lookup_darwin_arm.s | 9 ++++-- src/runtime/lookup_darwin_arm64.s | 9 ++++-- 7 files changed, 68 insertions(+), 31 deletions(-) diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go index 043a4f42e9f53c..673a086a11bc58 100644 --- a/src/net/cgo_darwin_stub.go +++ b/src/net/cgo_darwin_stub.go @@ -85,7 +85,7 @@ func resolverGetResources(ctx context.Context, hostname string, rtype, class int var responseBuffer = [512]byte{} var statp [71]uint64 - retcode := res_ninit(&statp) + retcode := res_init(&statp) if retcode < 0 { return nil, errors.New("could not initialize resolution data") } @@ -199,8 +199,8 @@ func parsePTRsFromResources(resources []dnsmessage.Resource) ([]string, error) { return answers, nil } -// res_ninit and res_nsearch are defined in runtimne/lookup_darwin.go +// res_init and res_nsearch are defined in runtimne/lookup_darwin.go -func res_ninit(statp *[71]uint64) int32 +func res_init(statp *[71]uint64) int32 func res_nsearch(statp *[71]uint64, dname *byte, class int32, rtype int32, answer *byte, anslen int32) int32 diff --git a/src/net/cgo_stub.go b/src/net/cgo_stub.go index 7812639659113d..09185d8b949d95 100644 --- a/src/net/cgo_stub.go +++ b/src/net/cgo_stub.go @@ -7,9 +7,13 @@ package net -import "context" +import ( + "context" +) -func init() { netGo = true } +func init() { + netGo = true +} type addrinfoErrno int diff --git a/src/runtime/lookup_darwin.go b/src/runtime/lookup_darwin.go index 7f64a9a85b48f7..166e84cd3c22e8 100644 --- a/src/runtime/lookup_darwin.go +++ b/src/runtime/lookup_darwin.go @@ -4,13 +4,13 @@ import ( "unsafe" ) -//go:linkname res_ninit net.res_ninit +//go:linkname res_init net.res_init //go:nosplit //go:cgo_unsafe_args -func res_ninit(statp *[71]uint64) int32 { - return libcCall(unsafe.Pointer(funcPC(res_ninit_trampoline)), unsafe.Pointer(&statp)) +func res_init(statp *[71]uint64) int32 { + return libcCall(unsafe.Pointer(funcPC(res_init_trampoline)), unsafe.Pointer(&statp)) } -func res_ninit_trampoline() +func res_init_trampoline() //go:linkname res_nsearch net.res_nsearch //go:nosplit @@ -21,4 +21,4 @@ func res_nsearch(statp *[71]uint64, dname *byte, class int32, rtype int32, answe func res_nsearch_trampoline() //go:cgo_import_dynamic libc_res_nsearch res_nsearch "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_res_ninit res_ninit "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_res_init res_init "/usr/lib/libSystem.B.dylib" diff --git a/src/runtime/lookup_darwin_386.s b/src/runtime/lookup_darwin_386.s index 152ad66aa88bb7..f94feb5b30263d 100644 --- a/src/runtime/lookup_darwin_386.s +++ b/src/runtime/lookup_darwin_386.s @@ -6,29 +6,52 @@ #include "go_tls.h" #include "textflag.h" -TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 +TEXT runtime·res_nsearch_trampoline(SB),NOSPLIT,$0 PUSHL BP MOVL SP, BP SUBL $24, SP MOVL 32(SP), CX - MOVL 16(CX), AX // arg 5 anslen + MOVL 20(CX), AX // arg 6 anslen + MOVL AX, 20(SP) + MOVL 16(CX), AX // arg 5 answer MOVL AX, 16(SP) - MOVL 12(CX), AX // arg 4 answer + MOVL 8(CX), AX // arg 3 class + MOVL AX, 8(SP) + MOVL 12(CX), AX // arg 4 type MOVL AX, 12(SP) - MOVL 4(CX), AX // arg 2 class + MOVL 4(CX), AX // arg 2 name MOVL AX, 4(SP) - MOVL 8(CX), AX // arg 3 type - MOVL AX, 8(SP) - MOVL 0(CX), AX // arg 1 name + MOVL 4(CX), AX // arg 2 name + MOVL AX, 4(SP) + MOVL 0(CX), AX // arg 1 statp + MOVL AX, 0(SP) + CALL libc_res_nsearch(SB) + XORL DX, DX + CMPL AX, $-1 + JNE ok + CALL libc_error(SB) + MOVL (AX), DX // errno + XORL AX, AX +ok: + MOVL BP, SP + POPL BP + RET + +TEXT runtime·res_ninit_trampoline(SB),NOSPLIT,$0 + PUSHL BP + MOVL SP, BP + SUBL $8, SP + MOVL 16(SP), CX + MOVL 0(CX), AX // arg 1 statp MOVL AX, 0(SP) - CALL libc_res_search(SB) - XORL DX, DX - CMPL AX, $-1 - JNE ok - CALL libc_error(SB) - MOVL (AX), DX // errno - XORL AX, AX -ok: + CALL libc_res_ninit(SB) + XORL DX, DX + CMPL AX, $-1 + JNE ok + CALL libc_error(SB) + MOVL (AX), DX + XORL AX, AX +ok: MOVL BP, SP POPL BP RET diff --git a/src/runtime/lookup_darwin_amd64.s b/src/runtime/lookup_darwin_amd64.s index 85b363d5bdf8ac..a0a9d6194f51c6 100644 --- a/src/runtime/lookup_darwin_amd64.s +++ b/src/runtime/lookup_darwin_amd64.s @@ -6,11 +6,11 @@ #include "go_tls.h" #include "textflag.h" -TEXT runtime·res_ninit_trampoline(SB),NOSPLIT,$0 +TEXT runtime·res_init_trampoline(SB),NOSPLIT,$0 PUSHQ BP MOVQ SP, BP MOVQ 0(DI), DI // arg 1 statp - CALL libc_res_ninit(SB) + CALL libc_res_init(SB) XORL DX, DX CMPQ AX, $-1 JNE ok diff --git a/src/runtime/lookup_darwin_arm.s b/src/runtime/lookup_darwin_arm.s index 15ae2c6d90eae9..7c2f4c17695468 100644 --- a/src/runtime/lookup_darwin_arm.s +++ b/src/runtime/lookup_darwin_arm.s @@ -14,7 +14,12 @@ // for resolution. This will just exit with nominal // exit code -TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 - MOVW $98, R0 +TEXT runtime·res_nsearch_trampoline(SB),NOSPLIT,$0 + MOVW $90, R0 + BL libc_exit(SB) + RET + +TEXT runtime·res_ninit_trampoline(SB),NOSPLIT,$0 + MOVW $91, R0 BL libc_exit(SB) RET diff --git a/src/runtime/lookup_darwin_arm64.s b/src/runtime/lookup_darwin_arm64.s index 92e34a30ee6e69..25bd36ed1a1ffc 100644 --- a/src/runtime/lookup_darwin_arm64.s +++ b/src/runtime/lookup_darwin_arm64.s @@ -10,7 +10,12 @@ // for resolution. This will just exit with nominal // exit code -TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 - MOVW $1, R0 +TEXT runtime·res_nsearch_trampoline(SB),NOSPLIT,$0 + MOVW $80, R0 + BL libc_exit(SB) + RET + +TEXT runtime·res_ninit_trampoline(SB),NOSPLIT,$0 + MOVW $81, R0 BL libc_exit(SB) RET From 50e802568c4d510fb1437020b846a0fbf88e21ba Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 22 Mar 2019 12:32:00 -0400 Subject: [PATCH 26/36] Roll back to res_search and res_init Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 11 +++++------ src/runtime/lookup_darwin.go | 12 ++++++------ src/runtime/lookup_darwin_386.s | 27 ++++++++++----------------- src/runtime/lookup_darwin_amd64.s | 16 +++++++--------- src/runtime/lookup_darwin_arm.s | 4 ++-- src/runtime/lookup_darwin_arm64.s | 4 ++-- 6 files changed, 32 insertions(+), 42 deletions(-) diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go index 673a086a11bc58..3a6a508a32e1ef 100644 --- a/src/net/cgo_darwin_stub.go +++ b/src/net/cgo_darwin_stub.go @@ -83,14 +83,13 @@ func cgoLookupPTR(ctx context.Context, addr string) (ptrs []string, err error, c func resolverGetResources(ctx context.Context, hostname string, rtype, class int32) ([]dnsmessage.Resource, error) { var byteHostname = []byte(hostname) var responseBuffer = [512]byte{} - var statp [71]uint64 - retcode := res_init(&statp) + retcode := res_init() if retcode < 0 { return nil, errors.New("could not initialize resolution data") } - retcode = res_nsearch(&statp, &byteHostname[0], class, rtype, &responseBuffer[0], 512) + retcode = res_search(&byteHostname[0], class, rtype, &responseBuffer[0], 512) if retcode < 0 { return nil, errors.New("could not complete domain resolution") } @@ -199,8 +198,8 @@ func parsePTRsFromResources(resources []dnsmessage.Resource) ([]string, error) { return answers, nil } -// res_init and res_nsearch are defined in runtimne/lookup_darwin.go +// res_init and res_search are defined in runtimne/lookup_darwin.go -func res_init(statp *[71]uint64) int32 +func res_init() int32 -func res_nsearch(statp *[71]uint64, dname *byte, class int32, rtype int32, answer *byte, anslen int32) int32 +func res_search(dname *byte, class int32, rtype int32, answer *byte, anslen int32) int32 diff --git a/src/runtime/lookup_darwin.go b/src/runtime/lookup_darwin.go index 166e84cd3c22e8..d218cfd4dda259 100644 --- a/src/runtime/lookup_darwin.go +++ b/src/runtime/lookup_darwin.go @@ -7,18 +7,18 @@ import ( //go:linkname res_init net.res_init //go:nosplit //go:cgo_unsafe_args -func res_init(statp *[71]uint64) int32 { +func res_init() int32 { return libcCall(unsafe.Pointer(funcPC(res_init_trampoline)), unsafe.Pointer(&statp)) } func res_init_trampoline() -//go:linkname res_nsearch net.res_nsearch +//go:linkname res_search net.res_search //go:nosplit //go:cgo_unsafe_args -func res_nsearch(statp *[71]uint64, dname *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { - return libcCall(unsafe.Pointer(funcPC(res_nsearch_trampoline)), unsafe.Pointer(&statp)) +func res_search(dname *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { + return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&statp)) } -func res_nsearch_trampoline() +func res_search_trampoline() -//go:cgo_import_dynamic libc_res_nsearch res_nsearch "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_res_search res_search "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic libc_res_init res_init "/usr/lib/libSystem.B.dylib" diff --git a/src/runtime/lookup_darwin_386.s b/src/runtime/lookup_darwin_386.s index f94feb5b30263d..bca4ca718accc3 100644 --- a/src/runtime/lookup_darwin_386.s +++ b/src/runtime/lookup_darwin_386.s @@ -6,26 +6,22 @@ #include "go_tls.h" #include "textflag.h" -TEXT runtime·res_nsearch_trampoline(SB),NOSPLIT,$0 +TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 PUSHL BP MOVL SP, BP SUBL $24, SP MOVL 32(SP), CX - MOVL 20(CX), AX // arg 6 anslen - MOVL AX, 20(SP) - MOVL 16(CX), AX // arg 5 answer + MOVL 16(CX), AX // arg 5 anslen MOVL AX, 16(SP) - MOVL 8(CX), AX // arg 3 class - MOVL AX, 8(SP) - MOVL 12(CX), AX // arg 4 type + MOVL 12(CX), AX // arg 4 answer MOVL AX, 12(SP) - MOVL 4(CX), AX // arg 2 name - MOVL AX, 4(SP) - MOVL 4(CX), AX // arg 2 name + MOVL 8(CX), AX // arg 3 type + MOVL AX, 8(SP) + MOVL 4(CX), AX // arg 2 class MOVL AX, 4(SP) - MOVL 0(CX), AX // arg 1 statp + MOVL 0(CX), AX // arg 1 name MOVL AX, 0(SP) - CALL libc_res_nsearch(SB) + CALL libc_res_search(SB) XORL DX, DX CMPL AX, $-1 JNE ok @@ -37,14 +33,11 @@ ok: POPL BP RET -TEXT runtime·res_ninit_trampoline(SB),NOSPLIT,$0 +TEXT runtime·res_init_trampoline(SB),NOSPLIT,$0 PUSHL BP MOVL SP, BP SUBL $8, SP - MOVL 16(SP), CX - MOVL 0(CX), AX // arg 1 statp - MOVL AX, 0(SP) - CALL libc_res_ninit(SB) + CALL libc_res_init(SB) XORL DX, DX CMPL AX, $-1 JNE ok diff --git a/src/runtime/lookup_darwin_amd64.s b/src/runtime/lookup_darwin_amd64.s index a0a9d6194f51c6..ffdb143b06263d 100644 --- a/src/runtime/lookup_darwin_amd64.s +++ b/src/runtime/lookup_darwin_amd64.s @@ -9,7 +9,6 @@ TEXT runtime·res_init_trampoline(SB),NOSPLIT,$0 PUSHQ BP MOVQ SP, BP - MOVQ 0(DI), DI // arg 1 statp CALL libc_res_init(SB) XORL DX, DX CMPQ AX, $-1 @@ -21,16 +20,15 @@ ok: POPQ BP RET -TEXT runtime·res_nsearch_trampoline(SB),NOSPLIT,$0 +TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 PUSHQ BP MOVQ SP, BP - MOVL 32(DI), R9 // arg 6 anslen - MOVQ 24(DI), R8 // arg 5 answer - MOVL 12(DI), DX // arg 3 class - MOVQ 16(DI), CX // arg 4 type - MOVQ 8(DI), SI // arg 2 name - MOVQ 0(DI), DI // arg 1 statp - CALL libc_res_nsearch(SB) + MOVL 24(DI), R8 // arg 5 anslen + MOVQ 16(DI), CX // arg 4 answer + MOVL 12(DI), DX // arg 3 type + MOVL 8(DI), SI // arg 2 class + MOVQ 0(DI), DI // arg 1 name + CALL libc_res_search(SB) XORL DX, DX CMPQ AX, $-1 JNE ok diff --git a/src/runtime/lookup_darwin_arm.s b/src/runtime/lookup_darwin_arm.s index 7c2f4c17695468..9f3648203dcfe9 100644 --- a/src/runtime/lookup_darwin_arm.s +++ b/src/runtime/lookup_darwin_arm.s @@ -14,12 +14,12 @@ // for resolution. This will just exit with nominal // exit code -TEXT runtime·res_nsearch_trampoline(SB),NOSPLIT,$0 +TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 MOVW $90, R0 BL libc_exit(SB) RET -TEXT runtime·res_ninit_trampoline(SB),NOSPLIT,$0 +TEXT runtime·res_init_trampoline(SB),NOSPLIT,$0 MOVW $91, R0 BL libc_exit(SB) RET diff --git a/src/runtime/lookup_darwin_arm64.s b/src/runtime/lookup_darwin_arm64.s index 25bd36ed1a1ffc..14760f0a1511d4 100644 --- a/src/runtime/lookup_darwin_arm64.s +++ b/src/runtime/lookup_darwin_arm64.s @@ -10,12 +10,12 @@ // for resolution. This will just exit with nominal // exit code -TEXT runtime·res_nsearch_trampoline(SB),NOSPLIT,$0 +TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 MOVW $80, R0 BL libc_exit(SB) RET -TEXT runtime·res_ninit_trampoline(SB),NOSPLIT,$0 +TEXT runtime·res_init_trampoline(SB),NOSPLIT,$0 MOVW $81, R0 BL libc_exit(SB) RET From 808f8be39673daa9d6bc172aebce574aa394734c Mon Sep 17 00:00:00 2001 From: grant Date: Mon, 25 Mar 2019 17:19:36 -0400 Subject: [PATCH 27/36] Add sync.Once to res_init call and fix import Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 10 ++++++++-- src/net/lookup_unix.go | 2 +- src/runtime/lookup_darwin.go | 4 ++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go index 3a6a508a32e1ef..38243b2b440fa7 100644 --- a/src/net/cgo_darwin_stub.go +++ b/src/net/cgo_darwin_stub.go @@ -10,8 +10,9 @@ package net import ( "context" "errors" + "sync" - "internal/x/net/dns/dnsmessage" + "golang.org/x/net/dns/dnsmessage" ) func cgoLookupHost(ctx context.Context, name string) (addrs []string, err error, completed bool) { @@ -78,13 +79,18 @@ func cgoLookupPTR(ctx context.Context, addr string) (ptrs []string, err error, c return ptrs, nil, true } +var resInitOnce sync.Once + // resolverGetResources will make a call to the 'res_search' routine in libSystem // and parse the output as a slice of resource resources which can then be parsed func resolverGetResources(ctx context.Context, hostname string, rtype, class int32) ([]dnsmessage.Resource, error) { var byteHostname = []byte(hostname) var responseBuffer = [512]byte{} - retcode := res_init() + var retcode int32 + resInitOnce.Do(func() { + retcode = res_init() + }) if retcode < 0 { return nil, errors.New("could not initialize resolution data") } diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index 6543f121a738f2..9055826d405c62 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -12,7 +12,7 @@ import ( "sync" "syscall" - "internal/x/net/dns/dnsmessage" + "golang.org/x/net/dns/dnsmessage" ) var onceReadProtocols sync.Once diff --git a/src/runtime/lookup_darwin.go b/src/runtime/lookup_darwin.go index d218cfd4dda259..5f46a8cc320a84 100644 --- a/src/runtime/lookup_darwin.go +++ b/src/runtime/lookup_darwin.go @@ -8,7 +8,7 @@ import ( //go:nosplit //go:cgo_unsafe_args func res_init() int32 { - return libcCall(unsafe.Pointer(funcPC(res_init_trampoline)), unsafe.Pointer(&statp)) + return libcCall(unsafe.Pointer(funcPC(res_init_trampoline)), nil) } func res_init_trampoline() @@ -16,7 +16,7 @@ func res_init_trampoline() //go:nosplit //go:cgo_unsafe_args func res_search(dname *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { - return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&statp)) + return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&dname)) } func res_search_trampoline() From cea6b6f4f61f779cddd81868eb51fda25eae4208 Mon Sep 17 00:00:00 2001 From: grant Date: Tue, 26 Mar 2019 17:34:36 -0400 Subject: [PATCH 28/36] Fix style issues Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 36 +++++++++++++++++------------------- src/net/cgo_stub.go | 10 +++------- src/net/conf.go | 11 ++++------- 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go index 38243b2b440fa7..7c39420a9bb29b 100644 --- a/src/net/cgo_darwin_stub.go +++ b/src/net/cgo_darwin_stub.go @@ -79,28 +79,31 @@ func cgoLookupPTR(ctx context.Context, addr string) (ptrs []string, err error, c return ptrs, nil, true } -var resInitOnce sync.Once +var ( + resInitOnce sync.Once + retcode int32 +) // resolverGetResources will make a call to the 'res_search' routine in libSystem // and parse the output as a slice of resource resources which can then be parsed func resolverGetResources(ctx context.Context, hostname string, rtype, class int32) ([]dnsmessage.Resource, error) { - var byteHostname = []byte(hostname) - var responseBuffer = [512]byte{} - var retcode int32 resInitOnce.Do(func() { retcode = res_init() }) if retcode < 0 { - return nil, errors.New("could not initialize resolution data") + return nil, errors.New("could not initialize name resolver data") } - retcode = res_search(&byteHostname[0], class, rtype, &responseBuffer[0], 512) + var byteHostname = []byte(hostname) + var responseBuffer [512]byte + + retcode = res_search(&byteHostname[0], class, rtype, &responseBuffer[0], len(responseBuffer)) if retcode < 0 { return nil, errors.New("could not complete domain resolution") } - msg := &dnsmessage.Message{} + var msg dnsmessage.Message err := msg.Unpack(responseBuffer[:]) if err != nil { return nil, err @@ -131,13 +134,11 @@ func parseHostsFromResources(resources []dnsmessage.Resource) ([]string, error) for i := range resources { switch resources[i].Header.Type { case dnsmessage.TypeA: - b, ok := resources[i].Body.(*dnsmessage.AResource) - if !ok { - return nil, errors.New("could not parse A resource record") - } + b := resources[i].Body.(*dnsmessage.AResource) + answers = append(answers, string(b.A[:])) case dnsmessage.TypeAAAA: - b, ok := resources[i].Body.(*dnsmessage.AAAAResource) + b := resources[i].Body.(*dnsmessage.AAAAResource) if !ok { return nil, errors.New("could not parse AAAA resource record") } @@ -155,14 +156,14 @@ func parseIPsFromResources(resources []dnsmessage.Resource) ([]IPAddr, error) { for i := range resources { switch resources[i].Header.Type { case dnsmessage.TypeA: - b, ok := resources[i].Body.(*dnsmessage.AResource) + b := resources[i].Body.(*dnsmessage.AResource) if !ok { return nil, errors.New("could not parse A resource record") } ip := parseIPv4(string(b.A[:])) answers = append(answers, IPAddr{IP: ip}) case dnsmessage.TypeAAAA: - b, ok := resources[i].Body.(*dnsmessage.AAAAResource) + b := resources[i].Body.(*dnsmessage.AAAAResource) if !ok { return nil, errors.New("could not parse AAAA resource record") } @@ -191,10 +192,7 @@ func parsePTRsFromResources(resources []dnsmessage.Resource) ([]string, error) { for i := range resources { switch resources[i].Header.Type { case dnsmessage.TypePTR: - p, ok := resources[0].Body.(*dnsmessage.PTRResource) - if !ok { - return nil, errors.New("could not parse PTR record") - } + p := resources[0].Body.(*dnsmessage.PTRResource) answers = append(answers, p.PTR.String()) default: return nil, errors.New("could not parse a PTR response from message buffer") @@ -204,7 +202,7 @@ func parsePTRsFromResources(resources []dnsmessage.Resource) ([]string, error) { return answers, nil } -// res_init and res_search are defined in runtimne/lookup_darwin.go +// res_init and res_search are defined in runtime/lookup_darwin.go func res_init() int32 diff --git a/src/net/cgo_stub.go b/src/net/cgo_stub.go index 09185d8b949d95..aa15ab4dc1043d 100644 --- a/src/net/cgo_stub.go +++ b/src/net/cgo_stub.go @@ -2,18 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build netgo !cgo +// +build !cgo netgo // +build !darwin package net -import ( - "context" -) +import "context" -func init() { - netGo = true -} +func init() { netGo = true } type addrinfoErrno int diff --git a/src/net/conf.go b/src/net/conf.go index 7906190eb01aee..1c88f096bad331 100644 --- a/src/net/conf.go +++ b/src/net/conf.go @@ -70,13 +70,10 @@ func initConfVal() { // their own DNS requests. So always use cgo instead, which // avoids that. if runtime.GOOS == "darwin" { - - // only use netgo if user specifies to - if dnsMode == "go" { - confVal.netGo = true - } else { - confVal.netGo = false - } + // Normally we force netGo to be true if building without cgo enabled. + // On Darwin, we can call libc even if cgo is not enabled, so only set netGo to true + // if explicitly requested. + confVal.netGo = dnsMode == "go" confVal.forceCgoLookupHost = true return From c238eb9bf11e7cd5d4f5bab1701bdc201cdabda4 Mon Sep 17 00:00:00 2001 From: grant Date: Tue, 26 Mar 2019 18:33:59 -0400 Subject: [PATCH 29/36] Fix undefined variable issue Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go index 7c39420a9bb29b..fdf74c5d4affa1 100644 --- a/src/net/cgo_darwin_stub.go +++ b/src/net/cgo_darwin_stub.go @@ -98,7 +98,7 @@ func resolverGetResources(ctx context.Context, hostname string, rtype, class int var byteHostname = []byte(hostname) var responseBuffer [512]byte - retcode = res_search(&byteHostname[0], class, rtype, &responseBuffer[0], len(responseBuffer)) + retcode = res_search(&byteHostname[0], class, rtype, &responseBuffer[0], int32(len(responseBuffer))) if retcode < 0 { return nil, errors.New("could not complete domain resolution") } @@ -135,13 +135,9 @@ func parseHostsFromResources(resources []dnsmessage.Resource) ([]string, error) switch resources[i].Header.Type { case dnsmessage.TypeA: b := resources[i].Body.(*dnsmessage.AResource) - answers = append(answers, string(b.A[:])) case dnsmessage.TypeAAAA: b := resources[i].Body.(*dnsmessage.AAAAResource) - if !ok { - return nil, errors.New("could not parse AAAA resource record") - } answers = append(answers, string(b.AAAA[:])) default: return nil, errors.New("could not parse an A or AAAA response from message buffer") @@ -157,16 +153,10 @@ func parseIPsFromResources(resources []dnsmessage.Resource) ([]IPAddr, error) { switch resources[i].Header.Type { case dnsmessage.TypeA: b := resources[i].Body.(*dnsmessage.AResource) - if !ok { - return nil, errors.New("could not parse A resource record") - } ip := parseIPv4(string(b.A[:])) answers = append(answers, IPAddr{IP: ip}) case dnsmessage.TypeAAAA: b := resources[i].Body.(*dnsmessage.AAAAResource) - if !ok { - return nil, errors.New("could not parse AAAA resource record") - } ip, zone := parseIPv6Zone(string(b.AAAA[:])) answers = append(answers, IPAddr{IP: ip, Zone: zone}) default: From 8c9efdd2387194308c77c60c62e0f3afe6248320 Mon Sep 17 00:00:00 2001 From: grant Date: Thu, 28 Mar 2019 16:24:04 -0400 Subject: [PATCH 30/36] Add second return to res_search, standardize arm return code Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 14 ++++++++------ src/runtime/lookup_darwin.go | 11 +++++++++-- src/runtime/lookup_darwin_386.s | 32 +++++++++++++++---------------- src/runtime/lookup_darwin_amd64.s | 28 +++++++++++++-------------- src/runtime/lookup_darwin_arm64.s | 4 ++-- 5 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go index fdf74c5d4affa1..6777bec3f48cbc 100644 --- a/src/net/cgo_darwin_stub.go +++ b/src/net/cgo_darwin_stub.go @@ -81,7 +81,7 @@ func cgoLookupPTR(ctx context.Context, addr string) (ptrs []string, err error, c var ( resInitOnce sync.Once - retcode int32 + errCode int32 ) // resolverGetResources will make a call to the 'res_search' routine in libSystem @@ -89,17 +89,19 @@ var ( func resolverGetResources(ctx context.Context, hostname string, rtype, class int32) ([]dnsmessage.Resource, error) { resInitOnce.Do(func() { - retcode = res_init() + errCode = res_init() }) - if retcode < 0 { + if errCode < 0 { return nil, errors.New("could not initialize name resolver data") } var byteHostname = []byte(hostname) var responseBuffer [512]byte + var size int32 - retcode = res_search(&byteHostname[0], class, rtype, &responseBuffer[0], int32(len(responseBuffer))) - if retcode < 0 { + size, errCode = res_search(&byteHostname[0], class, rtype, &responseBuffer[0], int32(len(responseBuffer))) + if errCode != 0 { + //TODO: translate error code return nil, errors.New("could not complete domain resolution") } @@ -196,4 +198,4 @@ func parsePTRsFromResources(resources []dnsmessage.Resource) ([]string, error) { func res_init() int32 -func res_search(dname *byte, class int32, rtype int32, answer *byte, anslen int32) int32 +func res_search(dname *byte, class int32, rtype int32, answer *byte, anslen int32) (int32, int32) diff --git a/src/runtime/lookup_darwin.go b/src/runtime/lookup_darwin.go index 5f46a8cc320a84..2b2ca97fed68b5 100644 --- a/src/runtime/lookup_darwin.go +++ b/src/runtime/lookup_darwin.go @@ -15,8 +15,15 @@ func res_init_trampoline() //go:linkname res_search net.res_search //go:nosplit //go:cgo_unsafe_args -func res_search(dname *byte, class int32, rtype int32, answer *byte, anslen int32) int32 { - return libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&dname)) +func res_search(dname *byte, class int32, rtype int32, answer *byte, anslen int32) (int32, int32) { + args := struct { + dname *byte + class, rtype int32 + answer *byte + anslen, retSize, retErr int32 + }{dname, class, rtype, answer, anslen, 0, 0} + libcCall(unsafe.Pointer(funcPC(res_search_trampoline)), unsafe.Pointer(&args)) + return args.retSize, args.retErr } func res_search_trampoline() diff --git a/src/runtime/lookup_darwin_386.s b/src/runtime/lookup_darwin_386.s index bca4ca718accc3..4995e51df5b5ee 100644 --- a/src/runtime/lookup_darwin_386.s +++ b/src/runtime/lookup_darwin_386.s @@ -6,6 +6,19 @@ #include "go_tls.h" #include "textflag.h" +TEXT runtime·res_init_trampoline(SB),NOSPLIT,$0 + PUSHL BP + MOVL SP, BP + SUBL $8, SP + CALL libc_res_init(SB) + CMPL AX, $-1 + JNE ok + CALL libc_error(SB) +ok: + MOVL BP, SP + POPL BP + RET + TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 PUSHL BP MOVL SP, BP @@ -26,25 +39,12 @@ TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 CMPL AX, $-1 JNE ok CALL libc_error(SB) - MOVL (AX), DX // errno - XORL AX, AX -ok: - MOVL BP, SP - POPL BP - RET - -TEXT runtime·res_init_trampoline(SB),NOSPLIT,$0 - PUSHL BP - MOVL SP, BP - SUBL $8, SP - CALL libc_res_init(SB) - XORL DX, DX - CMPL AX, $-1 - JNE ok - CALL libc_error(SB) MOVL (AX), DX XORL AX, AX ok: + MOVL 32(SP), CX + MOVL AX, 20(CX) + MOVL DX, 24(CX) MOVL BP, SP POPL BP RET diff --git a/src/runtime/lookup_darwin_amd64.s b/src/runtime/lookup_darwin_amd64.s index ffdb143b06263d..fa9b568d858941 100644 --- a/src/runtime/lookup_darwin_amd64.s +++ b/src/runtime/lookup_darwin_amd64.s @@ -10,12 +10,9 @@ TEXT runtime·res_init_trampoline(SB),NOSPLIT,$0 PUSHQ BP MOVQ SP, BP CALL libc_res_init(SB) - XORL DX, DX CMPQ AX, $-1 JNE ok CALL libc_error(SB) - MOVLQSX (AX), DX // errno - XORL AX, AX ok: POPQ BP RET @@ -23,18 +20,21 @@ ok: TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 PUSHQ BP MOVQ SP, BP - MOVL 24(DI), R8 // arg 5 anslen - MOVQ 16(DI), CX // arg 4 answer - MOVL 12(DI), DX // arg 3 type - MOVL 8(DI), SI // arg 2 class - MOVQ 0(DI), DI // arg 1 name + MOVQ DI, BX // move DI into BX to preserve struct addr + MOVL 24(BX), R8 // arg 5 anslen + MOVQ 16(BX), CX // arg 4 answer + MOVL 12(BX), DX // arg 3 type + MOVL 8(BX), SI // arg 2 class + MOVQ 0(BX), DI // arg 1 name CALL libc_res_search(SB) - XORL DX, DX - CMPQ AX, $-1 - JNE ok - CALL libc_error(SB) - MOVLQSX (AX), DX // errno - XORL AX, AX + XORL DX, DX + CMPQ AX, $-1 + JNE ok + CALL libc_error(SB) + MOVLQSX (AX), DX // move return from libc_error into DX + XORL AX, AX // size on error is 0 ok: + MOVQ AX, 28(BX) // size + MOVQ DX, 32(BX) // error code POPQ BP RET diff --git a/src/runtime/lookup_darwin_arm64.s b/src/runtime/lookup_darwin_arm64.s index 14760f0a1511d4..1bfe931c7ddeae 100644 --- a/src/runtime/lookup_darwin_arm64.s +++ b/src/runtime/lookup_darwin_arm64.s @@ -11,11 +11,11 @@ // exit code TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 - MOVW $80, R0 + MOVW $90, R0 BL libc_exit(SB) RET TEXT runtime·res_init_trampoline(SB),NOSPLIT,$0 - MOVW $81, R0 + MOVW $91, R0 BL libc_exit(SB) RET From d69aca60bb71c690bfc496d6738b03a5b02d3d21 Mon Sep 17 00:00:00 2001 From: grant Date: Thu, 28 Mar 2019 17:20:59 -0400 Subject: [PATCH 31/36] add return code to error message from res_search Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go index 6777bec3f48cbc..6aafefb7fe11e5 100644 --- a/src/net/cgo_darwin_stub.go +++ b/src/net/cgo_darwin_stub.go @@ -101,8 +101,7 @@ func resolverGetResources(ctx context.Context, hostname string, rtype, class int size, errCode = res_search(&byteHostname[0], class, rtype, &responseBuffer[0], int32(len(responseBuffer))) if errCode != 0 { - //TODO: translate error code - return nil, errors.New("could not complete domain resolution") + return nil, errors.New("could not complete domain resolution return code " + errCode) } var msg dnsmessage.Message From 1f3c262903bc7196988d5694d11921d10de7cdcf Mon Sep 17 00:00:00 2001 From: grant Date: Thu, 28 Mar 2019 20:58:52 -0400 Subject: [PATCH 32/36] remove whitespace Signed-off-by: grant --- src/runtime/lookup_darwin_amd64.s | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/lookup_darwin_amd64.s b/src/runtime/lookup_darwin_amd64.s index fa9b568d858941..bfe70c2d01cc51 100644 --- a/src/runtime/lookup_darwin_amd64.s +++ b/src/runtime/lookup_darwin_amd64.s @@ -27,10 +27,10 @@ TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 MOVL 8(BX), SI // arg 2 class MOVQ 0(BX), DI // arg 1 name CALL libc_res_search(SB) - XORL DX, DX - CMPQ AX, $-1 - JNE ok - CALL libc_error(SB) + XORL DX, DX + CMPQ AX, $-1 + JNE ok + CALL libc_error(SB) MOVLQSX (AX), DX // move return from libc_error into DX XORL AX, AX // size on error is 0 ok: From a9ccfe84a3dea336516a4e6752d0646ab0404a62 Mon Sep 17 00:00:00 2001 From: grant Date: Fri, 29 Mar 2019 11:24:08 -0400 Subject: [PATCH 33/36] fix mismatched string and int32 Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go index 6aafefb7fe11e5..550f8accabfa48 100644 --- a/src/net/cgo_darwin_stub.go +++ b/src/net/cgo_darwin_stub.go @@ -101,7 +101,7 @@ func resolverGetResources(ctx context.Context, hostname string, rtype, class int size, errCode = res_search(&byteHostname[0], class, rtype, &responseBuffer[0], int32(len(responseBuffer))) if errCode != 0 { - return nil, errors.New("could not complete domain resolution return code " + errCode) + return nil, errors.New("could not complete domain resolution return code " + string(errCode)) } var msg dnsmessage.Message From a9ff324b8d7049ea2f153121f8d3b845a1772e31 Mon Sep 17 00:00:00 2001 From: grant Date: Mon, 1 Apr 2019 17:15:53 -0400 Subject: [PATCH 34/36] define stub type and methods for vet Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go index 550f8accabfa48..1a50042f857fd0 100644 --- a/src/net/cgo_darwin_stub.go +++ b/src/net/cgo_darwin_stub.go @@ -15,6 +15,12 @@ import ( "golang.org/x/net/dns/dnsmessage" ) +type addrinfoErrno int + +func (eai addrinfoErrno) Error() string { return "" } +func (eai addrinfoErrno) Temporary() bool { return false } +func (eai addrinfoErrno) Timeout() bool { return false } + func cgoLookupHost(ctx context.Context, name string) (addrs []string, err error, completed bool) { resources, err := resolverGetResources(ctx, name, int32(dnsmessage.TypeALL), int32(dnsmessage.ClassINET)) if err != nil { @@ -103,6 +109,9 @@ func resolverGetResources(ctx context.Context, hostname string, rtype, class int if errCode != 0 { return nil, errors.New("could not complete domain resolution return code " + string(errCode)) } + if size == 0 { + return nil, errors.New("received empty response") + } var msg dnsmessage.Message err := msg.Unpack(responseBuffer[:]) From ce26e646918224ff467cc183dd0dbb4e212bc67f Mon Sep 17 00:00:00 2001 From: grant Date: Mon, 1 Apr 2019 17:52:21 -0400 Subject: [PATCH 35/36] trivial change Signed-off-by: grant --- src/net/cgo_darwin_stub.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/cgo_darwin_stub.go b/src/net/cgo_darwin_stub.go index 1a50042f857fd0..544df7fd6c1b0b 100644 --- a/src/net/cgo_darwin_stub.go +++ b/src/net/cgo_darwin_stub.go @@ -34,7 +34,7 @@ func cgoLookupHost(ctx context.Context, name string) (addrs []string, err error, } func cgoLookupPort(ctx context.Context, network, service string) (port int, err error, completed bool) { - port, err = goLookupPort(network, service) // just use netgo lookup + port, err = goLookupPort(network, service) // we can just use netgo lookup return port, err, err == nil } From 3c3ff6bfa7e4811f206f3b119a867c841a016e10 Mon Sep 17 00:00:00 2001 From: grant Date: Wed, 3 Apr 2019 10:20:09 -0400 Subject: [PATCH 36/36] Add copyright and fix grammar of comments Signed-off-by: grant --- src/runtime/lookup_darwin.go | 4 ++++ src/runtime/lookup_darwin_arm.s | 6 +++--- src/runtime/lookup_darwin_arm64.s | 6 +++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/runtime/lookup_darwin.go b/src/runtime/lookup_darwin.go index 2b2ca97fed68b5..c39b937ccfc554 100644 --- a/src/runtime/lookup_darwin.go +++ b/src/runtime/lookup_darwin.go @@ -1,3 +1,7 @@ +// Copyright 2019 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 runtime import ( diff --git a/src/runtime/lookup_darwin_arm.s b/src/runtime/lookup_darwin_arm.s index 9f3648203dcfe9..bf69d212136907 100644 --- a/src/runtime/lookup_darwin_arm.s +++ b/src/runtime/lookup_darwin_arm.s @@ -10,9 +10,9 @@ #include "go_tls.h" #include "textflag.h" -// On darwin/arm, the runtime always use runtime/cgo -// for resolution. This will just exit with nominal -// exit code +// On darwin/arm, the runtime always uses runtime/cgo +// for resolution. This will just exit with a nominal +// exit code. TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 MOVW $90, R0 diff --git a/src/runtime/lookup_darwin_arm64.s b/src/runtime/lookup_darwin_arm64.s index 1bfe931c7ddeae..31061e15c032b9 100644 --- a/src/runtime/lookup_darwin_arm64.s +++ b/src/runtime/lookup_darwin_arm64.s @@ -6,9 +6,9 @@ #include "go_tls.h" #include "textflag.h" -// On darwin/arm, the runtime always use runtime/cgo -// for resolution. This will just exit with nominal -// exit code +// On darwin/arm, the runtime always uses runtime/cgo +// for resolution. This will just exit with a nominal +// exit code. TEXT runtime·res_search_trampoline(SB),NOSPLIT,$0 MOVW $90, R0