github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/examples/fentry/fentry.c (about) 1 //go:build ignore 2 3 #include "common.h" 4 5 #include "bpf_endian.h" 6 #include "bpf_tracing.h" 7 8 #define AF_INET 2 9 #define TASK_COMM_LEN 16 10 11 char __license[] SEC("license") = "Dual MIT/GPL"; 12 13 /** 14 * This example copies parts of struct sock_common and struct sock from 15 * the Linux kernel, but doesn't cause any CO-RE information to be emitted 16 * into the ELF object. This requires the struct layout (up until the fields 17 * that are being accessed) to match the kernel's, and the example will break 18 * or misbehave when this is no longer the case. 19 * 20 * Also note that BTF-enabled programs like fentry, fexit, fmod_ret, tp_btf, 21 * lsm, etc. declared using the BPF_PROG macro can read kernel memory without 22 * needing to call bpf_probe_read*(). 23 */ 24 25 /** 26 * struct sock_common reflects the start of the kernel's struct sock_common. 27 * It only contains the fields up until skc_family that are accessed in the 28 * program, with padding to match the kernel's declaration. 29 */ 30 struct sock_common { 31 union { 32 struct { 33 __be32 skc_daddr; 34 __be32 skc_rcv_saddr; 35 }; 36 }; 37 union { 38 // Padding out union skc_hash. 39 __u32 _; 40 }; 41 union { 42 struct { 43 __be16 skc_dport; 44 __u16 skc_num; 45 }; 46 }; 47 short unsigned int skc_family; 48 }; 49 50 /** 51 * struct sock reflects the start of the kernel's struct sock. 52 */ 53 struct sock { 54 struct sock_common __sk_common; 55 }; 56 57 struct { 58 __uint(type, BPF_MAP_TYPE_RINGBUF); 59 __uint(max_entries, 1 << 24); 60 } events SEC(".maps"); 61 62 /** 63 * The sample submitted to userspace over a ring buffer. 64 * Emit struct event's type info into the ELF's BTF so bpf2go 65 * can generate a Go type from it. 66 */ 67 struct event { 68 u8 comm[16]; 69 __u16 sport; 70 __be16 dport; 71 __be32 saddr; 72 __be32 daddr; 73 }; 74 struct event *unused __attribute__((unused)); 75 76 SEC("fentry/tcp_connect") 77 int BPF_PROG(tcp_connect, struct sock *sk) { 78 if (sk->__sk_common.skc_family != AF_INET) { 79 return 0; 80 } 81 82 struct event *tcp_info; 83 tcp_info = bpf_ringbuf_reserve(&events, sizeof(struct event), 0); 84 if (!tcp_info) { 85 return 0; 86 } 87 88 tcp_info->saddr = sk->__sk_common.skc_rcv_saddr; 89 tcp_info->daddr = sk->__sk_common.skc_daddr; 90 tcp_info->dport = sk->__sk_common.skc_dport; 91 tcp_info->sport = bpf_htons(sk->__sk_common.skc_num); 92 93 bpf_get_current_comm(&tcp_info->comm, TASK_COMM_LEN); 94 95 bpf_ringbuf_submit(tcp_info, 0); 96 97 return 0; 98 }