165b4414aSStanislav Fomichev // SPDX-License-Identifier: GPL-2.0
265b4414aSStanislav Fomichev #include <netinet/in.h>
365b4414aSStanislav Fomichev #include <linux/bpf.h>
43e689141SToke Høiland-Jørgensen #include <bpf/bpf_helpers.h>
565b4414aSStanislav Fomichev 
665b4414aSStanislav Fomichev char _license[] SEC("license") = "GPL";
765b4414aSStanislav Fomichev 
8*15669e1dSAndrii Nakryiko SEC("cgroup/getsockopt")
965b4414aSStanislav Fomichev int _getsockopt_child(struct bpf_sockopt *ctx)
1065b4414aSStanislav Fomichev {
1165b4414aSStanislav Fomichev 	__u8 *optval_end = ctx->optval_end;
1265b4414aSStanislav Fomichev 	__u8 *optval = ctx->optval;
1365b4414aSStanislav Fomichev 
1465b4414aSStanislav Fomichev 	if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
1565b4414aSStanislav Fomichev 		return 1;
1665b4414aSStanislav Fomichev 
1765b4414aSStanislav Fomichev 	if (optval + 1 > optval_end)
1865b4414aSStanislav Fomichev 		return 0; /* EPERM, bounds check */
1965b4414aSStanislav Fomichev 
2065b4414aSStanislav Fomichev 	if (optval[0] != 0x80)
2165b4414aSStanislav Fomichev 		return 0; /* EPERM, unexpected optval from the kernel */
2265b4414aSStanislav Fomichev 
2365b4414aSStanislav Fomichev 	ctx->retval = 0; /* Reset system call return value to zero */
2465b4414aSStanislav Fomichev 
2565b4414aSStanislav Fomichev 	optval[0] = 0x90;
2665b4414aSStanislav Fomichev 	ctx->optlen = 1;
2765b4414aSStanislav Fomichev 
2865b4414aSStanislav Fomichev 	return 1;
2965b4414aSStanislav Fomichev }
3065b4414aSStanislav Fomichev 
31*15669e1dSAndrii Nakryiko SEC("cgroup/getsockopt")
3265b4414aSStanislav Fomichev int _getsockopt_parent(struct bpf_sockopt *ctx)
3365b4414aSStanislav Fomichev {
3465b4414aSStanislav Fomichev 	__u8 *optval_end = ctx->optval_end;
3565b4414aSStanislav Fomichev 	__u8 *optval = ctx->optval;
3665b4414aSStanislav Fomichev 
3765b4414aSStanislav Fomichev 	if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
3865b4414aSStanislav Fomichev 		return 1;
3965b4414aSStanislav Fomichev 
4065b4414aSStanislav Fomichev 	if (optval + 1 > optval_end)
4165b4414aSStanislav Fomichev 		return 0; /* EPERM, bounds check */
4265b4414aSStanislav Fomichev 
4365b4414aSStanislav Fomichev 	if (optval[0] != 0x90)
4465b4414aSStanislav Fomichev 		return 0; /* EPERM, unexpected optval from the kernel */
4565b4414aSStanislav Fomichev 
4665b4414aSStanislav Fomichev 	ctx->retval = 0; /* Reset system call return value to zero */
4765b4414aSStanislav Fomichev 
4865b4414aSStanislav Fomichev 	optval[0] = 0xA0;
4965b4414aSStanislav Fomichev 	ctx->optlen = 1;
5065b4414aSStanislav Fomichev 
5165b4414aSStanislav Fomichev 	return 1;
5265b4414aSStanislav Fomichev }
5365b4414aSStanislav Fomichev 
5465b4414aSStanislav Fomichev SEC("cgroup/setsockopt")
5565b4414aSStanislav Fomichev int _setsockopt(struct bpf_sockopt *ctx)
5665b4414aSStanislav Fomichev {
5765b4414aSStanislav Fomichev 	__u8 *optval_end = ctx->optval_end;
5865b4414aSStanislav Fomichev 	__u8 *optval = ctx->optval;
5965b4414aSStanislav Fomichev 
6065b4414aSStanislav Fomichev 	if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
6165b4414aSStanislav Fomichev 		return 1;
6265b4414aSStanislav Fomichev 
6365b4414aSStanislav Fomichev 	if (optval + 1 > optval_end)
6465b4414aSStanislav Fomichev 		return 0; /* EPERM, bounds check */
6565b4414aSStanislav Fomichev 
6665b4414aSStanislav Fomichev 	optval[0] += 0x10;
6765b4414aSStanislav Fomichev 	ctx->optlen = 1;
6865b4414aSStanislav Fomichev 
6965b4414aSStanislav Fomichev 	return 1;
7065b4414aSStanislav Fomichev }
71