androidandroid-ndknetlink

Cannot bind() netlink socket when targeting Android API 30


I have been using the following for quite some time to create a netlink socket:

NetLinkLocalNetworkInfo::NetLinkSocket::NetLinkSocket() :
fd(0)
{
    fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if(fd < 0)
    {
        throw std::runtime_error("Failed to create NetLink socket");
    }

    struct sockaddr_nl addr;
    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;

    int err = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
    if(err < 0)
    {
        close(fd);
        throw std::runtime_error("Failed to bind NetLink socket");
    }
}

This is used in part of the networking logic we have in place to perform automatic NAT traversal using ICE. When targeting API 30, the call to bind now returns -1 and errno is "Permission Denied".

A change in behavior for apps that target API 30 now means that bind() is a restricted call. (There's a document somewhere on the Google Developer page, but I'll be darned if I can find it again. It used to live here, but that page has changed since I first came across this issue a few months ago.) Supposedly this is supposed to affect all apps targeting API 30, but I've found that only apps targeting API 30 and running on a device (physical or emulator) running Android 11 are affected. My notes from when I first encountered this also mention that article suggesting using ConnectivityManager, but that would require either coming up with some way to pass the information down to native code or having the native code call into the Android platform code via JNI. I'm fine with either of those if that's what has to happen, but I'm wondering if there's another alternative I'm not aware of.

I also saw this similar question, but there is a link in one of the answers indicating that it should be possible, at least up until API 30.

Now that we aren't allowed to call bind(), what other options are available?


Solution

  • Found a solution to this. Turns out we were using NetLink sockets to discover network interface address information because ifaddrs was not available (or, not fully implemented, or something like that - nobody here could remember exactly why we couldn't use it) on Android at the time. As of API 24 ifaddrs is now available. We switched our implementation to use ifaddrs. As long as you're minimum supported version is API 24 or later you can do the same.