use*_*276 5 sockets linux 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);
Run Code Online (Sandbox Code Playgroud)
我还有一个不同的进程只使用SO_REUSEPORT标志来侦听同一个端口.从192.168.255.1我正在运行的IP机器echo 1234 | ncat 192.168.255.150 1234.根据我的过滤器,我希望第二个进程可以接收来自该IP地址的所有流量.然而,它都是第一个收到的.当我将过滤器更改为简单时:
struct sock_filter code[]={
{ 0x6, 0, 0, 0x00000001 },
};
它按预期工作,所有数据包都由第二个进程接收.知道为什么会这样吗?
我发现问题出在哪里了。该过滤器适用于所有数据包,甚至是 TCP 握手数据包。此外,基指针指向数据包有效负载的第一个字节,而不是标头。因此,当它执行时
ldh[12]
Run Code Online (Sandbox Code Playgroud)
它超出了数据包的限制(SYN 数据包有 0 字节的有效负载),默认行为是返回 0。