char buffer[1024] = {0}; // B reads "Hello!" and ACK int valread = read(client_fd, buffer, 1024); // B sends "Hello!" char *hello = "Hello!"; send(client_fd, hello ,strlen(hello) ,0); // B reads "Are you OK?" and ACK valread = read(client_fd, buffer, 1024); }
intmain(int argc, charconst *argv[]){ int B_pid = fork(); if (B_pid == 0) { // B sleep(1); // Let A start first host_B(); } else { // A host_A(); } return0; }
// filter.c: drop all A->B TCP packets #include<arpa/inet.h> #include<linux/bpf.h> #include<linux/if_ether.h> #include<linux/ip.h> #include<linux/tcp.h>
// The pattern that will be matched constchar match_pattern[] = "Are you OK?"; // The ports of src and dst #define A_PORT 1145 #define B_PORT 5141
// Tell clang that the section name of the function is prog SEC("prog") intxdp_func(struct xdp_md *ctx){ // ctx: the pointer to the frame and relevant fields void *data_end = (void *)(long)ctx->data_end; void *data = (void *)(long)ctx->data; // Ethernet header is the first one structethhdr *eth = data; if ((void *)eth + sizeof(*eth) > data_end) // Overflow detection return XDP_PASS; // PASS // Calculate the IP header address, must't overflow because tested structiphdr *ip = data + sizeof(*eth); if ((void *)ip + sizeof(*ip) > data_end) // Overflow detection return XDP_PASS; // If not IP protocol if (ip->protocol != IPPROTO_TCP) return XDP_PASS; // Calculatethe TCP header address structtcphdr *tcp = (void *)ip + sizeof(*ip); if ((void *)tcp + sizeof(*tcp) > data_end) // Overflow detection return XDP_PASS; // Match the source and target port // htons: host to network (byte order) short if (tcp->source != htons(A_PORT) || tcp->dest != htons(B_PORT)) return XDP_PASS; return XDP_DROP; // Drop it! }
看得出来,他会把所有的 A 到 B 的 TCP 包通过端口匹配丢掉,可以试试跑
experiment 来看看能不能过滤。
// filter.c (part) // include and some global variables ignored
// The pattern that will be matched constchar match_pattern[] = "Are you OK?";
SEC("prog") intxdp_func(struct xdp_md *ctx){ // ignored Ethernet, TCP, IP header tests // Here we begin to check payloads uint32_t payload_size = // ip total length - ip header length - tcp data offset ntohs(ip->tot_len) - ((uint32_t)(ip->ihl) << 2) - tcp_hdrl(tcp); uint32_t pattern_size = sizeof(match_pattern) - 1; if (payload_size != pattern_size) return XDP_PASS; // Point to start of payload. payload = (constchar *)tcp + tcp_hdrl(tcp); if ((void *)payload + payload_size > data_end) return XDP_PASS; // Compare first bytes, exit if a difference is found. #pragma unroll for (int i = 0; i < payload_size; i++) if (match_pattern[i] != payload[i]) return XDP_PASS; // matched, Drop it return XDP_DROP; }