2026-01-29 22:25:33 +08:00

161 lines
3.8 KiB
C

// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2023 Huawei Technologies Co., Ltd
*/
#include "bpf_sockmap.h"
#define NETACC_BIND_MAP_SIZE 100
#define CHECK_ACC_SOCK 1
struct ipaddr_port {
__u32 ip4;
__u32 port;
} __attribute__((packed));
#if CHECK_ACC_SOCK
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, struct ipaddr_port);
__type(value, int);
__uint(max_entries, NETACC_BIND_MAP_SIZE);
__uint(map_flags, 0);
} netacc_bind_map SEC(".maps");
static inline int __is_netacc_sock(struct ipaddr_port *key)
{
int *pv = NULL;
pv = bpf_map_lookup_elem(&netacc_bind_map, key);
if (pv)
return 1;
return 0;
}
static inline int is_netacc_sock(struct ipaddr_port *key1, struct ipaddr_port *key10)
{
net_dbg("is_netacc, ip1:0x%x, port1:0x%x\n", key1->ip4, key1->port);
if (__is_netacc_sock(key1))
return 1;
if (__is_netacc_sock(key10))
return 1;
return 0;
}
static inline void extract_dst_ipaddrport_from_ops(struct bpf_sock_ops *skops,
struct ipaddr_port *key)
{
if (skops->op == BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) {
key->ip4 = skops->remote_ip4;
// remote_port is in network byte order
key->port = bpf_ntohl(skops->remote_port);
} else if (skops->op == BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB) {
key->ip4 = skops->local_ip4;
// local_port is in host byte order
key->port = skops->local_port;
}
}
static inline int is_netacc_interested_tcp(struct bpf_sock_ops *skops)
{
struct ipaddr_port key = {0};
struct ipaddr_port key0;
// only test server's port
extract_dst_ipaddrport_from_ops(skops, &key);
key0.ip4 = 0;
key0.port = key.port;
if (!is_netacc_sock(&key, &key0))
return 0;
net_dbg("this is netacc sock\n");
net_dbg("the sock is netacc loopback sock\n");
return 1;
}
static inline int update_netacc_info(struct bpf_sock_ops *skops)
{
struct ipaddr_port key;
int value = 1;
char comm[16] = {0};
bpf_get_current_comm(comm, sizeof(comm));
if (bpf_strncmp(comm, 12, "redis-server"))
return 0;
key.ip4 = skops->local_ip4;
key.port = skops->local_port; // host order
bpf_map_update_elem(&netacc_bind_map, &key, &value, BPF_NOEXIST);
net_dbg("%s, update netaccinfo: sip:0x%x, sport:%d\n", comm, key.ip4, key.port);
return 1;
}
static inline void clean_netacc_info(struct bpf_sock_ops *skops)
{
struct ipaddr_port key;
key.ip4 = skops->local_ip4;
key.port = skops->local_port; // host order
net_dbg("clean netaccinfo, 0x%x:%d\n", key.ip4, key.port);
bpf_map_delete_elem(&netacc_bind_map, &key);
}
#else
static inline int is_netacc_interested_tcp(struct bpf_sock_ops *skops)
{
return 1;
}
static inline int update_netacc_info(struct bpf_sock_ops *skops)
{
return 0;
}
static inline void clean_netacc_info(struct bpf_sock_ops *skops)
{}
#endif
SEC("sockops")
int netacc_sockops(struct bpf_sock_ops *skops)
{
switch (skops->op) {
case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
if (skops->family == 2 && skops->local_skb) {// AF_INET
if (is_netacc_interested_tcp(skops)) {
net_dbg("bpf_sockops, sockmap, op:%d, sk:%p\n",
skops->op, skops->sk);
bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG);
bpf_sockmap_ipv4_insert(skops);
} else {
bpf_sock_ops_cb_flags_set(skops, 0);
}
}
break;
case BPF_SOCK_OPS_STATE_CB:
if (skops->family == 2 && skops->args[0] == BPF_TCP_LISTEN &&
skops->args[1] == BPF_TCP_CLOSE) {
clean_netacc_info(skops);
} else if (skops->family == 2 && (skops->args[1] == BPF_TCP_CLOSE ||
skops->args[1] == BPF_TCP_CLOSE_WAIT ||
skops->args[1] == BPF_TCP_FIN_WAIT1)) {
bpf_sockmap_ipv4_cleanup(skops, NULL);
}
break;
case BPF_SOCK_OPS_TCP_LISTEN_CB:
if (skops->family == 2 && update_netacc_info(skops))
bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG);
break;
default:
break;
}
return 1;
}
char _license[] SEC("license") = "GPL";
int _version SEC("version") = 1;