Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: support for android without cgo #8877

Open
crawshaw opened this issue Oct 6, 2014 · 14 comments
Open

net: support for android without cgo #8877

crawshaw opened this issue Oct 6, 2014 · 14 comments

Comments

@crawshaw
Copy link
Member

crawshaw commented Oct 6, 2014

It is possible to build Android OS binaries (not apps) without cgo. Those apps will fail
because the Android OS does not define /etc/resolve.conf. Some more details on #8020 and
the linked CL.

@jhleath
Copy link

jhleath commented Dec 27, 2014

Please note that this issue is present when building with cgo for Android and looking up DNS records not supported by getaddrinfo() such as SRV.

@mikioh
Copy link
Contributor

mikioh commented Jun 19, 2015

Note that there was an attempt: https://codereview.appspot.com/142200044/

@bradfitz
Copy link
Contributor

@crawshaw, what is your plan here? I'm not sure this needs to be a Go 1.5 issue. The proper way to do DNS on Android is to ask the local DNS proxy cache on the device for it, but that necessarily involves Binder calls and whatnot, and the details of how aren't a public interface AFAIU. (as least they weren't awhile ago).

The number of cases where you'd want a Go binary to do its own DNS lookups is rare. In those cases, we can do the whole getprop thing I suppose, but I'm not even sure I understand the advantages to not using cgo once our toolchain and linker are happier with Android stuff.

@crawshaw crawshaw modified the milestones: Go1.6, Go1.5 Jun 22, 2015
@crawshaw
Copy link
Member Author

Will look at in 1.6. Go binaries without cgo are not supported for apps, so this is low priority for me.

@rsc rsc modified the milestones: Unplanned, Go1.6 Nov 5, 2015
@AudriusButkevicius
Copy link
Contributor

It seems that some breeds of android manage to resolve DNS without cgo, while others fail.
I assume this is because some breeds have /etc/resolve.conf?

What's the right approach to fix this for the ones that don't?

@minux
Copy link
Member

minux commented Mar 26, 2016 via email

@yonderblue
Copy link

For the systems that do have /etc/resolve.conf is it appropriate to have a knob to use the Go resolver?

@bradfitz
Copy link
Contributor

@Gaillard, you're jumping on the wrong bug. Your question has nothing to do with Android, right? Also, the knob you want already exists. https://golang.org/pkg/net/#Resolver.PreferGo

@yonderblue
Copy link

I actually meant for android because its hard coded to not use the netdns value. But I appreciate the link I didn't know that was there.

@tmm1
Copy link
Contributor

tmm1 commented May 11, 2017

Here are some of hacks I've seen being used to enable DNS resolution w/out cgo on android:

OpenSilk/SyncthingAndroid@7a61add#diff-95f9e0a51eeab8f39703f35c52a5ed75
https://gist.github.com/ernesto-jimenez/8042366#file-go_android-patch-L44-L72

and my own variation for go 1.8:

commit 7d091b4af03b6db3b8d3eb60f1a4738c25330309
Author: Aman Gupta <aman@tmm1.net>
Date:   Thu May 11 16:00:43 2017 -0700

    add hack for dns lookups on android

diff --git a/src/net/dnsconfig_unix.go b/src/net/dnsconfig_unix.go
index 9c8108d11c..b3156d03ea 100644
--- a/src/net/dnsconfig_unix.go
+++ b/src/net/dnsconfig_unix.go
@@ -10,6 +10,8 @@ package net
 
 import (
 	"os"
+	"os/exec"
+	"strings"
 	"sync/atomic"
 	"time"
 )
@@ -33,8 +35,42 @@ type dnsConfig struct {
 	soffset    uint32        // used by serverOffset
 }
 
-// See resolv.conf(5) on a Linux machine.
 func dnsReadConfig(filename string) *dnsConfig {
+	if _, err := os.Stat("/system/bin/getprop"); err == nil {
+		return dnsReadConfigAndroid()
+	} else {
+		return dnsReadConfigUnix(filename)
+	}
+}
+
+func dnsReadConfigAndroid() *dnsConfig {
+	conf := &dnsConfig{
+		ndots:    1,
+		timeout:  5 * time.Second,
+		attempts: 2,
+		rotate:   false,
+	}
+
+	for _, prop := range []string{"net.dns1", "net.dns2"} {
+		out, err := exec.Command("/system/bin/getprop", prop).Output()
+		if err != nil {
+			continue
+		}
+		ip := strings.TrimSpace(string(out))
+		if ParseIP(ip) != nil {
+			conf.servers = append(conf.servers, JoinHostPort(ip, "53"))
+		}
+	}
+
+	if len(conf.servers) == 0 {
+		conf.servers = []string{"8.8.8.8:53", "8.8.4.4:53", "4.2.2.1:53"}
+	}
+
+	return conf
+}
+
+// See resolv.conf(5) on a Linux machine.
+func dnsReadConfigUnix(filename string) *dnsConfig {
 	conf := &dnsConfig{
 		ndots:    1,
 		timeout:  5 * time.Second,

@AudriusButkevicius
Copy link
Contributor

Another one to the list:

https://github.com/syncthing/syncthing-android/blob/master/patches/golang/all/dns.patch

@cs8425
Copy link

cs8425 commented Mar 20, 2019

I use some hack & reflect to overwrite defaultNS in net package.
It works on my Android 6.0, kernel 3.10.49, aarch64.
Only test with go version go1.11.5 linux/amd64
Build with GOOS=linux GOARCH=arm GOARM=7 and GOOS=linux GOARCH=arm64, and copy to Android then run.

The code:
https://gist.github.com/cs8425/107e01a0652f1f1f6e033b5b68364b5e

@makew0rld
Copy link

makew0rld commented Apr 18, 2022

I am also seeing this bug when building an Android SDK (.aar) using gomobile. Not sure if that's expected or not. It looks like maybe #10714 describes this but it says it was fixed and I'm still experiencing it.

@makew0rld
Copy link

I was not able to use the fix from @cs8425 for my Android AAR file. Instead I used a fix I got from here:

var dialer net.Dialer
net.DefaultResolver = &net.Resolver{
    PreferGo: false,
    Dial: func(context context.Context, _, _ string) (net.Conn, error) {
        conn, err := dialer.DialContext(context, "udp", "1.1.1.1:53")
        if err != nil {
            return nil, err
        }
        return conn, nil
    },
}

This fix worked for me, although obviously DNS is hardcoded instead of pulling the server address from the OS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests