Open halseth opened 4 years ago
/cc @hyangah
Any more updates on this one? Android 11 was released today.
Reproduced in Yggdrasil project for net.Interfaces(): https://github.com/yggdrasil-network/yggdrasil-go/blob/master/src/multicast/multicast.go#L192
Any updates?
I'd also love an update, if possible. This is blocking a project of mine right now.
Anybody looking into this?
Seems to be caused by these new restrictions in Android 11:
The following is a list of the ways that apps are affected by this change:
NetworkInterface.getHardwareAddress()
returnsnull
for every interface.- Apps cannot use the
bind()
function onNETLINK_ROUTE
sockets.- The
ip
command does not return information about interfaces.- Apps cannot send
RTM_GETLINK
messages.
https://developer.android.com/training/articles/user-data-ids#mac-11-plus
https://developer.android.com/distribute/best-practices/develop/target-sdk
In August 2021, new apps in the Google Play Store will be required to target API level 30. In November 2021, updates to existing apps in the Google Play Store will be required to target API level 30.
Any updates on this one? This fix did not work for us: Catfriend1/syncthing-android#800
Hello golang dev team, any update on this issue? This is blocking the Android 11 compatibility of my app :/. Thanks!
We ended up developing an alternative using Android APIs, which we call instead of getInterfaceAddrs(). https://github.com/tailscale/tailscale-android/pull/21
Great, will take a look and see if I can circumvent my issue with this . Thanks!
Sent from myMail for iOS
Thursday, 9 December 2021 14:39 -0600 from @. @.>:
We ended up developing an alternative using Android APIs, which we call instead of getInterfaceAddrs(). tailscale/tailscale-android#21 — You are receiving this because you commented. Reply to this email directly, view it on GitHub , or unsubscribe . Triage notifications on the go with GitHub Mobile for iOS or Android .
hello, any update on this?
I'm looking to use a go library inside an android app targeting API level 32. Code crashes on devices with API level >= 30 because of this reason (route ip+net: netlinkrib: permission denied).
I could downgrade to 29, but it's a hack. Go runtime should implement a workaround to fix the issue.
Hello there, no, I decided to go for the “ wait until golang devs fix it” route. If I go for fixing it myself I’ll end up maintaining too many dependencies forks. If your app is being published on Google Play you have no choice, you have to find a work around , if not, then just downgrade target api to 29 and you will be fine, not a hack actually , it’s still allowed ;)
And I agree this needs to be fixed from go runtime itself . Hope someone skilled enough can help with a fix/workaround soon 😬. Maybe we should start a bounty on this one hahaha
Sent from myMail for iOS
Thursday, 24 February 2022 11:46 -0600 from @. @.>: @.*** hello, any update on this?
I'm looking to use a go library inside an android app targeting API level 32. Code crashes on devices with API level >= 30 because of this reason (route ip+net: netlinkrib: permission denied). I could downgrade to 29, but it's a hack. Go runtime should implement a workaround to fix the issue. — Reply to this email directly, view it on GitHub , or unsubscribe . Triage notifications on the go with GitHub Mobile for iOS or Android . You are receiving this because you were mentioned. Message ID: <golang/go/issues/40569/1050103943 @ github . com>
Here is how I fix this x/mobile: Calling net.InterfaceAddrs() fails on Android SDK 30
issue to resolve IPFS in mobile issue like route ip+net: netlinkrib: permission denied with x/mobile/cmd/gomobile
as compile tools , ref to cmd/tailscale: implement getInterfaces + SDK 30 which use gioui.org
as compile tools.
MainApplication.java
Take react native project for example, in YOUR_PROJECT/android/app/src/main/AndroidManifest.xml
<application
android:name=".MainApplication"
so be the MainApplication.java
here.
import go.Seq;
...
@Override
public void onCreate() {
super.onCreate();
...
// setContext here, so that if RunOnJVM() with golang.org/x/mobile/app to call JAVA from GO,
// will not cause error "no current JVM"
Seq.setContext(getApplicationContext());
}
...
}
And also in MainApplication.java
import java.lang.StringBuilder;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
...
// To fix [x/mobile: Calling net.InterfaceAddrs() fails on Android SDK 30](https://github.com/golang/go/issues/40569)
// Ref to getInterfaces() in https://github.com/tailscale/tailscale-android/pull/21/files
//
// Returns details of the interfaces in the system, encoded as a single string for ease
// of JNI transfer over to the Go environment.
//
// Example:
// rmnet_data0 10 2000 true false false false false | fe80::4059:dc16:7ed3:9c6e%rmnet_data0/64
// dummy0 3 1500 true false false false false | fe80::1450:5cff:fe13:f891%dummy0/64
// wlan0 30 1500 true true false false true | fe80::2f60:2c82:4163:8389%wlan0/64 10.1.10.131/24
// r_rmnet_data0 21 1500 true false false false false | fe80::9318:6093:d1ad:ba7f%r_rmnet_data0/64
// rmnet_data2 12 1500 true false false false false | fe80::3c8c:44dc:46a9:9907%rmnet_data2/64
// r_rmnet_data1 22 1500 true false false false false | fe80::b6cd:5cb0:8ae6:fe92%r_rmnet_data1/64
// rmnet_data1 11 1500 true false false false false | fe80::51f2:ee00:edce:d68b%rmnet_data1/64
// lo 1 65536 true false true false false | ::1/128 127.0.0.1/8
// v4-rmnet_data2 68 1472 true true false true true | 192.0.0.4/32
//
// Where the fields are:
// name ifindex mtu isUp hasBroadcast isLoopback isPointToPoint hasMulticast | ip1/N ip2/N ip3/N;
String getInterfacesAsString() {
List<NetworkInterface> interfaces;
try {
interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
} catch (Exception e) {
return "";
}
StringBuilder sb = new StringBuilder("");
for (NetworkInterface nif : interfaces) {
try {
// Android doesn't have a supportsBroadcast() but the Go net.Interface wants
// one, so we say the interface has broadcast if it has multicast.
sb.append(String.format("%s %d %d %b %b %b %b %b |", nif.getName(),
nif.getIndex(), nif.getMTU(), nif.isUp(), nif.supportsMulticast(),
nif.isLoopback(), nif.isPointToPoint(), nif.supportsMulticast()));
for (InterfaceAddress ia : nif.getInterfaceAddresses()) {
// InterfaceAddress == hostname + "/" + IP
String[] parts = ia.toString().split("/", 0);
if (parts.length > 1) {
sb.append(String.format("%s/%d ", parts[1], ia.getNetworkPrefixLength()));
}
}
} catch (Exception e) {
// TODO(dgentry) should log the exception not silently suppress it.
continue;
}
sb.append("\n");
}
return sb.toString();
}
go.mod
Add
git.wow.st/gmp/jni v0.0.0-20200827154156-014cd5c7c4c0
inet.af/netaddr v0.0.0-20210721214506-ce7a8ad02cc1
go mod download
Above will download git.wow.st/gmp/jni
and inet.af/netaddr
into ~/go/pkg/mod/
, and modify go.mod
automatically.
go mod vendor
Above will remove vendor/
automatically then copy again from ~/go/pkg/mod/
.
If go mod download
modified go.mod
into
git.wow.st/gmp/jni v0.0.0-20200827154156-014cd5c7c4c0 // indirect
inet.af/netaddr v0.0.0-20210721214506-ce7a8ad02cc1 // indirect
then they will not be copied into vendor/
by go mod vendor
, so you can temporarily add
"git.wow.st/gmp/jni"
"inet.af/netaddr"
into one of your own .go
file, run go mod download
again, found // indirect
disappeared, reset your own .go
file, run go mod vendor
again, found they were copied into vendor/
.
vendor/github.com/multiformats/go-multiaddr/net/net.go
Replace
import (
"context"
"fmt"
"net"
ma "github.com/multiformats/go-multiaddr"
)
with
import (
"context"
"errors"
"fmt"
"net"
"runtime"
"strings"
"git.wow.st/gmp/jni"
"golang.org/x/mobile/app"
"inet.af/netaddr"
ma "github.com/multiformats/go-multiaddr"
)
And also in vendor/github.com/multiformats/go-multiaddr/net/net.go
, replace
// InterfaceMultiaddrs will return the addresses matching net.InterfaceAddrs
func InterfaceMultiaddrs() ([]ma.Multiaddr, error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
return nil, err
}
maddrs := make([]ma.Multiaddr, len(addrs))
for i, a := range addrs {
maddrs[i], err = FromNetAddr(a)
if err != nil {
return nil, err
}
}
return maddrs, nil
}
with
// InterfaceMultiaddrs will return the addresses matching net.InterfaceAddrs
func InterfaceMultiaddrs() ([]ma.Multiaddr, error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
if runtime.GOOS == "android" {
// To fix [x/mobile: Calling net.InterfaceAddrs() fails on Android SDK 30](https://github.com/golang/go/issues/40569)
addrs, err = getInterfaceAddrsFromAndroid()
if err != nil {
return nil, err
}
} else {
return nil, err
}
}
maddrs := make([]ma.Multiaddr, len(addrs))
for i, a := range addrs {
maddrs[i], err = FromNetAddr(a)
if err != nil {
return nil, err
}
}
return maddrs, nil
}
// Ref to getInterfaces() in https://github.com/tailscale/tailscale-android/pull/21/files
func getInterfaceAddrsFromAndroid() ([]net.Addr, error) {
var ifaceString string
// if use "gioui.org/app", ref to jni.Do() in https://github.com/tailscale/tailscale-android/pull/21/files
// if use "golang.org/x/mobile/app", use app.RunOnJVM() below
err := app.RunOnJVM(func(vm, env, ctx uintptr) error {
jniEnv := jni.EnvFor(env)
// cls := jni.FindClass(jniEnv, "YOUR/PACKAGE/NAME/CLASSNAME")
// m := jni.GetMethodID(jniEnv, cls, "getInterfacesAsString", "()Ljava/lang/String;")
// n, err := jni.CallStaticObjectMethod(jniEnv, cls, m)
// above `YOUR.PACKAGE.NAME` `CLASSNAME.java` sometimes will cause strange [java.lang.ClassNotFoundException: Didn't find class on path: dexpathlist](https://stackoverflow.com/questions/22399572/java-lang-classnotfoundexception-didnt-find-class-on-path-dexpathlist)
// so use below `MainApplication.java` comes from `<application android:name=".MainApplication"` in `YOUR_PROJECT/android/app/src/main/AndroidManifest.xml`
appCtx := jni.Object(ctx)
cls := jni.GetObjectClass(jniEnv, appCtx)
m := jni.GetMethodID(jniEnv, cls, "getInterfacesAsString", "()Ljava/lang/String;")
n, err := jni.CallObjectMethod(jniEnv, appCtx, m)
if err != nil {
return errors.New("getInterfacesAsString Method invocation failed")
}
ifaceString = jni.GoString(jniEnv, jni.String(n))
return nil
})
if err != nil {
return nil, err
}
var ifat []net.Addr
for _, iface := range strings.Split(ifaceString, "\n") {
// Example of the strings we're processing:
// wlan0 30 1500 true true false false true | fe80::2f60:2c82:4163:8389%wlan0/64 10.1.10.131/24
// r_rmnet_data0 21 1500 true false false false false | fe80::9318:6093:d1ad:ba7f%r_rmnet_data0/64
// mnet_data2 12 1500 true false false false false | fe80::3c8c:44dc:46a9:9907%rmnet_data2/64
if strings.TrimSpace(iface) == "" {
continue
}
fields := strings.Split(iface, "|")
if len(fields) != 2 {
// log.Printf("getInterfaces: unable to split %q", iface)
continue
}
addrs := strings.Trim(fields[1], " \n")
for _, addr := range strings.Split(addrs, " ") {
ip, err := netaddr.ParseIPPrefix(addr)
if err == nil {
ifat = append(ifat, ip.IPNet())
}
}
}
return ifat, nil
}
export ANDROID_NDK_HOME=~/tools/android-sdk/ndk/21.4.7075529
or
cd ~/tools/android-sdk/ndk
ln -s 21.4.7075529 ndk-bundle
21.4.7075529 is default in RN 0.66 and gradle 6.7.1
If r22 or higher, will cause
# golang.org/x/mobile/app
ld: error: duplicate symbol: display
Finally, you can continue your gomobile bind
work flow :yum:
PS: notice java.util.Locale.ROOT
as described below https://github.com/golang/go/issues/40569#issuecomment-1191823859
I did something similar for IPFS on Android as well, the project is https://github.com/AgregoreWeb/agregore-ipfs-daemon
Android Java code is here: https://github.com/AgregoreWeb/agregore-ipfs-daemon/blob/2a0798197769772be810947f2451c10fca03d1ca/get_interfaces.java
Parsing of interfaces string from Java is here: https://github.com/AgregoreWeb/agregore-ipfs-daemon/blob/2a0798197769772be810947f2451c10fca03d1ca/gateway/interfaces.go#L24
For anyone using the technique of having Java code pass a string with an interface list over to the Go code, we did find an issue after some time in the field.
For an Android phone in a Locale like Saudi Arabia which uses Hindu-Arabic numerals, the Java code will automatically format the decimal numbers using the locale-appropriate glyphs:
lo ١ ٦٥٥٣٦ true false true false false |
The receiving Go code cannot handle this. As these strings are purely internal to pass information between the Java runtime and Go environment, they will never be visible to the user. We addressed it by setting the locale in the Java code to always format the string in a way which the Go code can handle:
sb.append(String.format(java.util.Locale.ROOT, "%s %d %d %b %b %b %b %b |", nif.getName(),
The full PR to address it is in https://github.com/tailscale/tailscale-android/commit/fd42b4b3526a33338e6fa3f38ce332380139a860, the App.java file contains the relevant changes. We had also used a similar technique for DNS which required a similar fix but is not likely used in your system.
I did something similar for IPFS on Android as well, the project is https://github.com/AgregoreWeb/agregore-ipfs-daemon
Android Java code is here: https://github.com/AgregoreWeb/agregore-ipfs-daemon/blob/2a0798197769772be810947f2451c10fca03d1ca/get_interfaces.java
Parsing of interfaces string from Java is here: https://github.com/AgregoreWeb/agregore-ipfs-daemon/blob/2a0798197769772be810947f2451c10fca03d1ca/gateway/interfaces.go#L24
FYI @makeworld-the-better-one, in your code you replace the address parsing func: instead of using netaddr.ParseIPPrefix()
you use net.ParseCIDR()
. In my testing I found it did not give the same/desired result, however.
For example parsing net.ParseCIDR("10.150.6.112/16")
results in 10.150.0.0/16
.
I was able to work around this issue by calling getifaddrs
via cgo, which was preferable to using JNI for me. getifaddrs
is available in Android 7.0+.
Code in the gist here replicates most but not all of the stdlib functionality. Some data isn't populated. https://gist.github.com/iamcalledrob/67b710b1ca09465b906f04b91bb56e1f
Here is how I fix this
x/mobile: Calling net.InterfaceAddrs() fails on Android SDK 30
issue to resolve IPFS in mobile issue like route ip+net: netlinkrib: permission denied withx/mobile/cmd/gomobile
as compile tools , ref to cmd/tailscale: implement getInterfaces + SDK 30 which usegioui.org
as compile tools.
- In
MainApplication.java
Take react native project for example, in
YOUR_PROJECT/android/app/src/main/AndroidManifest.xml
<application android:name=".MainApplication"
so be the
MainApplication.java
here.import go.Seq;
@flyskywhy Hello there! I'm trying to solve the issue with your solution but Android Studio is giving me an error when importing go.Seq, maybe a stupid question but could not find an answer on google... how did you import the go.Seq dependence?
I was able to work around this issue by calling
getifaddrs
via cgo
Brilliant! Inspired by your work, I looked into how Android implements getifaddrs
, and found that RTM_GETADDR
is used for non-system apps as RTM_GETLINK
is forbidden [1]. On the other hand, there are already some code using RTM_GETADDR
in Go [2]. I collected relevant functions, removed usage of forbidden RTM_GETLINK
and got a working version:
[1] https://android.googlesource.com/platform/bionic/+/refs/tags/android-13.0.0_r18/libc/bionic/ifaddrs.cpp#315 [2] https://github.com/golang/go/blob/go1.20rc1/src/net/interface_linux.go#L124
I was able to work around this issue by calling
getifaddrs
via cgoBrilliant! Inspired by your work, I looked into how Android implements
getifaddrs
, and found thatRTM_GETADDR
is used for non-system apps asRTM_GETLINK
is forbidden [1]. On the other hand, there are already some code usingRTM_GETADDR
in Go [2]. I collected relevant functions, removed usage of forbiddenRTM_GETLINK
and got a working version:Pure-Go InterfaceAddrs() for newer Android [1] https://android.googlesource.com/platform/bionic/+/refs/tags/android-13.0.0_r18/libc/bionic/ifaddrs.cpp#315 [2] https://github.com/golang/go/blob/go1.20rc1/src/net/interface_linux.go#L124
I do it samething follew your ,but it does't work on ipfs kubo.
@yan12125 I haven't tested your code, but this approach looks great.
Unfortunately any of our workarounds don't work when using 3rd party libraries that call net.Interfaces() directly. This is a bit of a showstopper for a lot of networking code on Android.
I wonder if the net/interface pkg in stdlib can be updated to use these different syscalls for Android?
it does't work on ipfs kubo.
Any error meesages?
I wonder if the net/interface pkg in stdlib can be updated to use these different syscalls for Android?
I believe so. My example is modified from existing functions in stdlib, so those modifications should be compatible with stdlib. I can give it a try and create a pull request after finding time on reading contribution guidelines.
Sorry I made a mistake in my previous example - I tested on an app targeting older SDK. I updated the example after testing on newer SDK.
The key difference in the updated example is that I copied codes from syscall.NetlinkRIB
and remove the Bind
call on the netlink socket, which is forbidden by new Android. I assume binding is not necessary for net.InterfaceAddrs()
, but maybe necessary for some other scenarios. I'm not sure how to integrate such a change into Go stdlib. Maybe a new system call or a new argument for syscall.NetlinkRIB
?
Sorry I made a mistake in my previous example - I tested on an app targeting older SDK. I updated the example after testing on newer SDK.
The key difference in the updated example is that I copied codes from
syscall.NetlinkRIB
and remove theBind
call on the netlink socket, which is forbidden by new Android. I assume binding is not necessary fornet.InterfaceAddrs()
, but maybe necessary for some other scenarios. I'm not sure how to integrate such a change into Go stdlib. Maybe a new system call or a new argument forsyscall.NetlinkRIB
?
Would be great if you could do the PR. Wishing you the best of luck!
Thanks! But I'm not sure how to integrate those changes into stdlib in an elegant way as I've mentioned above.
Sorry I made a mistake in my previous example - I tested on an app targeting older SDK. I updated the example after testing on newer SDK.
The key difference in the updated example is that I copied codes from
syscall.NetlinkRIB
and remove theBind
call on the netlink socket, which is forbidden by new Android. I assume binding is not necessary fornet.InterfaceAddrs()
, but maybe necessary for some other scenarios. I'm not sure how to integrate such a change into Go stdlib. Maybe a new system call or a new argument forsyscall.NetlinkRIB
?
Could you provide more detail of remove bind?
Could you provide more detail of remove bind?
I removed https://github.com/golang/go/blob/go1.20rc1/src/syscall/netlink_linux.go#L59-L61, which violate the second rule mentioned at https://github.com/golang/go/issues/40569#issuecomment-806080888:
- Apps cannot use the
bind()
function onNETLINK_ROUTE
sockets.
As a result, the code fails on newer Android.
any update?
I did resovled this problem. No need java code, only need change some code of golang lib source code.
My android app intergrated ipfs ,but can not run on Android 13, this problem bother me for serveral months, I did resolve this problem yesterday.
@yiweichi , would you please explain how you did it? I'm trying with several proposals from others here but still struggling to make it work. I would like to have a NO JAVA code solution like you did :)
Brilliant! Inspired by your work, I looked into how Android implements
getifaddrs
, and found thatRTM_GETADDR
is used for non-system apps asRTM_GETLINK
is forbidden [1]. On the other hand, there are already some code usingRTM_GETADDR
in Go [2]. I collected relevant functions, removed usage of forbiddenRTM_GETLINK
and got a working version:Pure-Go InterfaceAddrs() for newer Android [1] https://android.googlesource.com/platform/bionic/+/refs/tags/android-13.0.0_r18/libc/bionic/ifaddrs.cpp#315 [2] https://github.com/golang/go/blob/go1.20rc1/src/net/interface_linux.go#L124
@yan12125 You're calling linux specific syscall constants (processor specific too I think). Can't work with this code on macOS (darwin syscall is different). There should be a platform independent way to implement this logic.
Brilliant! Inspired by your work, I looked into how Android implements
getifaddrs
, and found thatRTM_GETADDR
is used for non-system apps asRTM_GETLINK
is forbidden [1]. On the other hand, there are already some code usingRTM_GETADDR
in Go [2]. I collected relevant functions, removed usage of forbiddenRTM_GETLINK
and got a working version: Pure-Go InterfaceAddrs() for newer Android [1] https://android.googlesource.com/platform/bionic/+/refs/tags/android-13.0.0_r18/libc/bionic/ifaddrs.cpp#315 [2] https://github.com/golang/go/blob/go1.20rc1/src/net/interface_linux.go#L124@yan12125 You're calling linux specific syscall constants (processor specific too I think). Can't work with this code on macOS (darwin syscall is different). There should be a platform independent way to implement this logic.
It should work. Building Android apps on macOS will use Linux codes instead of Darwin ones.
@yan12125 I need to run and test the go library separately, this go code doesn't compile on macOS. Is there a tag I can add to avoid using this code when compiling in darwin.
You probably want something like // +build linux
.
@yan12125 Doesn't compile in editor (vscode) with build tags. How can I modify the go/src/net and /syscall libraries in my project like you did in Work-around ?
My android app intergrated ipfs ,but can not run on Android 13, this problem bother me for serveral months, I did resolve this problem yesterday.
can you please share your solution on how you resolved it?
@yan12125 Doesn't compile in editor (vscode) with build tags. How can I modify the go/src/net and /syscall libraries in my project like you did in Work-around ?
That commit is for go itself, not applications. Please check InterfaceAddrs
function in https://github.com/golang/go/issues/40569#issuecomment-1356266758 instead.
@yan12125 Can't use InterfaceAddrs function you shared in comment. I need to compile and test my go code on macOS before I can use it in my android app . Can you open/ ask for a pull request for the changes in work-around ?
In my test I saw that even if you set targetSdkVersion to 29, you'll still get the "route ip+net: netlinkrib: permission denied" error in Android 13+. Previous Android versions work OK.
Any updates?
Hello @yan12125 , I'm finally following your recommendation, downloaded go source code and modified both the netling_linux (removing the bind call) and replaced the content from interface_linux with your code, but I'm having the following issue while compiling from source in macOS:
ok go/ast 0.349s
--- FAIL: TestDependencies (1.32s)
deps_test.go:639: unexpected dependency: net imports [net]
FAIL
FAIL go/build 1.769s
Looks like the test is having a conflict with the net import. Did you do anything else beyond modifying such files?
Thanks!
@simbadMarino could you try this patch? It works with Go 1.21 rc1 source.
diff --git a/src/net/interface_linux.go b/src/net/interface_linux.go
index 9112ecc854c74..02b5a6047ed93 100644
--- a/src/net/interface_linux.go
+++ b/src/net/interface_linux.go
@@ -6,6 +6,7 @@ package net
import (
"os"
+ "runtime"
"syscall"
"unsafe"
)
@@ -133,7 +134,7 @@ func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
if ifi == nil {
var err error
ift, err = interfaceTable(0)
- if err != nil {
+ if err != nil && (runtime.GOOS != "android" || err != syscall.EACCES) {
return nil, err
}
}
@@ -153,6 +154,18 @@ loop:
break loop
case syscall.RTM_NEWADDR:
ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
+ if len(ift) == 0 && ifi == nil {
+ // if len(ift) == 0, the restriction on Android API 30+ applies, and RTM_GETLINK messages are prohibited
+ // Only querying all interfaces (ifi == nil) makes sense in this case.
+ attrs, err := syscall.ParseNetlinkRouteAttr(&m)
+ if err != nil {
+ return nil, os.NewSyscallError("parsenetlinkrouteattr", err)
+ }
+ ifa := newAddr(ifam, attrs)
+ if ifa != nil {
+ ifat = append(ifat, ifa)
+ }
+ }
if len(ift) != 0 || ifi.Index == int(ifam.Index) {
if len(ift) != 0 {
var err error
diff --git a/src/syscall/netlink_linux.go b/src/syscall/netlink_linux.go
index a503a0744005b..c4fba399a710d 100644
--- a/src/syscall/netlink_linux.go
+++ b/src/syscall/netlink_linux.go
@@ -7,6 +7,7 @@
package syscall
import (
+ "runtime"
"sync"
"unsafe"
)
@@ -65,7 +66,9 @@ func NetlinkRIB(proto, family int) ([]byte, error) {
defer Close(s)
sa := &SockaddrNetlink{Family: AF_NETLINK}
if err := Bind(s, sa); err != nil {
- return nil, err
+ if runtime.GOOS != "android" || err != EACCES {
+ return nil, err
+ }
}
wb := newNetlinkRouteRequest(proto, 1, family)
if err := Sendto(s, wb, 0, sa); err != nil {
@simbadMarino could you try this patch? It works with Go 1.21 rc1 source.
diff --git a/src/net/interface_linux.go b/src/net/interface_linux.go index 9112ecc854c74..02b5a6047ed93 100644 --- a/src/net/interface_linux.go +++ b/src/net/interface_linux.go @@ -6,6 +6,7 @@ package net import ( "os" + "runtime" "syscall" "unsafe" ) @@ -133,7 +134,7 @@ func interfaceAddrTable(ifi *Interface) ([]Addr, error) { if ifi == nil { var err error ift, err = interfaceTable(0) - if err != nil { + if err != nil && (runtime.GOOS != "android" || err != syscall.EACCES) { return nil, err } } @@ -153,6 +154,18 @@ loop: break loop case syscall.RTM_NEWADDR: ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0])) + if len(ift) == 0 && ifi == nil { + // if len(ift) == 0, the restriction on Android API 30+ applies, and RTM_GETLINK messages are prohibited + // Only querying all interfaces (ifi == nil) makes sense in this case. + attrs, err := syscall.ParseNetlinkRouteAttr(&m) + if err != nil { + return nil, os.NewSyscallError("parsenetlinkrouteattr", err) + } + ifa := newAddr(ifam, attrs) + if ifa != nil { + ifat = append(ifat, ifa) + } + } if len(ift) != 0 || ifi.Index == int(ifam.Index) { if len(ift) != 0 { var err error diff --git a/src/syscall/netlink_linux.go b/src/syscall/netlink_linux.go index a503a0744005b..c4fba399a710d 100644 --- a/src/syscall/netlink_linux.go +++ b/src/syscall/netlink_linux.go @@ -7,6 +7,7 @@ package syscall import ( + "runtime" "sync" "unsafe" ) @@ -65,7 +66,9 @@ func NetlinkRIB(proto, family int) ([]byte, error) { defer Close(s) sa := &SockaddrNetlink{Family: AF_NETLINK} if err := Bind(s, sa); err != nil { - return nil, err + if runtime.GOOS != "android" || err != EACCES { + return nil, err + } } wb := newNetlinkRouteRequest(proto, 1, family) if err := Sendto(s, wb, 0, sa); err != nil {
Thanks my friend, will give it a try tonight!
@yan12125 looks like its working! I can finally run BTFS on Android which is a go-ipfs fork, meaning those willing to run ipfs on android might find this patch handy, I tested with targetSdkVersion =30 & 33 and so far so good, thanks so much!! :)
@yan12125 looks like its working! I can finally run BTFS on Android which is a go-ipfs fork, meaning those willing to run ipfs on android might find this patch handy, I tested with targetSdkVersion =30 & 33 and so far so good, thanks so much!! :)
@simbadMarino Can you please elaborate on the full steps you took? I mean which files you modified, etc ? Sorry for being a noob here
@ehsan6sha , sure, below I describe what you need to do:
Download your prefered go version source code from: https://go.dev/dl/ (I downloaded go1.19.9 for instance) and unzip it into your home/yourusername
directory, if you already have a "go" folder remove it and later on unzip.
As per https://github.com/golang/go/issues/40569#issuecomment-1600898227 go to your recently unzipped go folder and find the src
folder and proceed to modify src/net/interface_linux.go & /src/syscall/netlink_linux.go files as described in the comment above.
Open a terminal window and go to your /home/yourusername/go/src, then build your modified go source by using sending $ ./all.bash
through the command line as per go source install instructions
After successful build, go to your golfing project and build your binaries as usual, change your targetSdkVersion to 30 or above in your build.gradle file, compile your project in Android Studio et voila!
As @yan12125 this is a super clean patch in the go source code to work around the issue, looks effective until now :). Next step its to upload my app to google play as final test hehe
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Calling
net.InterfaceAddrs()
fails on Android app targetting SDK version 30. Withbuild.gradle
looking like:Building the exact same app targetting SDK 29 works, and returns no error:
What did you expect to see?
Targetting SDK 30 would behave no differently.
What did you see instead?
Calling
net.InterfaceAddrs()
results in errorroute ip+net: netlinkrib: permission denied
when embedded in Android app targetting SDK 30 (R):