linux - SO_ATTACH_REUSEPORT_CBPF 套接字选项意外行为

标签 linux sockets packet-capture

我正在尝试使用来自两个应用程序的端口,并让每个应用程序从一组不同的 IP 地址接收数据包。为了实现这一点,我使用了 SO_REUSEPORT 和 SO_ATTACH_REUSEPORT_CBPF 套接字选项。我的代码如下:

parentfd = socket(AF_INET, SOCK_STREAM, 0);
if (parentfd < 0)
  error( "ERROR opening socket");

struct sock_filter code[]={
  { 0x28, 0, 0, 0x0000000c },
  { 0x15, 0, 3, 0x00000800 },
  { 0x20, 0, 0, 0x0000001a },
  { 0x15, 2, 0, 0xc0a8ff01 },
  { 0x6, 0, 0, 0x00000000 },
  { 0x6, 0, 0, 0x00040000 },
  { 0x6, 0, 0, 0x00000001 },
};

struct sock_fprog bpf = {
  .len = ARRAY_SIZE(code),
  .filter = code,
};

if (setsockopt(parentfd, SOL_SOCKET, SO_REUSEPORT, (const void *)&optval,sizeof(optval)))
  error("ERROR setting SO_REUSEPORT");

if (setsockopt(parentfd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, (const void *)&bpf, sizeof(bpf)))
  error("ERROR setting SO_ATTACH_REUSEPORT_CBPF);

我还有一个不同的进程,它使用 SO_REUSEPORT 标志监听同一个端口。从 IP 为 192.168.255.1 的机器我正在运行 echo 1234 | ncat 192.168.255.150 1234。根据我的过滤器,我希望第二个进程接收来自该 IP 地址的所有流量。然而,这一切都被第一个收到了。当我将过滤器更改为简单时:

struct sock_filter code[]={ { 0x6, 0, 0, 0x00000001 }, };

它按预期工作,所有数据包都由第二个进程接收。知道为什么会这样吗?

最佳答案

我发现了问题所在。过滤器适用于所有数据包,甚至是 TCP 握手数据包。此外,基指针指向数据包有效负载的第一个字节,而不是 header 。因此,当它执行时

ldh[12]

它超出了数据包的限制(SYN 数据包的有效负载为 0 字节),默认行为是返回 0。

关于linux - SO_ATTACH_REUSEPORT_CBPF 套接字选项意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47482223/

相关文章:

linux - 汇编语言有什么优点吗?

linux - 现有文件的 Docker "not found"

c# - 将图像从 C# 客户端发送到 C 服务器

network-programming - 如何在网卡上发送 pcap 文件包?

linux - Gitlab:如何在 git repo url 中显示 http 端口?

php & filesystem +setUID/permissions ...我只是不明白!

sockets - TCP套接字的传输时间

c++ - 从套接字进行异步读取时出现 Heisenbug

udp - 如何让 Wireshark 读取没有 UDP/IP/以太网 header 的无 header pcap 文件?

https - Wireshark 不捕获 HTTPS 数据包?