1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */ |
3 | |
4 | #include "vmlinux.h" |
5 | #include "bpf_tracing_net.h" |
6 | #include <bpf/bpf_helpers.h> |
7 | #include <bpf/bpf_endian.h> |
8 | |
9 | #define UDP_TEST_PORT 7777 |
10 | |
11 | void *bpf_cast_to_kern_ctx(void *) __ksym; |
12 | bool init_csum_partial = false; |
13 | bool final_csum_none = false; |
14 | bool broken_csum_start = false; |
15 | |
16 | static unsigned int skb_headlen(const struct sk_buff *skb) |
17 | { |
18 | return skb->len - skb->data_len; |
19 | } |
20 | |
21 | static unsigned int skb_headroom(const struct sk_buff *skb) |
22 | { |
23 | return skb->data - skb->head; |
24 | } |
25 | |
26 | static int skb_checksum_start_offset(const struct sk_buff *skb) |
27 | { |
28 | return skb->csum_start - skb_headroom(skb); |
29 | } |
30 | |
31 | SEC("tc" ) |
32 | int decap_sanity(struct __sk_buff *skb) |
33 | { |
34 | struct sk_buff *kskb; |
35 | struct ipv6hdr ip6h; |
36 | struct udphdr udph; |
37 | int err; |
38 | |
39 | if (skb->protocol != __bpf_constant_htons(ETH_P_IPV6)) |
40 | return TC_ACT_SHOT; |
41 | |
42 | if (bpf_skb_load_bytes(skb, ETH_HLEN, &ip6h, sizeof(ip6h))) |
43 | return TC_ACT_SHOT; |
44 | |
45 | if (ip6h.nexthdr != IPPROTO_UDP) |
46 | return TC_ACT_SHOT; |
47 | |
48 | if (bpf_skb_load_bytes(skb, ETH_HLEN + sizeof(ip6h), &udph, sizeof(udph))) |
49 | return TC_ACT_SHOT; |
50 | |
51 | if (udph.dest != __bpf_constant_htons(UDP_TEST_PORT)) |
52 | return TC_ACT_SHOT; |
53 | |
54 | kskb = bpf_cast_to_kern_ctx(skb); |
55 | init_csum_partial = (kskb->ip_summed == CHECKSUM_PARTIAL); |
56 | err = bpf_skb_adjust_room(skb, -(s32)(ETH_HLEN + sizeof(ip6h) + sizeof(udph)), |
57 | 1, BPF_F_ADJ_ROOM_FIXED_GSO); |
58 | if (err) |
59 | return TC_ACT_SHOT; |
60 | final_csum_none = (kskb->ip_summed == CHECKSUM_NONE); |
61 | if (kskb->ip_summed == CHECKSUM_PARTIAL && |
62 | (unsigned int)skb_checksum_start_offset(skb: kskb) >= skb_headlen(skb: kskb)) |
63 | broken_csum_start = true; |
64 | |
65 | return TC_ACT_SHOT; |
66 | } |
67 | |
68 | char __license[] SEC("license" ) = "GPL" ; |
69 | |