#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_endian.h>
#define MAX_ENTRIES 32768
#define TASK_COMM_LEN 16
#define AF_INET 2
#define AF_INET6 10
#define IPPROTO_ICMP 1
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
#define IPPROTO_ICMPV6 58
struct conn_key
{
__u32 saddr[4]; __u32 daddr[4]; __u16 sport;
__u16 dport;
__u8 proto; __u8 family; } __attribute__((packed));
struct conn_info
{
__u32 pid;
__u32 uid;
char comm[TASK_COMM_LEN];
__u64 timestamp;
} __attribute__((packed));
struct
{
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_ENTRIES);
__type(key, struct conn_key);
__type(value, struct conn_info);
} socket_map SEC(".maps");
struct task_struct___local
{
struct task_struct___local *group_leader;
char comm[TASK_COMM_LEN];
} __attribute__((preserve_access_index));
static __always_inline void get_process_info(struct conn_info *info)
{
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u64 uid_gid = bpf_get_current_uid_gid();
info->pid = pid_tgid >> 32;
info->uid = uid_gid >> 32;
info->timestamp = bpf_ktime_get_ns();
struct task_struct___local *task =
(struct task_struct___local *)bpf_get_current_task();
long err = BPF_CORE_READ_STR_INTO(&info->comm, task, group_leader, comm);
if (err <= 0 || info->comm[0] == '\0')
{
bpf_get_current_comm(&info->comm, sizeof(info->comm));
}
}
SEC("kprobe/tcp_connect")
int trace_tcp_connect(struct pt_regs *ctx)
{
struct sock *sk = (struct sock *)PT_REGS_PARM1_CORE(ctx);
if (!sk)
{
return 0;
}
struct conn_key key = {};
struct conn_info info = {};
key.saddr[0] = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);
key.daddr[0] = BPF_CORE_READ(sk, __sk_common.skc_daddr);
key.sport = BPF_CORE_READ(sk, __sk_common.skc_num);
key.dport = BPF_CORE_READ(sk, __sk_common.skc_dport);
key.dport = bpf_ntohs(key.dport);
key.proto = IPPROTO_TCP;
key.family = AF_INET;
get_process_info(&info);
int ret = bpf_map_update_elem(&socket_map, &key, &info, BPF_ANY);
if (ret != 0)
{
bpf_printk("tcp_connect: map update failed ret=%d", ret);
}
return 0;
}
SEC("kprobe/inet_csk_accept")
int trace_tcp_accept(struct pt_regs *ctx)
{
struct sock *sk = (struct sock *)PT_REGS_PARM1_CORE(ctx);
if (!sk)
{
return 0;
}
struct conn_key key = {};
struct conn_info info = {};
key.saddr[0] = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);
key.daddr[0] = BPF_CORE_READ(sk, __sk_common.skc_daddr);
key.sport = BPF_CORE_READ(sk, __sk_common.skc_num);
key.dport = BPF_CORE_READ(sk, __sk_common.skc_dport);
key.dport = bpf_ntohs(key.dport);
key.proto = IPPROTO_TCP;
key.family = AF_INET;
get_process_info(&info);
int ret = bpf_map_update_elem(&socket_map, &key, &info, BPF_ANY);
if (ret != 0)
{
bpf_printk("inet_csk_accept: map update failed ret=%d", ret);
}
return 0;
}
SEC("kprobe/udp_sendmsg")
int trace_udp_sendmsg(struct pt_regs *ctx)
{
struct sock *sk = (struct sock *)PT_REGS_PARM1_CORE(ctx);
struct msghdr *msg = (struct msghdr *)PT_REGS_PARM2_CORE(ctx);
if (!sk || !msg)
{
return 0;
}
struct conn_key key = {};
struct conn_info info = {};
key.saddr[0] = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);
key.sport = BPF_CORE_READ(sk, __sk_common.skc_num);
struct sockaddr_in *dest_addr = NULL;
bpf_probe_read_kernel(&dest_addr, sizeof(dest_addr), &msg->msg_name);
if (dest_addr)
{
bpf_probe_read_kernel(&key.daddr[0], sizeof(__u32), &dest_addr->sin_addr.s_addr);
bpf_probe_read_kernel(&key.dport, sizeof(__u16), &dest_addr->sin_port);
}
else
{
key.daddr[0] = BPF_CORE_READ(sk, __sk_common.skc_daddr);
key.dport = BPF_CORE_READ(sk, __sk_common.skc_dport);
}
if (key.daddr[0] == 0)
{
return 0;
}
key.dport = bpf_ntohs(key.dport);
key.proto = IPPROTO_UDP;
key.family = AF_INET;
get_process_info(&info);
int ret = bpf_map_update_elem(&socket_map, &key, &info, BPF_ANY);
if (ret != 0)
{
bpf_printk("udp_sendmsg: map update failed ret=%d", ret);
}
return 0;
}
SEC("kprobe/tcp_v6_connect")
int trace_tcp_v6_connect(struct pt_regs *ctx)
{
struct sock *sk = (struct sock *)PT_REGS_PARM1_CORE(ctx);
if (!sk)
return 0;
struct conn_key key = {};
struct conn_info info = {};
struct in6_addr temp_saddr, temp_daddr;
BPF_CORE_READ_INTO(&temp_saddr, sk, __sk_common.skc_v6_rcv_saddr);
BPF_CORE_READ_INTO(&temp_daddr, sk, __sk_common.skc_v6_daddr);
__builtin_memcpy(key.saddr, &temp_saddr, sizeof(temp_saddr));
__builtin_memcpy(key.daddr, &temp_daddr, sizeof(temp_daddr));
key.sport = BPF_CORE_READ(sk, __sk_common.skc_num);
key.dport = BPF_CORE_READ(sk, __sk_common.skc_dport);
key.dport = bpf_ntohs(key.dport);
key.proto = IPPROTO_TCP;
key.family = AF_INET6;
get_process_info(&info);
bpf_map_update_elem(&socket_map, &key, &info, BPF_ANY);
return 0;
}
SEC("kprobe/udpv6_sendmsg")
int trace_udp_v6_sendmsg(struct pt_regs *ctx)
{
struct sock *sk = (struct sock *)PT_REGS_PARM1_CORE(ctx);
if (!sk)
return 0;
struct conn_key key = {};
struct conn_info info = {};
struct in6_addr temp_saddr, temp_daddr;
BPF_CORE_READ_INTO(&temp_saddr, sk, __sk_common.skc_v6_rcv_saddr);
BPF_CORE_READ_INTO(&temp_daddr, sk, __sk_common.skc_v6_daddr);
__builtin_memcpy(key.saddr, &temp_saddr, sizeof(temp_saddr));
__builtin_memcpy(key.daddr, &temp_daddr, sizeof(temp_daddr));
key.sport = BPF_CORE_READ(sk, __sk_common.skc_num);
key.dport = BPF_CORE_READ(sk, __sk_common.skc_dport);
key.dport = bpf_ntohs(key.dport);
key.proto = IPPROTO_UDP;
key.family = AF_INET6;
get_process_info(&info);
bpf_map_update_elem(&socket_map, &key, &info, BPF_ANY);
return 0;
}
SEC("kprobe/ping_v4_sendmsg")
int trace_ping_v4_sendmsg(struct pt_regs *ctx)
{
struct sock *sk = (struct sock *)PT_REGS_PARM1_CORE(ctx);
struct msghdr *msg = (struct msghdr *)PT_REGS_PARM2_CORE(ctx);
if (!sk || !msg)
return 0;
struct conn_key key = {};
struct conn_info info = {};
key.saddr[0] = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);
key.sport = BPF_CORE_READ(sk, __sk_common.skc_num);
struct sockaddr_in *dest_addr = NULL;
bpf_probe_read_kernel(&dest_addr, sizeof(dest_addr), &msg->msg_name);
if (dest_addr)
{
bpf_probe_read_kernel(&key.daddr[0], sizeof(__u32), &dest_addr->sin_addr.s_addr);
}
else
{
key.daddr[0] = BPF_CORE_READ(sk, __sk_common.skc_daddr);
}
if (key.daddr[0] == 0)
return 0;
key.dport = 0; key.proto = IPPROTO_ICMP;
key.family = AF_INET;
get_process_info(&info);
bpf_map_update_elem(&socket_map, &key, &info, BPF_ANY);
return 0;
}
SEC("kprobe/ping_v6_sendmsg")
int trace_ping_v6_sendmsg(struct pt_regs *ctx)
{
struct sock *sk = (struct sock *)PT_REGS_PARM1_CORE(ctx);
struct msghdr *msg = (struct msghdr *)PT_REGS_PARM2_CORE(ctx);
if (!sk || !msg)
return 0;
struct conn_key key = {};
struct conn_info info = {};
struct in6_addr temp_saddr;
BPF_CORE_READ_INTO(&temp_saddr, sk, __sk_common.skc_v6_rcv_saddr);
__builtin_memcpy(key.saddr, &temp_saddr, sizeof(temp_saddr));
key.sport = BPF_CORE_READ(sk, __sk_common.skc_num);
struct sockaddr_in6 *dest_addr = NULL;
bpf_probe_read_kernel(&dest_addr, sizeof(dest_addr), &msg->msg_name);
if (dest_addr)
{
struct in6_addr temp_daddr;
bpf_probe_read_kernel(&temp_daddr, sizeof(temp_daddr), &dest_addr->sin6_addr);
__builtin_memcpy(key.daddr, &temp_daddr, sizeof(temp_daddr));
}
else
{
struct in6_addr temp_daddr;
BPF_CORE_READ_INTO(&temp_daddr, sk, __sk_common.skc_v6_daddr);
__builtin_memcpy(key.daddr, &temp_daddr, sizeof(temp_daddr));
}
key.dport = 0;
key.proto = IPPROTO_ICMPV6;
key.family = AF_INET6;
get_process_info(&info);
bpf_map_update_elem(&socket_map, &key, &info, BPF_ANY);
return 0;
}
char LICENSE[] SEC("license") = "Dual BSD/GPL";