Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  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_helpers.h"
 16#include "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
 31struct {
 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
 38struct {
 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
 45struct {
 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
 52struct {
 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
 59struct {
 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
 66struct {
 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
 73struct {
 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
 80struct {
 81	__uint(type, BPF_MAP_TYPE_ARRAY);
 82	__uint(max_entries, 1);
 83	__type(key, int);
 84	__type(value, int);
 85} sock_skb_opts SEC(".maps");
 86
 87SEC("sk_skb1")
 88int bpf_prog1(struct __sk_buff *skb)
 89{
 90	return skb->len;
 91}
 92
 93SEC("sk_skb2")
 94int bpf_prog2(struct __sk_buff *skb)
 95{
 96	__u32 lport = skb->local_port;
 97	__u32 rport = skb->remote_port;
 98	int len, *f, ret, zero = 0;
 99	__u64 flags = 0;
100
101	if (lport == 10000)
102		ret = 10;
103	else
104		ret = 1;
105
106	len = (__u32)skb->data_end - (__u32)skb->data;
107	f = bpf_map_lookup_elem(&sock_skb_opts, &zero);
108	if (f && *f) {
109		ret = 3;
110		flags = *f;
111	}
112
113	bpf_printk("sk_skb2: redirect(%iB) flags=%i\n",
114		   len, flags);
115#ifdef SOCKMAP
116	return bpf_sk_redirect_map(skb, &sock_map, ret, flags);
117#else
118	return bpf_sk_redirect_hash(skb, &sock_map, &ret, flags);
119#endif
120
121}
122
123SEC("sockops")
124int bpf_sockmap(struct bpf_sock_ops *skops)
125{
126	__u32 lport, rport;
127	int op, err = 0, index, key, ret;
128
129
130	op = (int) skops->op;
131
132	switch (op) {
133	case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
134		lport = skops->local_port;
135		rport = skops->remote_port;
136
137		if (lport == 10000) {
138			ret = 1;
139#ifdef SOCKMAP
140			err = bpf_sock_map_update(skops, &sock_map, &ret,
141						  BPF_NOEXIST);
142#else
143			err = bpf_sock_hash_update(skops, &sock_map, &ret,
144						   BPF_NOEXIST);
145#endif
146			bpf_printk("passive(%i -> %i) map ctx update err: %d\n",
147				   lport, bpf_ntohl(rport), err);
148		}
149		break;
150	case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
151		lport = skops->local_port;
152		rport = skops->remote_port;
153
154		if (bpf_ntohl(rport) == 10001) {
155			ret = 10;
156#ifdef SOCKMAP
157			err = bpf_sock_map_update(skops, &sock_map, &ret,
158						  BPF_NOEXIST);
159#else
160			err = bpf_sock_hash_update(skops, &sock_map, &ret,
161						   BPF_NOEXIST);
162#endif
163			bpf_printk("active(%i -> %i) map ctx update err: %d\n",
164				   lport, bpf_ntohl(rport), err);
165		}
166		break;
167	default:
168		break;
169	}
170
171	return 0;
172}
173
174SEC("sk_msg1")
175int bpf_prog4(struct sk_msg_md *msg)
176{
177	int *bytes, zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
178	int *start, *end, *start_push, *end_push, *start_pop, *pop;
179
180	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
181	if (bytes)
182		bpf_msg_apply_bytes(msg, *bytes);
183	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
184	if (bytes)
185		bpf_msg_cork_bytes(msg, *bytes);
186	start = bpf_map_lookup_elem(&sock_bytes, &zero);
187	end = bpf_map_lookup_elem(&sock_bytes, &one);
188	if (start && end)
189		bpf_msg_pull_data(msg, *start, *end, 0);
190	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
191	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
192	if (start_push && end_push)
193		bpf_msg_push_data(msg, *start_push, *end_push, 0);
194	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
195	pop = bpf_map_lookup_elem(&sock_bytes, &five);
196	if (start_pop && pop)
197		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
198	return SK_PASS;
199}
200
201SEC("sk_msg2")
202int bpf_prog5(struct sk_msg_md *msg)
203{
204	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
205	int *start, *end, *start_push, *end_push, *start_pop, *pop;
206	int *bytes, len1, len2 = 0, len3, len4;
207	int err1 = -1, err2 = -1;
208
209	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
210	if (bytes)
211		err1 = bpf_msg_apply_bytes(msg, *bytes);
212	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
213	if (bytes)
214		err2 = bpf_msg_cork_bytes(msg, *bytes);
215	len1 = (__u64)msg->data_end - (__u64)msg->data;
216	start = bpf_map_lookup_elem(&sock_bytes, &zero);
217	end = bpf_map_lookup_elem(&sock_bytes, &one);
218	if (start && end) {
219		int err;
220
221		bpf_printk("sk_msg2: pull(%i:%i)\n",
222			   start ? *start : 0, end ? *end : 0);
223		err = bpf_msg_pull_data(msg, *start, *end, 0);
224		if (err)
225			bpf_printk("sk_msg2: pull_data err %i\n",
226				   err);
227		len2 = (__u64)msg->data_end - (__u64)msg->data;
228		bpf_printk("sk_msg2: length update %i->%i\n",
229			   len1, len2);
230	}
231
232	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
233	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
234	if (start_push && end_push) {
235		int err;
236
237		bpf_printk("sk_msg2: push(%i:%i)\n",
238			   start_push ? *start_push : 0,
239			   end_push ? *end_push : 0);
240		err = bpf_msg_push_data(msg, *start_push, *end_push, 0);
241		if (err)
242			bpf_printk("sk_msg2: push_data err %i\n", err);
243		len3 = (__u64)msg->data_end - (__u64)msg->data;
244		bpf_printk("sk_msg2: length push_update %i->%i\n",
245			   len2 ? len2 : len1, len3);
246	}
247	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
248	pop = bpf_map_lookup_elem(&sock_bytes, &five);
249	if (start_pop && pop) {
250		int err;
251
252		bpf_printk("sk_msg2: pop(%i@%i)\n",
253			   start_pop, pop);
254		err = bpf_msg_pop_data(msg, *start_pop, *pop, 0);
255		if (err)
256			bpf_printk("sk_msg2: pop_data err %i\n", err);
257		len4 = (__u64)msg->data_end - (__u64)msg->data;
258		bpf_printk("sk_msg2: length pop_data %i->%i\n",
259			   len1 ? len1 : 0,  len4);
260	}
261
262	bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
263		   len1, err1, err2);
264	return SK_PASS;
265}
266
267SEC("sk_msg3")
268int bpf_prog6(struct sk_msg_md *msg)
269{
270	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, key = 0;
271	int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
272	__u64 flags = 0;
273
274	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
275	if (bytes)
276		bpf_msg_apply_bytes(msg, *bytes);
277	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
278	if (bytes)
279		bpf_msg_cork_bytes(msg, *bytes);
280
281	start = bpf_map_lookup_elem(&sock_bytes, &zero);
282	end = bpf_map_lookup_elem(&sock_bytes, &one);
283	if (start && end)
284		bpf_msg_pull_data(msg, *start, *end, 0);
285
286	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
287	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
288	if (start_push && end_push)
289		bpf_msg_push_data(msg, *start_push, *end_push, 0);
290
291	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
292	pop = bpf_map_lookup_elem(&sock_bytes, &five);
293	if (start_pop && pop)
294		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
295
296	f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
297	if (f && *f) {
298		key = 2;
299		flags = *f;
300	}
301#ifdef SOCKMAP
302	return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
303#else
304	return bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
305#endif
306}
307
308SEC("sk_msg4")
309int bpf_prog7(struct sk_msg_md *msg)
310{
311	int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
312	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
313	int len1, len2 = 0, len3, len4;
314	int err1 = 0, err2 = 0, key = 0;
315	__u64 flags = 0;
316
317		int err;
318	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
319	if (bytes)
320		err1 = bpf_msg_apply_bytes(msg, *bytes);
321	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
322	if (bytes)
323		err2 = bpf_msg_cork_bytes(msg, *bytes);
324	len1 = (__u64)msg->data_end - (__u64)msg->data;
325
326	start = bpf_map_lookup_elem(&sock_bytes, &zero);
327	end = bpf_map_lookup_elem(&sock_bytes, &one);
328	if (start && end) {
329		bpf_printk("sk_msg2: pull(%i:%i)\n",
330			   start ? *start : 0, end ? *end : 0);
331		err = bpf_msg_pull_data(msg, *start, *end, 0);
332		if (err)
333			bpf_printk("sk_msg2: pull_data err %i\n",
334				   err);
335		len2 = (__u64)msg->data_end - (__u64)msg->data;
336		bpf_printk("sk_msg2: length update %i->%i\n",
337			   len1, len2);
338	}
339
340	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
341	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
342	if (start_push && end_push) {
343		bpf_printk("sk_msg4: push(%i:%i)\n",
344			   start_push ? *start_push : 0,
345			   end_push ? *end_push : 0);
346		err = bpf_msg_push_data(msg, *start_push, *end_push, 0);
347		if (err)
348			bpf_printk("sk_msg4: push_data err %i\n",
349				   err);
350		len3 = (__u64)msg->data_end - (__u64)msg->data;
351		bpf_printk("sk_msg4: length push_update %i->%i\n",
352			   len2 ? len2 : len1, len3);
353	}
354
355	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
356	pop = bpf_map_lookup_elem(&sock_bytes, &five);
357	if (start_pop && pop) {
358		int err;
359
360		bpf_printk("sk_msg4: pop(%i@%i)\n",
361			   start_pop, pop);
362		err = bpf_msg_pop_data(msg, *start_pop, *pop, 0);
363		if (err)
364			bpf_printk("sk_msg4: pop_data err %i\n", err);
365		len4 = (__u64)msg->data_end - (__u64)msg->data;
366		bpf_printk("sk_msg4: length pop_data %i->%i\n",
367			   len1 ? len1 : 0,  len4);
368	}
369
370
371	f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
372	if (f && *f) {
373		key = 2;
374		flags = *f;
375	}
376	bpf_printk("sk_msg3: redirect(%iB) flags=%i err=%i\n",
377		   len1, flags, err1 ? err1 : err2);
378#ifdef SOCKMAP
379	err = bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
380#else
381	err = bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
382#endif
383	bpf_printk("sk_msg3: err %i\n", err);
384	return err;
385}
386
387SEC("sk_msg5")
388int bpf_prog8(struct sk_msg_md *msg)
389{
390	void *data_end = (void *)(long) msg->data_end;
391	void *data = (void *)(long) msg->data;
392	int ret = 0, *bytes, zero = 0;
393
394	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
395	if (bytes) {
396		ret = bpf_msg_apply_bytes(msg, *bytes);
397		if (ret)
398			return SK_DROP;
399	} else {
400		return SK_DROP;
401	}
402	return SK_PASS;
403}
404SEC("sk_msg6")
405int bpf_prog9(struct sk_msg_md *msg)
406{
407	void *data_end = (void *)(long) msg->data_end;
408	void *data = (void *)(long) msg->data;
409	int ret = 0, *bytes, zero = 0;
410
411	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
412	if (bytes) {
413		if (((__u64)data_end - (__u64)data) >= *bytes)
414			return SK_PASS;
415		ret = bpf_msg_cork_bytes(msg, *bytes);
416		if (ret)
417			return SK_DROP;
418	}
419	return SK_PASS;
420}
421
422SEC("sk_msg7")
423int bpf_prog10(struct sk_msg_md *msg)
424{
425	int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop;
426	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
427
428	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
429	if (bytes)
430		bpf_msg_apply_bytes(msg, *bytes);
431	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
432	if (bytes)
433		bpf_msg_cork_bytes(msg, *bytes);
434	start = bpf_map_lookup_elem(&sock_bytes, &zero);
435	end = bpf_map_lookup_elem(&sock_bytes, &one);
436	if (start && end)
437		bpf_msg_pull_data(msg, *start, *end, 0);
438	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
439	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
440	if (start_push && end_push)
441		bpf_msg_push_data(msg, *start_push, *end_push, 0);
442	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
443	pop = bpf_map_lookup_elem(&sock_bytes, &five);
444	if (start_pop && pop)
445		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
446	bpf_printk("return sk drop\n");
447	return SK_DROP;
448}
449
450int _version SEC("version") = 1;
451char _license[] SEC("license") = "GPL";