过滤 Arp 回复
Filter Arp-Replies
我正在用 C 从头开始编写一个网络库。我已经实现了以太网协议,现在我想让 ARP 工作。
发送 Requests/Replies 工作正常,但接收工作不正常。
当我发送一个发送请求并等待它之后的回复时,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 packets/how 来做到这一点?
提前致谢。
--- 编辑 ---
我试过 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 */
我希望我没有犯任何 stupid/obvious 错误。
提前致谢!
-- 最后一次编辑 --
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) 的回复是 accepted/received.
非常感谢 Ctx!
您可以使用(正确配置的)Berkeley 数据包过滤器 (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 = ...;
...
"language" 非常基础,描述为 here
然后将这些指令组合成一个BPF程序:
struct sock_fprog prog;
prog.len = NR_INSTRUCTIONS;
prog.filter = filter;
最后,您可以将过滤器连接到您的插座:
setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog));
如果您正确配置了过滤器,从现在开始您将只会在您的套接字上收到匹配的 arp 回复。
对于下一个 request/reply,您必须重新配置过滤器以匹配新参数(SO_DETACH_FILTER 后跟 SO_ATTACH_FILTER 新程序)。
对于 ARP 数据包,构建过滤器特别容易,因为数据包中字段的偏移量是固定的。
我正在用 C 从头开始编写一个网络库。我已经实现了以太网协议,现在我想让 ARP 工作。 发送 Requests/Replies 工作正常,但接收工作不正常。 当我发送一个发送请求并等待它之后的回复时,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 packets/how 来做到这一点?
提前致谢。
--- 编辑 ---
我试过 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 */
我希望我没有犯任何 stupid/obvious 错误。
提前致谢!
-- 最后一次编辑 --
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) 的回复是 accepted/received.
非常感谢 Ctx!
您可以使用(正确配置的)Berkeley 数据包过滤器 (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 = ...;
...
"language" 非常基础,描述为 here
然后将这些指令组合成一个BPF程序:
struct sock_fprog prog;
prog.len = NR_INSTRUCTIONS;
prog.filter = filter;
最后,您可以将过滤器连接到您的插座:
setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog));
如果您正确配置了过滤器,从现在开始您将只会在您的套接字上收到匹配的 arp 回复。
对于下一个 request/reply,您必须重新配置过滤器以匹配新参数(SO_DETACH_FILTER 后跟 SO_ATTACH_FILTER 新程序)。
对于 ARP 数据包,构建过滤器特别容易,因为数据包中字段的偏移量是固定的。