File Index
Files and directories
Sign in
FILE

ip_check_defrag.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/ip_check_defrag.c 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.