1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io */
3 #include <stddef.h>
4 #include <string.h>
5 #include <linux/bpf.h>
6 #include <linux/if_ether.h>
7 #include <linux/if_packet.h>
8 #include <linux/ip.h>
9 #include <linux/ipv6.h>
10 #include <linux/in.h>
11 #include <linux/udp.h>
12 #include <linux/tcp.h>
13 #include <linux/pkt_cls.h>
14 #include <sys/socket.h>
15 #include <bpf/bpf_helpers.h>
16 #include <bpf/bpf_endian.h>
17 
18 /* Sockmap sample program connects a client and a backend together
19  * using cgroups.
20  *
21  *    client:X <---> frontend:80 client:X <---> backend:80
22  *
23  * For simplicity we hard code values here and bind 1:1. The hard
24  * coded values are part of the setup in sockmap.sh script that
25  * is associated with this BPF program.
26  *
27  * The bpf_printk is verbose and prints information as connections
28  * are established and verdicts are decided.
29  */
30 
31 struct {
32 	__uint(type, TEST_MAP_TYPE);
33 	__uint(max_entries, 20);
34 	__uint(key_size, sizeof(int));
35 	__uint(value_size, sizeof(int));
36 } sock_map SEC(".maps");
37 
38 struct {
39 	__uint(type, TEST_MAP_TYPE);
40 	__uint(max_entries, 20);
41 	__uint(key_size, sizeof(int));
42 	__uint(value_size, sizeof(int));
43 } sock_map_txmsg SEC(".maps");
44 
45 struct {
46 	__uint(type, TEST_MAP_TYPE);
47 	__uint(max_entries, 20);
48 	__uint(key_size, sizeof(int));
49 	__uint(value_size, sizeof(int));
50 } sock_map_redir SEC(".maps");
51 
52 struct {
53 	__uint(type, BPF_MAP_TYPE_ARRAY);
54 	__uint(max_entries, 1);
55 	__type(key, int);
56 	__type(value, int);
57 } sock_apply_bytes SEC(".maps");
58 
59 struct {
60 	__uint(type, BPF_MAP_TYPE_ARRAY);
61 	__uint(max_entries, 1);
62 	__type(key, int);
63 	__type(value, int);
64 } sock_cork_bytes SEC(".maps");
65 
66 struct {
67 	__uint(type, BPF_MAP_TYPE_ARRAY);
68 	__uint(max_entries, 6);
69 	__type(key, int);
70 	__type(value, int);
71 } sock_bytes SEC(".maps");
72 
73 struct {
74 	__uint(type, BPF_MAP_TYPE_ARRAY);
75 	__uint(max_entries, 1);
76 	__type(key, int);
77 	__type(value, int);
78 } sock_redir_flags SEC(".maps");
79 
80 struct {
81 	__uint(type, BPF_MAP_TYPE_ARRAY);
82 	__uint(max_entries, 2);
83 	__type(key, int);
84 	__type(value, int);
85 } sock_skb_opts SEC(".maps");
86 
87 struct {
88 	__uint(type, TEST_MAP_TYPE);
89 	__uint(max_entries, 20);
90 	__uint(key_size, sizeof(int));
91 	__uint(value_size, sizeof(int));
92 } tls_sock_map SEC(".maps");
93 
94 SEC("sk_skb1")
95 int bpf_prog1(struct __sk_buff *skb)
96 {
97 	return skb->len;
98 }
99 
100 SEC("sk_skb2")
101 int bpf_prog2(struct __sk_buff *skb)
102 {
103 	__u32 lport = skb->local_port;
104 	__u32 rport = skb->remote_port;
105 	int len, *f, ret, zero = 0;
106 	__u64 flags = 0;
107 
108 	if (lport == 10000)
109 		ret = 10;
110 	else
111 		ret = 1;
112 
113 	len = (__u32)skb->data_end - (__u32)skb->data;
114 	f = bpf_map_lookup_elem(&sock_skb_opts, &zero);
115 	if (f && *f) {
116 		ret = 3;
117 		flags = *f;
118 	}
119 
120 #ifdef SOCKMAP
121 	return bpf_sk_redirect_map(skb, &sock_map, ret, flags);
122 #else
123 	return bpf_sk_redirect_hash(skb, &sock_map, &ret, flags);
124 #endif
125 
126 }
127 
128 SEC("sk_skb3")
129 int bpf_prog3(struct __sk_buff *skb)
130 {
131 	const int one = 1;
132 	int err, *f, ret = SK_PASS;
133 	void *data_end;
134 	char *c;
135 
136 	err = bpf_skb_pull_data(skb, 19);
137 	if (err)
138 		goto tls_out;
139 
140 	c = (char *)(long)skb->data;
141 	data_end = (void *)(long)skb->data_end;
142 
143 	if (c + 18 < data_end)
144 		memcpy(&c[13], "PASS", 4);
145 	f = bpf_map_lookup_elem(&sock_skb_opts, &one);
146 	if (f && *f) {
147 		__u64 flags = 0;
148 
149 		ret = 0;
150 		flags = *f;
151 #ifdef SOCKMAP
152 		return bpf_sk_redirect_map(skb, &tls_sock_map, ret, flags);
153 #else
154 		return bpf_sk_redirect_hash(skb, &tls_sock_map, &ret, flags);
155 #endif
156 	}
157 
158 	f = bpf_map_lookup_elem(&sock_skb_opts, &one);
159 	if (f && *f)
160 		ret = SK_DROP;
161 tls_out:
162 	return ret;
163 }
164 
165 SEC("sockops")
166 int bpf_sockmap(struct bpf_sock_ops *skops)
167 {
168 	__u32 lport, rport;
169 	int op, err = 0, index, key, ret;
170 
171 
172 	op = (int) skops->op;
173 
174 	switch (op) {
175 	case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
176 		lport = skops->local_port;
177 		rport = skops->remote_port;
178 
179 		if (lport == 10000) {
180 			ret = 1;
181 #ifdef SOCKMAP
182 			err = bpf_sock_map_update(skops, &sock_map, &ret,
183 						  BPF_NOEXIST);
184 #else
185 			err = bpf_sock_hash_update(skops, &sock_map, &ret,
186 						   BPF_NOEXIST);
187 #endif
188 		}
189 		break;
190 	case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
191 		lport = skops->local_port;
192 		rport = skops->remote_port;
193 
194 		if (bpf_ntohl(rport) == 10001) {
195 			ret = 10;
196 #ifdef SOCKMAP
197 			err = bpf_sock_map_update(skops, &sock_map, &ret,
198 						  BPF_NOEXIST);
199 #else
200 			err = bpf_sock_hash_update(skops, &sock_map, &ret,
201 						   BPF_NOEXIST);
202 #endif
203 		}
204 		break;
205 	default:
206 		break;
207 	}
208 
209 	return 0;
210 }
211 
212 SEC("sk_msg1")
213 int bpf_prog4(struct sk_msg_md *msg)
214 {
215 	int *bytes, zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
216 	int *start, *end, *start_push, *end_push, *start_pop, *pop;
217 
218 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
219 	if (bytes)
220 		bpf_msg_apply_bytes(msg, *bytes);
221 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
222 	if (bytes)
223 		bpf_msg_cork_bytes(msg, *bytes);
224 	start = bpf_map_lookup_elem(&sock_bytes, &zero);
225 	end = bpf_map_lookup_elem(&sock_bytes, &one);
226 	if (start && end)
227 		bpf_msg_pull_data(msg, *start, *end, 0);
228 	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
229 	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
230 	if (start_push && end_push)
231 		bpf_msg_push_data(msg, *start_push, *end_push, 0);
232 	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
233 	pop = bpf_map_lookup_elem(&sock_bytes, &five);
234 	if (start_pop && pop)
235 		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
236 	return SK_PASS;
237 }
238 
239 SEC("sk_msg2")
240 int bpf_prog6(struct sk_msg_md *msg)
241 {
242 	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, key = 0;
243 	int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
244 	__u64 flags = 0;
245 
246 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
247 	if (bytes)
248 		bpf_msg_apply_bytes(msg, *bytes);
249 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
250 	if (bytes)
251 		bpf_msg_cork_bytes(msg, *bytes);
252 
253 	start = bpf_map_lookup_elem(&sock_bytes, &zero);
254 	end = bpf_map_lookup_elem(&sock_bytes, &one);
255 	if (start && end)
256 		bpf_msg_pull_data(msg, *start, *end, 0);
257 
258 	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
259 	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
260 	if (start_push && end_push)
261 		bpf_msg_push_data(msg, *start_push, *end_push, 0);
262 
263 	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
264 	pop = bpf_map_lookup_elem(&sock_bytes, &five);
265 	if (start_pop && pop)
266 		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
267 
268 	f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
269 	if (f && *f) {
270 		key = 2;
271 		flags = *f;
272 	}
273 #ifdef SOCKMAP
274 	return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
275 #else
276 	return bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
277 #endif
278 }
279 
280 SEC("sk_msg3")
281 int bpf_prog8(struct sk_msg_md *msg)
282 {
283 	void *data_end = (void *)(long) msg->data_end;
284 	void *data = (void *)(long) msg->data;
285 	int ret = 0, *bytes, zero = 0;
286 
287 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
288 	if (bytes) {
289 		ret = bpf_msg_apply_bytes(msg, *bytes);
290 		if (ret)
291 			return SK_DROP;
292 	} else {
293 		return SK_DROP;
294 	}
295 	return SK_PASS;
296 }
297 SEC("sk_msg4")
298 int bpf_prog9(struct sk_msg_md *msg)
299 {
300 	void *data_end = (void *)(long) msg->data_end;
301 	void *data = (void *)(long) msg->data;
302 	int ret = 0, *bytes, zero = 0;
303 
304 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
305 	if (bytes) {
306 		if (((__u64)data_end - (__u64)data) >= *bytes)
307 			return SK_PASS;
308 		ret = bpf_msg_cork_bytes(msg, *bytes);
309 		if (ret)
310 			return SK_DROP;
311 	}
312 	return SK_PASS;
313 }
314 
315 SEC("sk_msg5")
316 int bpf_prog10(struct sk_msg_md *msg)
317 {
318 	int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop;
319 	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
320 
321 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
322 	if (bytes)
323 		bpf_msg_apply_bytes(msg, *bytes);
324 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
325 	if (bytes)
326 		bpf_msg_cork_bytes(msg, *bytes);
327 	start = bpf_map_lookup_elem(&sock_bytes, &zero);
328 	end = bpf_map_lookup_elem(&sock_bytes, &one);
329 	if (start && end)
330 		bpf_msg_pull_data(msg, *start, *end, 0);
331 	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
332 	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
333 	if (start_push && end_push)
334 		bpf_msg_push_data(msg, *start_push, *end_push, 0);
335 	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
336 	pop = bpf_map_lookup_elem(&sock_bytes, &five);
337 	if (start_pop && pop)
338 		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
339 	return SK_DROP;
340 }
341 
342 int _version SEC("version") = 1;
343 char _license[] SEC("license") = "GPL";
344