首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SO_ATTACH_REUSEPORT_CBPF套接字选项意外行为

SO_ATTACH_REUSEPORT_CBPF套接字选项意外行为
EN

Stack Overflow用户
提问于 2017-11-25 02:56:30
回答 2查看 1.3K关注 0票数 7

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

代码语言:javascript
复制
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 }, };

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-12-04 22:07:30

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

代码语言:javascript
复制
ldh[12]

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

票数 3
EN

Stack Overflow用户

发布于 2017-12-03 20:01:56

不工作的代码是:

代码语言:javascript
复制
l0: ldh [12]                   /* read EtherType (2 bytes), which is found at offset 12 (decimal) */
l1: jeq #0x800, l2, l5         /* if EtherType == `0x800` (IPv4), jump to `l2`, otherwise jump to `l5` */
l2: ld [26]                    /* read source IP address (4 bytes) */
l3: jeq #0xc0a8ff01, l6, l4    /* if source IP address == 192.168.255.1, jump to l6 (return 1), else jump to l4 (return 0) */
l4: ret #0
l5: ret #0x40000
l6: ret #0x1

工作守则是:

代码语言:javascript
复制
ret #0x1

socket (7)说:

BPF程序必须返回一个0到N1之间的索引,表示套接字,该套接字应该接收数据包(其中N是组中的套接字数)。如果BPF程序返回无效的索引,套接字选择将回到普通的SO_REUSEPORT机制。

在我的机器上tcpdump -i lo -ddd 'src host 192.168.255.1'生产

代码语言:javascript
复制
10
40 0 0 12
21 0 2 2048
32 0 0 26
21 4 5 3232300801
21 1 0 2054
21 0 3 32821
32 0 0 28
21 0 1 3232300801
6 0 0 262144
6 0 0 0

这就是

代码语言:javascript
复制
l0: ldh [12]
l1: jeq #0x800, l2, l4
l2: ld [26]
l3: jeq #0xc0a8ff01, l8, l9
l4: jeq #0x806, l6, l5
l5: jeq #0x8035, l6, l9
l6: ld [28]
l7: jeq #0xc0a8ff01, l8, l9
l8: ret #0x40000
l9: ret #0

我看不出你的代码有什么问题。

您试过在服务器上运行tcpdump吗?也许您忘了删除客户端上的额外IP地址,或者某个地方忘记了SNAT规则?

您正在运行哪个内核版本?你能发布一个最小的C应用程序来重现这个问题吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47482223

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档