最新的linux内核中,写xdp程序时,bpf()函数如何使用,给出一个只阻断tcp80端口、其他流量全部放行完整示例,包括内核空间和用户空间的代码,要求不使用libbpf
时间: 2024-05-15 10:15:43 浏览: 197
bpfcountd:一个使用 bpf(伯克利数据包过滤器)监控网络流量的小守护进程
下面是一个阻断TCP 80端口的XDP程序示例,其他流量全部放行:
内核空间代码:
```c
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#define SEC(NAME) __attribute__((section(NAME), used))
// 定义BPF程序,只阻断TCP 80端口
SEC("xdp_prog")
int xdp_prog(struct xdp_md *ctx) {
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;
if ((void*)eth + sizeof(struct ethhdr) > data_end) {
return XDP_DROP;
}
struct iphdr *iph = data + sizeof(struct ethhdr);
if ((void*)iph + sizeof(struct iphdr) > data_end) {
return XDP_DROP;
}
if (iph->protocol == IPPROTO_TCP) {
struct tcphdr *tcph = data + sizeof(struct ethhdr) + sizeof(struct iphdr);
if ((void*)tcph + sizeof(struct tcphdr) > data_end) {
return XDP_DROP;
}
if (ntohs(tcph->dest) == 80) {
return XDP_DROP;
}
}
return XDP_PASS;
}
char _license[] SEC("license") = "GPL";
```
用户空间代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <arpa/inet.h>
#define IFNAME "eth0"
#define MAX_PACKET_SIZE 4096
int main(int argc, char **argv) {
int sock_fd, ifindex;
char ifname[IFNAMSIZ];
struct sockaddr_ll sa;
// 打开网络接口
strncpy(ifname, IFNAME, IFNAMSIZ);
sock_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock_fd < 0) {
perror("socket");
exit(1);
}
ifindex = if_nametoindex(ifname);
if (ifindex == 0) {
perror("if_nametoindex");
exit(1);
}
memset(&sa, 0, sizeof(struct sockaddr_ll));
sa.sll_family = AF_PACKET;
sa.sll_ifindex = ifindex;
sa.sll_protocol = htons(ETH_P_ALL);
if (bind(sock_fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_ll)) < 0) {
perror("bind");
exit(1);
}
// 加载XDP程序
int prog_fd = bpf_prog_load(BPF_PROG_TYPE_XDP, xdp_prog, sizeof(xdp_prog), "GPL", 0, NULL, 0);
if (prog_fd < 0) {
perror("bpf_prog_load");
exit(1);
}
// 将XDP程序绑定到网络接口
if (setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd, sizeof(prog_fd)) < 0) {
perror("setsockopt");
exit(1);
}
// 接收网络数据包
char packet_buf[MAX_PACKET_SIZE];
while (1) {
int packet_size = recv(sock_fd, packet_buf, MAX_PACKET_SIZE, 0);
if (packet_size < 0) {
if (errno == EINTR) {
continue;
}
perror("recv");
exit(1);
}
// 处理网络数据包
printf("Received a packet of size %d\n", packet_size);
}
return 0;
}
```
阅读全文