/*
 * vsock sock_diag(7) module
 *
 * Copyright (C) 2017 Red Hat, Inc.
 * Author: Stefan Hajnoczi <stefanha@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation version 2 and no later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 */

#include <linux/module.h>
#include <linux/sock_diag.h>
#include <linux/vm_sockets_diag.h>
#include <net/af_vsock.h>

static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
			u32 portid, u32 seq, u32 flags)
{
	struct vsock_sock *vsk = vsock_sk(sk);
	struct vsock_diag_msg *rep;
	struct nlmsghdr *nlh;

	nlh = nlmsg_put(skb, portid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep),
			flags);
	if (!nlh)
		return -EMSGSIZE;

	rep = nlmsg_data(nlh);
	rep->vdiag_family = AF_VSOCK;

	/* Lock order dictates that sk_lock is acquired before
	 * vsock_table_lock, so we cannot lock here.  Simply don't take
	 * sk_lock; sk is guaranteed to stay alive since vsock_table_lock is
	 * held.
	 */
	rep->vdiag_type = sk->sk_type;
	rep->vdiag_state = sk->sk_state;
	rep->vdiag_shutdown = sk->sk_shutdown;
	rep->vdiag_src_cid = vsk->local_addr.svm_cid;
	rep->vdiag_src_port = vsk->local_addr.svm_port;
	rep->vdiag_dst_cid = vsk->remote_addr.svm_cid;
	rep->vdiag_dst_port = vsk->remote_addr.svm_port;
	rep->vdiag_ino = sock_i_ino(sk);

	sock_diag_save_cookie(sk, rep->vdiag_cookie);

	return 0;
}

static int vsock_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct vsock_diag_req *req;
	struct vsock_sock *vsk;
	unsigned int bucket;
	unsigned int last_i;
	unsigned int table;
	struct net *net;
	unsigned int i;

	req = nlmsg_data(cb->nlh);
	net = sock_net(skb->sk);

	/* State saved between calls: */
	table = cb->args[0];
	bucket = cb->args[1];
	i = last_i = cb->args[2];

	/* TODO VMCI pending sockets? */

	spin_lock_bh(&vsock_table_lock);

	/* Bind table (locally created sockets) */
	if (table == 0) {
		while (bucket < ARRAY_SIZE(vsock_bind_table)) {
			struct list_head *head = &vsock_bind_table[bucket];

			i = 0;
			list_for_each_entry(vsk, head, bound_table) {
				struct sock *sk = sk_vsock(vsk);

				if (!net_eq(sock_net(sk), net))
					continue;
				if (i < last_i)
					goto next_bind;
				if (!(req->vdiag_states & (1 << sk->sk_state)))
					goto next_bind;
				if (sk_diag_fill(sk, skb,
						 NETLINK_CB(cb->skb).portid,
						 cb->nlh->nlmsg_seq,
						 NLM_F_MULTI) < 0)
					goto done;
next_bind:
				i++;
			}
			last_i = 0;
			bucket++;
		}

		table++;
		bucket = 0;
	}

	/* Connected table (accepted connections) */
	while (bucket < ARRAY_SIZE(vsock_connected_table)) {
		struct list_head *head = &vsock_connected_table[bucket];

		i = 0;
		list_for_each_entry(vsk, head, connected_table) {
			struct sock *sk = sk_vsock(vsk);

			/* Skip sockets we've already seen above */
			if (__vsock_in_bound_table(vsk))
				continue;

			if (!net_eq(sock_net(sk), net))
				continue;
			if (i < last_i)
				goto next_connected;
			if (!(req->vdiag_states & (1 << sk->sk_state)))
				goto next_connected;
			if (sk_diag_fill(sk, skb,
					 NETLINK_CB(cb->skb).portid,
					 cb->nlh->nlmsg_seq,
					 NLM_F_MULTI) < 0)
				goto done;
next_connected:
			i++;
		}
		last_i = 0;
		bucket++;
	}

done:
	spin_unlock_bh(&vsock_table_lock);

	cb->args[0] = table;
	cb->args[1] = bucket;
	cb->args[2] = i;

	return skb->len;
}

static int vsock_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
{
	int hdrlen = sizeof(struct vsock_diag_req);
	struct net *net = sock_net(skb->sk);

	if (nlmsg_len(h) < hdrlen)
		return -EINVAL;

	if (h->nlmsg_flags & NLM_F_DUMP) {
		struct netlink_dump_control c = {
			.dump = vsock_diag_dump,
		};
		return netlink_dump_start(net->diag_nlsk, skb, h, &c);
	}

	return -EOPNOTSUPP;
}

static const struct sock_diag_handler vsock_diag_handler = {
	.family = AF_VSOCK,
	.dump = vsock_diag_handler_dump,
};

static int __init vsock_diag_init(void)
{
	return sock_diag_register(&vsock_diag_handler);
}

static void __exit vsock_diag_exit(void)
{
	sock_diag_unregister(&vsock_diag_handler);
}

module_init(vsock_diag_init);
module_exit(vsock_diag_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG,
			       40 /* AF_VSOCK */);
