162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <sys/socket.h>
462306a36Sopenharmony_ci#include <linux/bpf.h>
562306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ciint invocations = 0, in_use = 0;
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistruct {
1062306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_SK_STORAGE);
1162306a36Sopenharmony_ci	__uint(map_flags, BPF_F_NO_PREALLOC);
1262306a36Sopenharmony_ci	__type(key, int);
1362306a36Sopenharmony_ci	__type(value, int);
1462306a36Sopenharmony_ci} sk_map SEC(".maps");
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ciSEC("cgroup/sock_create")
1762306a36Sopenharmony_ciint sock(struct bpf_sock *ctx)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	int *sk_storage;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	if (ctx->type != SOCK_DGRAM)
2262306a36Sopenharmony_ci		return 1;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	sk_storage = bpf_sk_storage_get(&sk_map, ctx, 0,
2562306a36Sopenharmony_ci					BPF_SK_STORAGE_GET_F_CREATE);
2662306a36Sopenharmony_ci	if (!sk_storage)
2762306a36Sopenharmony_ci		return 0;
2862306a36Sopenharmony_ci	*sk_storage = 0xdeadbeef;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	__sync_fetch_and_add(&invocations, 1);
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	if (in_use > 0) {
3362306a36Sopenharmony_ci		/* BPF_CGROUP_INET_SOCK_RELEASE is _not_ called
3462306a36Sopenharmony_ci		 * when we return an error from the BPF
3562306a36Sopenharmony_ci		 * program!
3662306a36Sopenharmony_ci		 */
3762306a36Sopenharmony_ci		return 0;
3862306a36Sopenharmony_ci	}
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	__sync_fetch_and_add(&in_use, 1);
4162306a36Sopenharmony_ci	return 1;
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ciSEC("cgroup/sock_release")
4562306a36Sopenharmony_ciint sock_release(struct bpf_sock *ctx)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	int *sk_storage;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	if (ctx->type != SOCK_DGRAM)
5062306a36Sopenharmony_ci		return 1;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	sk_storage = bpf_sk_storage_get(&sk_map, ctx, 0, 0);
5362306a36Sopenharmony_ci	if (!sk_storage || *sk_storage != 0xdeadbeef)
5462306a36Sopenharmony_ci		return 0;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	__sync_fetch_and_add(&invocations, 1);
5762306a36Sopenharmony_ci	__sync_fetch_and_add(&in_use, -1);
5862306a36Sopenharmony_ci	return 1;
5962306a36Sopenharmony_ci}
60