161 lines
3.8 KiB
C
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;
|