linux socket c 设置过滤规则,把报文低八位为0x91,0x92保留,其他的过滤掉
时间: 2023-09-20 15:09:07 浏览: 87
可以使用 Berkeley Packet Filter (BPF)来设置过滤规则。下面是一个简单的示例程序:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <linux/filter.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#define ETH_HDR_LEN 14
int main(int argc, char **argv) {
int sock_fd;
struct sock_fprog bpf;
struct sock_filter code[] = {
{ 0x30, 0, 0, 0x00000000 },
{ 0x15, 0, 5, 0x00000091 },
{ 0x20, 0, 0, 0x00000000 },
{ 0x15, 0, 3, 0x00000092 },
{ 0x6, 0, 0, 0x0000ffff },
{ 0x6, 0, 0, 0x00000000 },
};
unsigned char buf[ETH_FRAME_LEN];
ssize_t num_bytes;
struct sockaddr_ll saddr;
socklen_t saddr_len;
// 创建原始套接字
sock_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock_fd < 0) {
perror("socket");
exit(1);
}
// 设置 BPF 过滤规则
memset(&bpf, 0, sizeof(bpf));
bpf.filter = code;
bpf.len = sizeof(code) / sizeof(code[0]);
if (setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf)) < 0) {
perror("setsockopt");
exit(1);
}
// 接收报文并过滤
while (1) {
saddr_len = sizeof(saddr);
num_bytes = recvfrom(sock_fd, buf, ETH_FRAME_LEN, 0, (struct sockaddr *)&saddr, &saddr_len);
if (num_bytes < 0) {
perror("recvfrom");
exit(1);
}
// 检查低八位是否为 0x91 或 0x92
if ((buf[ETH_HDR_LEN + num_bytes - 1] & 0xff) == 0x91 || (buf[ETH_HDR_LEN + num_bytes - 1] & 0xff) == 0x92) {
printf("Received a packet, length = %zd\n", num_bytes);
printf("%02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x, protocol = %04x\n",
buf[6], buf[7], buf[8], buf[9], buf[10], buf[11],
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
ntohs(((unsigned short *)buf)[6]));
} else {
printf("Packet filtered\n");
}
}
return 0;
}
```
上面的代码中,我们使用了一个 BPF 过滤规则,它包含了 6 条指令,主要功能是检查报文的最后一个字节是否为 0x91 或 0x92。如果是,则打印报文的信息,否则过滤掉该报文。
注意,上面的代码仅仅是一个示例程序,实际情况中需要根据具体的需求修改过滤规则。
阅读全文