1 /* SPDX-License-Identifier: GPL-2.0 */
2 // Copyright (c) 2018 Covalent IO, Inc. http://covalent.io
8 #include <linux/if_ether.h>
11 #include <linux/ipv6.h>
12 #include <linux/pkt_cls.h>
13 #include <linux/tcp.h>
14 #include <sys/socket.h>
15 #include <bpf/bpf_helpers.h>
16 #include <bpf/bpf_endian.h>
18 char _license[] SEC("license") = "GPL";
20 /* Fill 'tuple' with L3 info, and attempt to find L4. On fail, return NULL. */
21 static struct bpf_sock_tuple *get_tuple(void *data, __u64 nh_off,
22 void *data_end, __u16 eth_proto,
25 struct bpf_sock_tuple *result;
29 if (eth_proto == bpf_htons(ETH_P_IP)) {
30 struct iphdr *iph = (struct iphdr *)(data + nh_off);
32 if (iph + 1 > data_end)
34 ihl_len = iph->ihl * 4;
35 proto = iph->protocol;
37 result = (struct bpf_sock_tuple *)&iph->saddr;
38 } else if (eth_proto == bpf_htons(ETH_P_IPV6)) {
39 struct ipv6hdr *ip6h = (struct ipv6hdr *)(data + nh_off);
41 if (ip6h + 1 > data_end)
43 ihl_len = sizeof(*ip6h);
44 proto = ip6h->nexthdr;
46 result = (struct bpf_sock_tuple *)&ip6h->saddr;
49 if (data + nh_off + ihl_len > data_end || proto != IPPROTO_TCP)
56 int sk_lookup_success(struct __sk_buff *skb)
58 void *data_end = (void *)(long)skb->data_end;
59 void *data = (void *)(long)skb->data;
60 struct ethhdr *eth = (struct ethhdr *)(data);
61 struct bpf_sock_tuple *tuple;
66 if (eth + 1 > data_end)
69 tuple = get_tuple(data, sizeof(*eth), data_end, eth->h_proto, &ipv4);
70 if (!tuple || tuple + sizeof *tuple > data_end)
73 tuple_len = ipv4 ? sizeof(tuple->ipv4) : sizeof(tuple->ipv6);
74 sk = bpf_sk_lookup_tcp(skb, tuple, tuple_len, BPF_F_CURRENT_NETNS, 0);
75 bpf_printk("sk=%d\n", sk ? 1 : 0);
78 return sk ? TC_ACT_OK : TC_ACT_UNSPEC;
82 int sk_lookup_success_simple(struct __sk_buff *skb)
84 struct bpf_sock_tuple tuple = {};
87 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
94 int err_use_after_free(struct __sk_buff *skb)
96 struct bpf_sock_tuple tuple = {};
100 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
109 int err_modify_sk_pointer(struct __sk_buff *skb)
111 struct bpf_sock_tuple tuple = {};
114 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
123 int err_modify_sk_or_null_pointer(struct __sk_buff *skb)
125 struct bpf_sock_tuple tuple = {};
128 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
136 int err_no_release(struct __sk_buff *skb)
138 struct bpf_sock_tuple tuple = {};
140 bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
145 int err_release_twice(struct __sk_buff *skb)
147 struct bpf_sock_tuple tuple = {};
150 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
157 int err_release_unchecked(struct __sk_buff *skb)
159 struct bpf_sock_tuple tuple = {};
162 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
167 void lookup_no_release(struct __sk_buff *skb)
169 struct bpf_sock_tuple tuple = {};
170 bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
174 int err_no_release_subcall(struct __sk_buff *skb)
176 lookup_no_release(skb);