99 lines
2.2 KiB
C
99 lines
2.2 KiB
C
//go:build ignore
|
|
|
|
#include "common.h"
|
|
|
|
#include "bpf_endian.h"
|
|
#include "bpf_tracing.h"
|
|
|
|
#define AF_INET 2
|
|
#define TASK_COMM_LEN 16
|
|
|
|
char __license[] SEC("license") = "Dual MIT/GPL";
|
|
|
|
/**
|
|
* This example copies parts of struct sock_common and struct sock from
|
|
* the Linux kernel, but doesn't cause any CO-RE information to be emitted
|
|
* into the ELF object. This requires the struct layout (up until the fields
|
|
* that are being accessed) to match the kernel's, and the example will break
|
|
* or misbehave when this is no longer the case.
|
|
*
|
|
* Also note that BTF-enabled programs like fentry, fexit, fmod_ret, tp_btf,
|
|
* lsm, etc. declared using the BPF_PROG macro can read kernel memory without
|
|
* needing to call bpf_probe_read*().
|
|
*/
|
|
|
|
/**
|
|
* struct sock_common reflects the start of the kernel's struct sock_common.
|
|
* It only contains the fields up until skc_family that are accessed in the
|
|
* program, with padding to match the kernel's declaration.
|
|
*/
|
|
struct sock_common {
|
|
union {
|
|
struct {
|
|
__be32 skc_daddr;
|
|
__be32 skc_rcv_saddr;
|
|
};
|
|
};
|
|
union {
|
|
// Padding out union skc_hash.
|
|
__u32 _;
|
|
};
|
|
union {
|
|
struct {
|
|
__be16 skc_dport;
|
|
__u16 skc_num;
|
|
};
|
|
};
|
|
short unsigned int skc_family;
|
|
};
|
|
|
|
/**
|
|
* struct sock reflects the start of the kernel's struct sock.
|
|
*/
|
|
struct sock {
|
|
struct sock_common __sk_common;
|
|
};
|
|
|
|
struct {
|
|
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
|
__uint(max_entries, 1 << 24);
|
|
} events SEC(".maps");
|
|
|
|
/**
|
|
* The sample submitted to userspace over a ring buffer.
|
|
* Emit struct event's type info into the ELF's BTF so bpf2go
|
|
* can generate a Go type from it.
|
|
*/
|
|
struct event {
|
|
u8 comm[16];
|
|
__u16 sport;
|
|
__be16 dport;
|
|
__be32 saddr;
|
|
__be32 daddr;
|
|
};
|
|
struct event *unused __attribute__((unused));
|
|
|
|
SEC("fentry/tcp_connect")
|
|
int BPF_PROG(tcp_connect, struct sock *sk) {
|
|
if (sk->__sk_common.skc_family != AF_INET) {
|
|
return 0;
|
|
}
|
|
|
|
struct event *tcp_info;
|
|
tcp_info = bpf_ringbuf_reserve(&events, sizeof(struct event), 0);
|
|
if (!tcp_info) {
|
|
return 0;
|
|
}
|
|
|
|
tcp_info->saddr = sk->__sk_common.skc_rcv_saddr;
|
|
tcp_info->daddr = sk->__sk_common.skc_daddr;
|
|
tcp_info->dport = sk->__sk_common.skc_dport;
|
|
tcp_info->sport = bpf_htons(sk->__sk_common.skc_num);
|
|
|
|
bpf_get_current_comm(&tcp_info->comm, TASK_COMM_LEN);
|
|
|
|
bpf_ringbuf_submit(tcp_info, 0);
|
|
|
|
return 0;
|
|
}
|