17c128a6bSYonghong Song // SPDX-License-Identifier: GPL-2.0
27c128a6bSYonghong Song /* Copyright (c) 2020 Facebook */
384544f56SYonghong Song #include "bpf_iter.h"
4647b502eSYonghong Song #include "bpf_tracing_net.h"
57c128a6bSYonghong Song #include <bpf/bpf_helpers.h>
67c128a6bSYonghong Song 
77c128a6bSYonghong Song char _license[] SEC("license") = "GPL";
87c128a6bSYonghong Song 
SOCK_INODE(struct socket * socket)99c82a63cSAndrii Nakryiko static __attribute__((noinline)) struct inode *SOCK_INODE(struct socket *socket)
107c128a6bSYonghong Song {
117c128a6bSYonghong Song 	return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
127c128a6bSYonghong Song }
137c128a6bSYonghong Song 
147c128a6bSYonghong Song SEC("iter/netlink")
dump_netlink(struct bpf_iter__netlink * ctx)157c128a6bSYonghong Song int dump_netlink(struct bpf_iter__netlink *ctx)
167c128a6bSYonghong Song {
177c128a6bSYonghong Song 	struct seq_file *seq = ctx->meta->seq;
187c128a6bSYonghong Song 	struct netlink_sock *nlk = ctx->sk;
197c128a6bSYonghong Song 	unsigned long group, ino;
207c128a6bSYonghong Song 	struct inode *inode;
217c128a6bSYonghong Song 	struct socket *sk;
227c128a6bSYonghong Song 	struct sock *s;
237c128a6bSYonghong Song 
247c128a6bSYonghong Song 	if (nlk == (void *)0)
257c128a6bSYonghong Song 		return 0;
267c128a6bSYonghong Song 
277c128a6bSYonghong Song 	if (ctx->meta->seq_num == 0)
287c128a6bSYonghong Song 		BPF_SEQ_PRINTF(seq, "sk               Eth Pid        Groups   "
297c128a6bSYonghong Song 				    "Rmem     Wmem     Dump  Locks    Drops    "
307c128a6bSYonghong Song 				    "Inode\n");
317c128a6bSYonghong Song 
327c128a6bSYonghong Song 	s = &nlk->sk;
337c128a6bSYonghong Song 	BPF_SEQ_PRINTF(seq, "%pK %-3d ", s, s->sk_protocol);
347c128a6bSYonghong Song 
357c128a6bSYonghong Song 	if (!nlk->groups)  {
367c128a6bSYonghong Song 		group = 0;
377c128a6bSYonghong Song 	} else {
38e4d9c232SIlya Leoshkevich 		/* FIXME: temporary use bpf_probe_read_kernel here, needs
397c128a6bSYonghong Song 		 * verifier support to do direct access.
407c128a6bSYonghong Song 		 */
41e4d9c232SIlya Leoshkevich 		bpf_probe_read_kernel(&group, sizeof(group), &nlk->groups[0]);
427c128a6bSYonghong Song 	}
437c128a6bSYonghong Song 	BPF_SEQ_PRINTF(seq, "%-10u %08x %-8d %-8d %-5d %-8d ",
447c128a6bSYonghong Song 		       nlk->portid, (u32)group,
457c128a6bSYonghong Song 		       s->sk_rmem_alloc.counter,
467c128a6bSYonghong Song 		       s->sk_wmem_alloc.refs.counter - 1,
477c128a6bSYonghong Song 		       nlk->cb_running, s->sk_refcnt.refs.counter);
487c128a6bSYonghong Song 
497c128a6bSYonghong Song 	sk = s->sk_socket;
507c128a6bSYonghong Song 	if (!sk) {
517c128a6bSYonghong Song 		ino = 0;
527c128a6bSYonghong Song 	} else {
537c128a6bSYonghong Song 		/* FIXME: container_of inside SOCK_INODE has a forced
547c128a6bSYonghong Song 		 * type conversion, and direct access cannot be used
557c128a6bSYonghong Song 		 * with current verifier.
567c128a6bSYonghong Song 		 */
577c128a6bSYonghong Song 		inode = SOCK_INODE(sk);
58e4d9c232SIlya Leoshkevich 		bpf_probe_read_kernel(&ino, sizeof(ino), &inode->i_ino);
597c128a6bSYonghong Song 	}
607c128a6bSYonghong Song 	BPF_SEQ_PRINTF(seq, "%-8u %-8lu\n", s->sk_drops.counter, ino);
617c128a6bSYonghong Song 
627c128a6bSYonghong Song 	return 0;
637c128a6bSYonghong Song }
64