1251875Speter// SPDX-License-Identifier: GPL-2.0
2251875Speter#include <netinet/in.h>
3251875Speter#include <linux/bpf.h>
4251875Speter#include <bpf/bpf_helpers.h>
5251875Speter
6251875Speterchar _license[] SEC("license") = "GPL";
7251875Speter
8251875Speter__s32 page_size = 0;
9251875Speter
10251875SpeterSEC("cgroup/getsockopt")
11251875Speterint _getsockopt_child(struct bpf_sockopt *ctx)
12251875Speter{
13251875Speter	__u8 *optval_end = ctx->optval_end;
14251875Speter	__u8 *optval = ctx->optval;
15251875Speter
16251875Speter	if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
17251875Speter		goto out;
18251875Speter
19251875Speter	if (optval + 1 > optval_end)
20251875Speter		return 0; /* EPERM, bounds check */
21251875Speter
22251875Speter	if (optval[0] != 0x80)
23251875Speter		return 0; /* EPERM, unexpected optval from the kernel */
24251875Speter
25251875Speter	ctx->retval = 0; /* Reset system call return value to zero */
26251875Speter
27251875Speter	optval[0] = 0x90;
28251875Speter	ctx->optlen = 1;
29251875Speter
30251875Speter	return 1;
31251875Speter
32251875Speterout:
33251875Speter	/* optval larger than PAGE_SIZE use kernel's buffer. */
34251875Speter	if (ctx->optlen > page_size)
35251875Speter		ctx->optlen = 0;
36251875Speter	return 1;
37251875Speter}
38251875Speter
39251875SpeterSEC("cgroup/getsockopt")
40251875Speterint _getsockopt_parent(struct bpf_sockopt *ctx)
41251875Speter{
42251875Speter	__u8 *optval_end = ctx->optval_end;
43251875Speter	__u8 *optval = ctx->optval;
44251875Speter
45251875Speter	if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
46251875Speter		goto out;
47251875Speter
48251875Speter	if (optval + 1 > optval_end)
49251875Speter		return 0; /* EPERM, bounds check */
50251875Speter
51251875Speter	if (optval[0] != 0x90)
52251875Speter		return 0; /* EPERM, unexpected optval from the kernel */
53251875Speter
54251875Speter	ctx->retval = 0; /* Reset system call return value to zero */
55251875Speter
56251875Speter	optval[0] = 0xA0;
57251875Speter	ctx->optlen = 1;
58251875Speter
59251875Speter	return 1;
60251875Speter
61251875Speterout:
62251875Speter	/* optval larger than PAGE_SIZE use kernel's buffer. */
63251875Speter	if (ctx->optlen > page_size)
64251875Speter		ctx->optlen = 0;
65251875Speter	return 1;
66251875Speter}
67251875Speter
68251875SpeterSEC("cgroup/setsockopt")
69251875Speterint _setsockopt(struct bpf_sockopt *ctx)
70251875Speter{
71251875Speter	__u8 *optval_end = ctx->optval_end;
72251875Speter	__u8 *optval = ctx->optval;
73251875Speter
74251875Speter	if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
75251875Speter		goto out;
76251875Speter
77251875Speter	if (optval + 1 > optval_end)
78251875Speter		return 0; /* EPERM, bounds check */
79251875Speter
80251875Speter	optval[0] += 0x10;
81251875Speter	ctx->optlen = 1;
82251875Speter
83251875Speter	return 1;
84251875Speter
85251875Speterout:
86251875Speter	/* optval larger than PAGE_SIZE use kernel's buffer. */
87251875Speter	if (ctx->optlen > page_size)
88251875Speter		ctx->optlen = 0;
89251875Speter	return 1;
90251875Speter}
91251875Speter