FILE
ip_check_defrag.c
File preview with syntax highlighting.
linux-6.19.14/tools/testing/selftests/bpf/progs/ip_check_defrag.c
1// SPDX-License-Identifier: GPL-2.0-only 2#include "vmlinux.h" 3#include <bpf/bpf_helpers.h> 4#include <bpf/bpf_endian.h> 5#include "bpf_tracing_net.h" 6 7#define NF_DROP 0 8#define NF_ACCEPT 1 9#define ETH_P_IP 0x0800 10#define ETH_P_IPV6 0x86DD 11#define IP_MF 0x2000 12#define IP_OFFSET 0x1FFF 13#define NEXTHDR_FRAGMENT 44 14 15volatile int shootdowns = 0; 16 17static bool is_frag_v4(struct iphdr *iph) 18{ 19 int offset; 20 int flags; 21 22 offset = bpf_ntohs(iph->frag_off); 23 flags = offset & ~IP_OFFSET; 24 offset &= IP_OFFSET; 25 offset <<= 3; 26 27 return (flags & IP_MF) || offset; 28} 29 30static bool is_frag_v6(struct ipv6hdr *ip6h) 31{ 32 /* Simplifying assumption that there are no extension headers 33 * between fixed header and fragmentation header. This assumption 34 * is only valid in this test case. It saves us the hassle of 35 * searching all potential extension headers. 36 */ 37 return ip6h->nexthdr == NEXTHDR_FRAGMENT; 38} 39 40static int handle_v4(struct __sk_buff *skb) 41{ 42 struct bpf_dynptr ptr; 43 u8 iph_buf[20] = {}; 44 struct iphdr *iph; 45 46 if (bpf_dynptr_from_skb(skb, 0, &ptr)) 47 return NF_DROP; 48 49 iph = bpf_dynptr_slice(&ptr, 0, iph_buf, sizeof(iph_buf)); 50 if (!iph) 51 return NF_DROP; 52 53 /* Shootdown any frags */ 54 if (is_frag_v4(iph)) { 55 shootdowns++; 56 return NF_DROP; 57 } 58 59 return NF_ACCEPT; 60} 61 62static int handle_v6(struct __sk_buff *skb) 63{ 64 struct bpf_dynptr ptr; 65 struct ipv6hdr *ip6h; 66 u8 ip6h_buf[40] = {}; 67 68 if (bpf_dynptr_from_skb(skb, 0, &ptr)) 69 return NF_DROP; 70 71 ip6h = bpf_dynptr_slice(&ptr, 0, ip6h_buf, sizeof(ip6h_buf)); 72 if (!ip6h) 73 return NF_DROP; 74 75 /* Shootdown any frags */ 76 if (is_frag_v6(ip6h)) { 77 shootdowns++; 78 return NF_DROP; 79 } 80 81 return NF_ACCEPT; 82} 83 84SEC("netfilter") 85int defrag(struct bpf_nf_ctx *ctx) 86{ 87 struct __sk_buff *skb = (struct __sk_buff *)ctx->skb; 88 89 switch (bpf_ntohs(ctx->skb->protocol)) { 90 case ETH_P_IP: 91 return handle_v4(skb); 92 case ETH_P_IPV6: 93 return handle_v6(skb); 94 default: 95 return NF_ACCEPT; 96 } 97} 98 99char _license[] SEC("license") = "GPL";
~/
Read-only file preview.