#include
#include
#include
#include
#include
#include
void dump_line(const struct sock_filter *line)
{
printf("{ 0x%02x, %d, %d, 0x%08x}\n", line->code, line->jt, line->jf, line->k);
}
#if !defined(ETH_ALEN)
#define ETH_ALEN 6
#endif
int filter_out_by_source_mac_addr(int sockfd, uint8_t h_source_mac_addr[ETH_ALEN])
{
uint16_t mac_first_2_bytes = 0;
uint32_t mac_last_4_bytes = 0;
memcpy(&mac_first_2_bytes, h_source_mac_addr, sizeof(uint16_t));
memcpy(&mac_last_4_bytes, h_source_mac_addr+2, sizeof(uint32_t));
struct sock_fprog bpf_prog;
struct sock_filter filter[6] ={
BPF_STMT(BPF_LD|BPF_W|BPF_ABS, __builtin_offsetof(struct ethhdr, h_source)+2),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(mac_last_4_bytes), 0, 3),
BPF_STMT(BPF_LD|BPF_H|BPF_ABS, __builtin_offsetof(struct ethhdr, h_source)),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(mac_first_2_bytes), 0, 1),
BPF_STMT(BPF_RET, 0),
BPF_STMT(BPF_RET, UINT16_MAX),
};
bpf_prog.filter = filter;
bpf_prog.len = sizeof(filter) / sizeof(filter[0]);
int err = 0;
err = setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf_prog, sizeof(struct sock_fprog));
if (err) {
return -1;
}
return 0;
}
int main()
{
uint8_t mac[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
uint16_t mac_first_2_bytes = 0;
uint32_t mac_last_4_bytes = 0;
memcpy(&mac_first_2_bytes, mac, sizeof(uint16_t));
memcpy(&mac_last_4_bytes, mac+2, sizeof(uint32_t));
// 检查MAC报头,过滤掉任何发件人MAC地址=aa:bb:cc:dd:ee:ff的报文
// sudo tcpdump -s 65535 "not ether src host aa:bb:cc:dd:ee:ff" -dd
// { 0x20, 0, 0, 0x00000008 },
// { 0x15, 0, 3, 0xccddeeff },
// { 0x28, 0, 0, 0x00000006 },
// { 0x15, 0, 1, 0x0000aabb },
// { 0x06, 0, 0, 0x00000000 },
// { 0x06, 0, 0, 0x0000ffff },
struct sock_filter filter_program[100] ={
BPF_STMT(BPF_LD|BPF_W|BPF_ABS, __builtin_offsetof(struct ethhdr, h_source)+2),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(mac_last_4_bytes), 0, 3),
BPF_STMT(BPF_LD|BPF_H|BPF_ABS, __builtin_offsetof(struct ethhdr, h_source)),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(mac_first_2_bytes), 0, 1),
BPF_STMT(BPF_RET, 0),
BPF_STMT(BPF_RET, UINT16_MAX),
};
// sudo tcpdump -s 65535 "not ether src host aa:bb:cc:dd:ee:ff" -d
// (000) ld [8]
// (001) jeq #0xccddeeff jt 2 jf 5
// (002) ldh [6]
// (003) jeq #0xaabb jt 4 jf 5
// (004) ret #0
// (005) ret #65535
for (int i=0; i<6; i++) {
struct sock_filter *line;
line = &filter_program[i];
dump_line(line);
}
return 0;
}