我已经使用以下方法创建一个 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 开发者页面的某处有一份文档,但如果我能再次找到它,我会很高兴。它曾经存在 here,但自从几个月前我第一次遇到这个问题以来,该页面已经发生了变化。)据说这应该会影响所有以 API 30 为目标的应用程序,但我发现只有以 API 30 为目标的应用程序和在运行 Android 11 的设备(物理或模拟器)上运行会受到影响。我第一次遇到这个问题时的笔记也提到了建议使用 ConnectivityManager 的文章,但这需要想出某种方法将信息向下传递给 native 代码,或者让 native 代码通过 JNI 调用 Android 平台代码。如果这是必须发生的事情,我对其中任何一个都没有意见,但我想知道是否还有我不知道的另一种选择。
我还看到了this similar question ,但其中一个答案中有一个链接表明它应该是可能的,至少在 API 30 之前是这样。
既然我们不允许调用 bind()
,还有哪些其他选项可用?
最佳答案
找到了解决办法。结果我们使用 NetLink 套接字来发现网络接口(interface)地址信息,因为 ifaddrs
不可用(或者,没有完全实现,或者类似的东西 - 这里没有人能确切记得我们为什么不能使用它)当时在安卓上。从 API 24 开始,ifaddrs
现已可用。我们将实现切换为使用 ifaddrs
。只要您支持的最低版本是 API 24 或更高版本,您就可以执行相同的操作。
关于android - 以 Android API 30 为目标时无法绑定(bind) () netlink 套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64884994/