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  }