过滤ARP回复

时间:2018-07-09 10:32:19

标签: c networking arp

我正在从头开始用C编写网络库。我已经实现了以太网协议,现在想使ARP工作。 发送请求/回复工作正常,但接收效果不佳。 当我发送发送请求并等待回复后,recvfrom()只会接收第一个传入的ARP数据包。但是我想得到主持人对我的请求的回复。

我不能只收到正确的数据包,因为该库应该支持套接字超时。 (使用setsockopt()设置)

套接字是这样创建的:

int sfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP))

我的测试程序的输出:

Sending ARP-Request ...

0o0o0o0 ARP-FRAME DUMP 0o0o0o0

HwType: 256 (0x7ab74e358670)
PrType: 8 (0x7ab74e358672)
HwALen: 6 (0x7ab74e358674)
PrALen: 4 (0x7ab74e358675)
ArpOP : 256 (0x7ab74e358676)
Sha   : 84:4b:10:14:a0:04 (0x7ab74e358678)
Spa   : 192.168.12.1 (0x7ab74e35867e)
Tha   : 00:00:00:00:00:00 (0x7ab74e358682)
Tpa   : 192.168.0.3 (0x7ab74e358688)

Receiving ARP-Reply ...


0o0o0o0 ARP-FRAME DUMP 0o0o0o0

HwType: 256 (0x7ab74e358670)
PrType: 8 (0x7ab74e358672)
HwALen: 6 (0x7ab74e358674)
PrALen: 4 (0x7ab74e358675)
ArpOP : 512 (0x7ab74e358676)
Sha   : 10:00:00:00:00:01 (0x7ab74e358678)
Spa   : 192.168.12.78 (0x7ab74e35867e)
Tha   : 84:4b:10:14:a0:04 (0x7ab74e358682)
Tpa   : 192.168.12.1 (0x7ab74e358688)

是否可以过滤传入的ARP数据包/如何处理?

谢谢。

---编辑---

我和BPF一起玩,它可以很好地过滤掉ARP数据包。 它写了这个过滤器

ld [28]
jne #0x4e0ca8c0, drop
ret #-1
drop: ret #0

过滤传入的ARP答复。 它应该从数据包中加载源IP,并将其与代码中定义的IP进行比较。 0x4e0ca8c0是有效的IP地址。我要回复其主机的主机。 tcpdump显示收到的答复,但是我的程序死机了(永远等待)。 我这样使用BPF:

struct sock_fprog prog;
struct sock_filter filter[4] =\
{{ 0x20,  0,  0, 0x0000001c },
 { 0x15,  0,  1, 0x4e0ca8c0 },
 { 0x06,  0,  0, 0xffffffff },
 { 0x06,  0,  0, 0000000000 }};

prog.len = 4;
prog.filter = filter;

if(setsockopt(sfd, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) ==\
-1) {
    fprintf(stderr, "ERROR enabling bpf: setsockopt(): %s\n",\
    strerror(errno));
    goto ... (error handler);
}
/* Receive incoming ARP reply */

我希望我没有犯任何愚蠢/明显的错误。

谢谢!

-最后编辑-

IP地址。必须在NBO中。 因此,使用正确的BPF:

struct sock_filter filter[4] =\
{{ 0x20,  0,  0, 0x0000001c },
 { 0x15,  0,  1, 0xc0a80c4e },
 { 0x06,  0,  0, 0xffffffff },
 { 0x06,  0,  0, 0000000000 }};

...仅接受/接收来自192.168.12.78(0xc0a80c4e)的答复。

非常感谢Ctx!

1 个答案:

答案 0 :(得分:1)

您可以为其使用(正确配置的)伯克利包过滤器(BPF)。

为此,您必须编写一个(小)BPF过滤器,该过滤器与您要查找的答复完全匹配。

#include <linux/filter.h>

struct sock_filter filter[NR_INSTRUCTIONS];

filter[0].code = ...;
filter[0].k = ...;
filter[0].jt = ...;
filter[0].jf = ...;
filter[1].code = ...;
...

“语言”非常基础,here对此进行了描述

然后将指令放到BPF程序中

struct sock_fprog prog;
prog.len = NR_INSTRUCTIONS;
prog.filter = filter;

最后,您可以将过滤器连接到插槽:

setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog));

如果正确配置了过滤器,从现在开始,您只会在套接字上收到匹配的arp答复。

对于下一个请求/答复,您必须重新配置过滤器以使其与新参数(SO_DETACH_FILTER,然后是新程序的SO_ATTACH_FILTER)相匹配。

对于ARP数据包来说,构造一个过滤器特别容易,因为数据包中字段的偏移量是固定的。