1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright Amazon.com Inc. or its affiliates. */ |
3 | #include "bpf_iter.h" |
4 | #include "bpf_tracing_net.h" |
5 | #include <bpf/bpf_helpers.h> |
6 | #include <bpf/bpf_endian.h> |
7 | |
8 | char _license[] SEC("license" ) = "GPL" ; |
9 | |
10 | static long sock_i_ino(const struct sock *sk) |
11 | { |
12 | const struct socket *sk_socket = sk->sk_socket; |
13 | const struct inode *inode; |
14 | unsigned long ino; |
15 | |
16 | if (!sk_socket) |
17 | return 0; |
18 | |
19 | inode = &container_of(sk_socket, struct socket_alloc, socket)->vfs_inode; |
20 | bpf_probe_read_kernel(&ino, sizeof(ino), &inode->i_ino); |
21 | return ino; |
22 | } |
23 | |
24 | SEC("iter/unix" ) |
25 | int dump_unix(struct bpf_iter__unix *ctx) |
26 | { |
27 | struct unix_sock *unix_sk = ctx->unix_sk; |
28 | struct sock *sk = (struct sock *)unix_sk; |
29 | struct seq_file *seq; |
30 | __u32 seq_num; |
31 | |
32 | if (!unix_sk) |
33 | return 0; |
34 | |
35 | seq = ctx->meta->seq; |
36 | seq_num = ctx->meta->seq_num; |
37 | if (seq_num == 0) |
38 | BPF_SEQ_PRINTF(seq, "Num RefCount Protocol Flags Type St Inode Path\n" ); |
39 | |
40 | BPF_SEQ_PRINTF(seq, "%pK: %08X %08X %08X %04X %02X %8lu" , |
41 | unix_sk, |
42 | sk->sk_refcnt.refs.counter, |
43 | 0, |
44 | sk->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0, |
45 | sk->sk_type, |
46 | sk->sk_socket ? |
47 | (sk->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) : |
48 | (sk->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING), |
49 | sock_i_ino(sk)); |
50 | |
51 | if (unix_sk->addr) { |
52 | if (unix_sk->addr->name->sun_path[0]) { |
53 | BPF_SEQ_PRINTF(seq, " %s" , unix_sk->addr->name->sun_path); |
54 | } else { |
55 | /* The name of the abstract UNIX domain socket starts |
56 | * with '\0' and can contain '\0'. The null bytes |
57 | * should be escaped as done in unix_seq_show(). |
58 | */ |
59 | __u64 i, len; |
60 | |
61 | len = unix_sk->addr->len - sizeof(short); |
62 | |
63 | BPF_SEQ_PRINTF(seq, " @" ); |
64 | |
65 | for (i = 1; i < len; i++) { |
66 | /* unix_validate_addr() tests this upper bound. */ |
67 | if (i >= sizeof(struct sockaddr_un)) |
68 | break; |
69 | |
70 | BPF_SEQ_PRINTF(seq, "%c" , |
71 | unix_sk->addr->name->sun_path[i] ?: |
72 | '@'); |
73 | } |
74 | } |
75 | } |
76 | |
77 | BPF_SEQ_PRINTF(seq, "\n" ); |
78 | |
79 | return 0; |
80 | } |
81 | |