2 * vsock sock_diag(7) module
4 * Copyright (C) 2017 Red Hat, Inc.
5 * Author: Stefan Hajnoczi <stefanha@redhat.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation version 2 and no later version.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 #include <linux/module.h>
18 #include <linux/sock_diag.h>
19 #include <linux/vm_sockets_diag.h>
20 #include <net/af_vsock.h>
22 static int sk_diag_fill(struct sock
*sk
, struct sk_buff
*skb
,
23 u32 portid
, u32 seq
, u32 flags
)
25 struct vsock_sock
*vsk
= vsock_sk(sk
);
26 struct vsock_diag_msg
*rep
;
29 nlh
= nlmsg_put(skb
, portid
, seq
, SOCK_DIAG_BY_FAMILY
, sizeof(*rep
),
34 rep
= nlmsg_data(nlh
);
35 rep
->vdiag_family
= AF_VSOCK
;
37 /* Lock order dictates that sk_lock is acquired before
38 * vsock_table_lock, so we cannot lock here. Simply don't take
39 * sk_lock; sk is guaranteed to stay alive since vsock_table_lock is
42 rep
->vdiag_type
= sk
->sk_type
;
43 rep
->vdiag_state
= sk
->sk_state
;
44 rep
->vdiag_shutdown
= sk
->sk_shutdown
;
45 rep
->vdiag_src_cid
= vsk
->local_addr
.svm_cid
;
46 rep
->vdiag_src_port
= vsk
->local_addr
.svm_port
;
47 rep
->vdiag_dst_cid
= vsk
->remote_addr
.svm_cid
;
48 rep
->vdiag_dst_port
= vsk
->remote_addr
.svm_port
;
49 rep
->vdiag_ino
= sock_i_ino(sk
);
51 sock_diag_save_cookie(sk
, rep
->vdiag_cookie
);
56 static int vsock_diag_dump(struct sk_buff
*skb
, struct netlink_callback
*cb
)
58 struct vsock_diag_req
*req
;
59 struct vsock_sock
*vsk
;
66 req
= nlmsg_data(cb
->nlh
);
67 net
= sock_net(skb
->sk
);
69 /* State saved between calls: */
72 i
= last_i
= cb
->args
[2];
74 /* TODO VMCI pending sockets? */
76 spin_lock_bh(&vsock_table_lock
);
78 /* Bind table (locally created sockets) */
80 while (bucket
< ARRAY_SIZE(vsock_bind_table
)) {
81 struct list_head
*head
= &vsock_bind_table
[bucket
];
84 list_for_each_entry(vsk
, head
, bound_table
) {
85 struct sock
*sk
= sk_vsock(vsk
);
87 if (!net_eq(sock_net(sk
), net
))
91 if (!(req
->vdiag_states
& (1 << sk
->sk_state
)))
93 if (sk_diag_fill(sk
, skb
,
94 NETLINK_CB(cb
->skb
).portid
,
109 /* Connected table (accepted connections) */
110 while (bucket
< ARRAY_SIZE(vsock_connected_table
)) {
111 struct list_head
*head
= &vsock_connected_table
[bucket
];
114 list_for_each_entry(vsk
, head
, connected_table
) {
115 struct sock
*sk
= sk_vsock(vsk
);
117 /* Skip sockets we've already seen above */
118 if (__vsock_in_bound_table(vsk
))
121 if (!net_eq(sock_net(sk
), net
))
125 if (!(req
->vdiag_states
& (1 << sk
->sk_state
)))
127 if (sk_diag_fill(sk
, skb
,
128 NETLINK_CB(cb
->skb
).portid
,
140 spin_unlock_bh(&vsock_table_lock
);
143 cb
->args
[1] = bucket
;
149 static int vsock_diag_handler_dump(struct sk_buff
*skb
, struct nlmsghdr
*h
)
151 int hdrlen
= sizeof(struct vsock_diag_req
);
152 struct net
*net
= sock_net(skb
->sk
);
154 if (nlmsg_len(h
) < hdrlen
)
157 if (h
->nlmsg_flags
& NLM_F_DUMP
) {
158 struct netlink_dump_control c
= {
159 .dump
= vsock_diag_dump
,
161 return netlink_dump_start(net
->diag_nlsk
, skb
, h
, &c
);
167 static const struct sock_diag_handler vsock_diag_handler
= {
169 .dump
= vsock_diag_handler_dump
,
172 static int __init
vsock_diag_init(void)
174 return sock_diag_register(&vsock_diag_handler
);
177 static void __exit
vsock_diag_exit(void)
179 sock_diag_unregister(&vsock_diag_handler
);
182 module_init(vsock_diag_init
);
183 module_exit(vsock_diag_exit
);
184 MODULE_LICENSE("GPL");
185 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK
, NETLINK_SOCK_DIAG
,