1// SPDX-License-Identifier: GPL-2.0
2#include <netinet/in.h>
3#include <linux/bpf.h>
4#include <bpf/bpf_helpers.h>
5
6char _license[] SEC("license") = "GPL";
7
8__s32 page_size = 0;
9
10SEC("cgroup/getsockopt")
11int _getsockopt_child(struct bpf_sockopt *ctx)
12{
13 __u8 *optval_end = ctx->optval_end;
14 __u8 *optval = ctx->optval;
15
16 if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
17 goto out;
18
19 if (optval + 1 > optval_end)
20 return 0; /* EPERM, bounds check */
21
22 if (optval[0] != 0x80)
23 return 0; /* EPERM, unexpected optval from the kernel */
24
25 ctx->retval = 0; /* Reset system call return value to zero */
26
27 optval[0] = 0x90;
28 ctx->optlen = 1;
29
30 return 1;
31
32out:
33 /* optval larger than PAGE_SIZE use kernel's buffer. */
34 if (ctx->optlen > page_size)
35 ctx->optlen = 0;
36 return 1;
37}
38
39SEC("cgroup/getsockopt")
40int _getsockopt_parent(struct bpf_sockopt *ctx)
41{
42 __u8 *optval_end = ctx->optval_end;
43 __u8 *optval = ctx->optval;
44
45 if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
46 goto out;
47
48 if (optval + 1 > optval_end)
49 return 0; /* EPERM, bounds check */
50
51 if (optval[0] != 0x90)
52 return 0; /* EPERM, unexpected optval from the kernel */
53
54 ctx->retval = 0; /* Reset system call return value to zero */
55
56 optval[0] = 0xA0;
57 ctx->optlen = 1;
58
59 return 1;
60
61out:
62 /* optval larger than PAGE_SIZE use kernel's buffer. */
63 if (ctx->optlen > page_size)
64 ctx->optlen = 0;
65 return 1;
66}
67
68SEC("cgroup/setsockopt")
69int _setsockopt(struct bpf_sockopt *ctx)
70{
71 __u8 *optval_end = ctx->optval_end;
72 __u8 *optval = ctx->optval;
73
74 if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
75 goto out;
76
77 if (optval + 1 > optval_end)
78 return 0; /* EPERM, bounds check */
79
80 optval[0] += 0x10;
81 ctx->optlen = 1;
82
83 return 1;
84
85out:
86 /* optval larger than PAGE_SIZE use kernel's buffer. */
87 if (ctx->optlen > page_size)
88 ctx->optlen = 0;
89 return 1;
90}
91

source code of linux/tools/testing/selftests/bpf/progs/sockopt_multi.c