当针对Android API 30时,无法绑定netlink套接字(bind() netlink socket)。

4

我已经使用以下内容相当一段时间来创建netlink套接字:

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");
    }
}

这是我们在网络逻辑中使用的一部分,以使用ICE执行自动NAT遍历。当目标API为30时,对bind的调用现在返回-1,并且errno为“Permission Denied”。

针对API 30的应用程序行为变化意味着bind()现在是受限制的调用。(有一个文档在Google开发者页面上,但是我现在找不到它了。它曾经存在于此处,但自从我几个月前第一次遇到此问题以来,该页面已经更改。)据说这应该影响所有目标为API 30的应用程序,但我发现只有在运行Android 11的设备(物理或模拟器)上运行的目标为API 30的应用程序受到影响。我初次遇到此问题时的笔记还提到了那篇文章建议使用ConnectivityManager,但这将要求设计一些方法将信息传递到本机代码中或通过JNI使本机代码调用Android平台代码。如果必须这样做,我可以接受其中的任何一种,但我想知道是否有其他替代方法。

我还看到了这个类似问题,但其中一个答案中有一个链接表明,至少在API 30之前是可以实现的。

既然我们不允许调用bind(),那么还有哪些选项可用?


如果你不进行那个调用,为什么还需要绑定呢? - blackapps
将套接字 fd 绑定到 sockaddr_nl addr - Jordan
但是为什么?我从来没有绑定过套接字。 - blackapps
你将如何收集有关设备网络接口的信息?老实说,我不记得为什么我们要这样做。自从5年前实施以来就一直这样。如果你有其他办法,我很愿意听取建议。 - Jordan
1个回答

6

我找到了解决办法。原来我们使用NetLink套接字来发现网络接口地址信息,因为在当时Android上没有可用的ifaddrs(或者说未完全实现,或者类似的问题——这里没有人能够确切地记得为什么不能使用它)。从API 24开始,ifaddrs现在是可用的。我们将我们的实现切换到使用ifaddrs。只要您的最低支持版本是API 24或更高版本,您也可以做同样的事情。


请问您到底做了什么?我遇到了 NETLINK 套接字绑定问题。ifaddrs 是什么,如何将其合并? - Mike
2
ifaddrs是NDK中的实用程序(https://android.googlesource.com/platform/prebuilts/ndk/+/dev/platform/sysroot/usr/include/ifaddrs.h)。 ifaddrs结构包含接口信息。您只需创建一个ifaddrs结构,然后将其传递给getifaddrs(),它会填充字段。 ifa_name是接口名称,ifa_addrsockaddr等。 ifaddrs.h头文件具有所需的文档。 - Jordan
非常感谢。 - Mike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接