blob: c049ad4b6c3f260e5c1a0bcde5e40f3d2b781d40 [file] [log] [blame]
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (c) 2021 Hengqi Chen */
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_tracing.h>
#include "solisten.h"
#define MAX_ENTRIES 10240
#define AF_INET 2
#define AF_INET6 10
const volatile pid_t target_pid = 0;
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_ENTRIES);
__type(key, __u32);
__type(value, struct event);
} values SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(__u32));
__uint(value_size, sizeof(__u32));
} events SEC(".maps");
static void fill_event(struct event *event, struct socket *sock)
{
__u16 family, type;
struct sock *sk;
struct inet_sock *inet;
sk = BPF_CORE_READ(sock, sk);
inet = (struct inet_sock *)sk;
family = BPF_CORE_READ(sk, __sk_common.skc_family);
type = BPF_CORE_READ(sock, type);
event->proto = ((__u32)family << 16) | type;
event->port = bpf_ntohs(BPF_CORE_READ(inet, inet_sport));
if (family == AF_INET)
event->addr[0] = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);
else if (family == AF_INET6)
BPF_CORE_READ_INTO(event->addr, sk, __sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
bpf_get_current_comm(event->task, sizeof(event->task));
}
SEC("kprobe/inet_listen")
int BPF_KPROBE(inet_listen_entry, struct socket *sock, int backlog)
{
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u32 pid = pid_tgid >> 32;
__u32 tid = (__u32)pid_tgid;
struct event event = {};
if (target_pid && target_pid != pid)
return 0;
fill_event(&event, sock);
event.pid = pid;
event.backlog = backlog;
bpf_map_update_elem(&values, &tid, &event, BPF_ANY);
return 0;
}
SEC("kretprobe/inet_listen")
int BPF_KRETPROBE(inet_listen_exit, int ret)
{
__u32 tid = bpf_get_current_pid_tgid();
struct event *eventp;
eventp = bpf_map_lookup_elem(&values, &tid);
if (!eventp)
return 0;
eventp->ret = ret;
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, eventp, sizeof(*eventp));
bpf_map_delete_elem(&values, &tid);
return 0;
}
SEC("fexit/inet_listen")
int BPF_PROG(inet_listen_fexit, struct socket *sock, int backlog, int ret)
{
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u32 pid = pid_tgid >> 32;
struct event event = {};
if (target_pid && target_pid != pid)
return 0;
fill_event(&event, sock);
event.pid = pid;
event.backlog = backlog;
event.ret = ret;
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
return 0;
}
char LICENSE[] SEC("license") = "Dual BSD/GPL";