diff options
author | Pavel Emelyanov <xemul@parallels.com> | 2011-12-14 21:44:52 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-16 13:48:28 -0500 |
commit | 45a96b9be6ec1b7d248642d17ceee59ff5f64451 (patch) | |
tree | 9623dc58bd01b23a70b3ef261e69b533b717ec46 /net/unix/diag.c | |
parent | 22931d3b906cd0a1726a49a09713f9220a5fab8a (diff) |
unix_diag: Dumping all sockets core
Walk the unix sockets table and fill the core response structure,
which includes type, state and inode.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/unix/diag.c')
-rw-r--r-- | net/unix/diag.c | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/net/unix/diag.c b/net/unix/diag.c index 6be16c0ad38f..86d85abf90c6 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c | |||
@@ -10,9 +10,83 @@ | |||
10 | #define UNIX_DIAG_PUT(skb, attrtype, attrlen) \ | 10 | #define UNIX_DIAG_PUT(skb, attrtype, attrlen) \ |
11 | RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) | 11 | RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) |
12 | 12 | ||
13 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req, | ||
14 | u32 pid, u32 seq, u32 flags, int sk_ino) | ||
15 | { | ||
16 | unsigned char *b = skb_tail_pointer(skb); | ||
17 | struct nlmsghdr *nlh; | ||
18 | struct unix_diag_msg *rep; | ||
19 | |||
20 | nlh = NLMSG_PUT(skb, pid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep)); | ||
21 | nlh->nlmsg_flags = flags; | ||
22 | |||
23 | rep = NLMSG_DATA(nlh); | ||
24 | |||
25 | rep->udiag_family = AF_UNIX; | ||
26 | rep->udiag_type = sk->sk_type; | ||
27 | rep->udiag_state = sk->sk_state; | ||
28 | rep->udiag_ino = sk_ino; | ||
29 | sock_diag_save_cookie(sk, rep->udiag_cookie); | ||
30 | |||
31 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; | ||
32 | return skb->len; | ||
33 | |||
34 | nlmsg_failure: | ||
35 | nlmsg_trim(skb, b); | ||
36 | return -EMSGSIZE; | ||
37 | } | ||
38 | |||
39 | static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req, | ||
40 | u32 pid, u32 seq, u32 flags) | ||
41 | { | ||
42 | int sk_ino; | ||
43 | |||
44 | unix_state_lock(sk); | ||
45 | sk_ino = sock_i_ino(sk); | ||
46 | unix_state_unlock(sk); | ||
47 | |||
48 | if (!sk_ino) | ||
49 | return 0; | ||
50 | |||
51 | return sk_diag_fill(sk, skb, req, pid, seq, flags, sk_ino); | ||
52 | } | ||
53 | |||
13 | static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | 54 | static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) |
14 | { | 55 | { |
15 | return 0; | 56 | struct unix_diag_req *req; |
57 | int num, s_num, slot, s_slot; | ||
58 | |||
59 | req = NLMSG_DATA(cb->nlh); | ||
60 | |||
61 | s_slot = cb->args[0]; | ||
62 | num = s_num = cb->args[1]; | ||
63 | |||
64 | spin_lock(&unix_table_lock); | ||
65 | for (slot = s_slot; slot <= UNIX_HASH_SIZE; s_num = 0, slot++) { | ||
66 | struct sock *sk; | ||
67 | struct hlist_node *node; | ||
68 | |||
69 | num = 0; | ||
70 | sk_for_each(sk, node, &unix_socket_table[slot]) { | ||
71 | if (num < s_num) | ||
72 | goto next; | ||
73 | if (!(req->udiag_states & (1 << sk->sk_state))) | ||
74 | goto next; | ||
75 | if (sk_diag_dump(sk, skb, req, | ||
76 | NETLINK_CB(cb->skb).pid, | ||
77 | cb->nlh->nlmsg_seq, | ||
78 | NLM_F_MULTI) < 0) | ||
79 | goto done; | ||
80 | next: | ||
81 | num++; | ||
82 | } | ||
83 | } | ||
84 | done: | ||
85 | spin_unlock(&unix_table_lock); | ||
86 | cb->args[0] = slot; | ||
87 | cb->args[1] = num; | ||
88 | |||
89 | return skb->len; | ||
16 | } | 90 | } |
17 | 91 | ||
18 | static int unix_diag_get_exact(struct sk_buff *in_skb, | 92 | static int unix_diag_get_exact(struct sk_buff *in_skb, |