162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <netinet/in.h>
362306a36Sopenharmony_ci#include <linux/bpf.h>
462306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
562306a36Sopenharmony_ci
662306a36Sopenharmony_cichar _license[] SEC("license") = "GPL";
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci__u32 page_size = 0;
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ciSEC("cgroup/getsockopt")
1162306a36Sopenharmony_ciint _getsockopt_child(struct bpf_sockopt *ctx)
1262306a36Sopenharmony_ci{
1362306a36Sopenharmony_ci	__u8 *optval_end = ctx->optval_end;
1462306a36Sopenharmony_ci	__u8 *optval = ctx->optval;
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
1762306a36Sopenharmony_ci		goto out;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	if (optval + 1 > optval_end)
2062306a36Sopenharmony_ci		return 0; /* EPERM, bounds check */
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	if (optval[0] != 0x80)
2362306a36Sopenharmony_ci		return 0; /* EPERM, unexpected optval from the kernel */
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	ctx->retval = 0; /* Reset system call return value to zero */
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	optval[0] = 0x90;
2862306a36Sopenharmony_ci	ctx->optlen = 1;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	return 1;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ciout:
3362306a36Sopenharmony_ci	/* optval larger than PAGE_SIZE use kernel's buffer. */
3462306a36Sopenharmony_ci	if (ctx->optlen > page_size)
3562306a36Sopenharmony_ci		ctx->optlen = 0;
3662306a36Sopenharmony_ci	return 1;
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ciSEC("cgroup/getsockopt")
4062306a36Sopenharmony_ciint _getsockopt_parent(struct bpf_sockopt *ctx)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	__u8 *optval_end = ctx->optval_end;
4362306a36Sopenharmony_ci	__u8 *optval = ctx->optval;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
4662306a36Sopenharmony_ci		goto out;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	if (optval + 1 > optval_end)
4962306a36Sopenharmony_ci		return 0; /* EPERM, bounds check */
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	if (optval[0] != 0x90)
5262306a36Sopenharmony_ci		return 0; /* EPERM, unexpected optval from the kernel */
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	ctx->retval = 0; /* Reset system call return value to zero */
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	optval[0] = 0xA0;
5762306a36Sopenharmony_ci	ctx->optlen = 1;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	return 1;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ciout:
6262306a36Sopenharmony_ci	/* optval larger than PAGE_SIZE use kernel's buffer. */
6362306a36Sopenharmony_ci	if (ctx->optlen > page_size)
6462306a36Sopenharmony_ci		ctx->optlen = 0;
6562306a36Sopenharmony_ci	return 1;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ciSEC("cgroup/setsockopt")
6962306a36Sopenharmony_ciint _setsockopt(struct bpf_sockopt *ctx)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	__u8 *optval_end = ctx->optval_end;
7262306a36Sopenharmony_ci	__u8 *optval = ctx->optval;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
7562306a36Sopenharmony_ci		goto out;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	if (optval + 1 > optval_end)
7862306a36Sopenharmony_ci		return 0; /* EPERM, bounds check */
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	optval[0] += 0x10;
8162306a36Sopenharmony_ci	ctx->optlen = 1;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	return 1;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ciout:
8662306a36Sopenharmony_ci	/* optval larger than PAGE_SIZE use kernel's buffer. */
8762306a36Sopenharmony_ci	if (ctx->optlen > page_size)
8862306a36Sopenharmony_ci		ctx->optlen = 0;
8962306a36Sopenharmony_ci	return 1;
9062306a36Sopenharmony_ci}
91