在Linux机器上使用BPF和SOCK_DGRAM

问题描述 投票:3回答:1

是否可以在数据报套接字上使用BPF过滤数据包?

我尝试连接过滤器时没有错误,但我没有收到任何数据包。我使用libpcap编译了一个过滤器,过滤器与tcpdump一起使用。

这是我的代码的缩短版本:

static const char filter[] = "udp[8] == 0x00";
int sock = socket(AF_INET, SOCK_DGRAM, 0);
pcap_t *pcap = pcap_open_dead(DLT_RAW, 1024);
struct bpf_program bpf_prog;
pcap_compile(pcap, &bpf_prog, filter, 0, PCAP_NETMASK_UNKNOWN);
struct sock_fprog linux_bpf = {
    .len = bpf_prog.bf_len,
    .filter = (struct sock_filter *) bpf_prog.bf_insns,
};
setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &linux_bpf, sizeof(linux_bpf));

我的机器是ubuntu 12.04 x86。

linux udp pcap bpf
1个回答
6
投票

好吧,经过一些测试和试验,这是可能的。但是,libpcap不直接支持它。

应该做的是打开指定以太网数据类型的pcap处理程序,然后访问udp数据包中的字节,就像访问以太网数据包一样。过滤器偏移从数据包的开头开始,但“数据包”取决于您打开套接字的层。如果用SOCK_DGRAM打开套接字,bpf指令ldb 0将加载udp头的第一个字节。因此,当在过滤器中访问ether[0]时,libpcap会将其编译为ldb 0,这就是我们想要的。

所以,更正的代码应该是这样的:

static const char filter[] = "ether[8] == 0x00";
int sock = socket(AF_INET, SOCK_DGRAM, 0);
pcap_t *pcap = pcap_open_dead(DLT_EN10MB, 1024);
struct bpf_program bpf_prog;
pcap_compile(pcap, &bpf_prog, filter, 0, PCAP_NETMASK_UNKNOWN);
struct sock_fprog linux_bpf = {
    .len = bpf_prog.bf_len,
    .filter = (struct sock_filter *) bpf_prog.bf_insns,
};
setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &linux_bpf, sizeof(linux_bpf));
© www.soinside.com 2019 - 2024. All rights reserved.