解决您最初的问题“我需要能够在驱动程序中识别用户空间库拦截了哪些套接字。” 实际上有几个功能。
首先你需要知道所有现有的连接都存储在一个全局哈希表——“tcp_hashinfo”中,你可以在 /proc/kallsyms 中找到地址。
主要的函数是__inet_lookup_skb(),它调用了__inet_lookup(),分为__inet_lookup_established()(寻找已经建立的任何匹配的socket)和__inet_lookup_listener()(寻找打开的监听器,但还没有建立连接)。
查找所需的主要输入是源/目标端口和 IP 地址信息,如果找到返回指针是套接字的“struct sock *”。
IPv6 具有相同的名称和相同的逻辑。
函数 (__inet_lookup_skb()) 被声明为“静态内联” - 它无法从 /proc/kallsyms 中找到,驱动程序也无法看到它,因为它是内联编译的。但是这没有问题,因为它调用了另外两个函数 - inet_lookup_listener() 和 inet_lookup_established() ,它们不是内联编译的。它的符号已导出,因此您可以安全地从内核模块中使用它。
重要的是,读取这个 hashinfo 表是一项关键操作 - 多个 CPU 可能同时读取/写入它,这就是为什么在读取完成时在函数的开头/结尾进行锁定,以防止它在阅读时被修改。由于很难访问这些 RCU 锁,即使它本质上是全局的,也不要重新实现这些功能,只需重用它们即可。