aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/udp_diag.c
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@parallels.com>2011-12-09 01:24:21 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-09 14:15:00 -0500
commitb6d640c2286d16b15a21a4475c896cdce6a0bbe0 (patch)
tree01f55007bfb8c680a4689d6e6f312f22f28adec3 /net/ipv4/udp_diag.c
parenta925aa00a55e3b72bd38bfdd3d6f97c0d900c949 (diff)
udp_diag: Implement the dump-all functionality
Do the same as TCP does -- iterate the given udp_table, filter sockets with bytecode and dump sockets into reply message. The same filtering as for TCP applies, though only some of the state bits really matter. Signed-off-by: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/udp_diag.c')
-rw-r--r--net/ipv4/udp_diag.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index caa164dcd30f..65063444a119 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -18,6 +18,17 @@
18#include <linux/inet_diag.h> 18#include <linux/inet_diag.h>
19#include <linux/sock_diag.h> 19#include <linux/sock_diag.h>
20 20
21static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
22 struct netlink_callback *cb, struct inet_diag_req *req,
23 struct nlattr *bc)
24{
25 if (!inet_diag_bc_sk(bc, sk))
26 return 0;
27
28 return inet_sk_diag_fill(sk, NULL, skb, req, NETLINK_CB(cb->skb).pid,
29 cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
30}
31
21static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, 32static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
22 const struct nlmsghdr *nlh, struct inet_diag_req *req) 33 const struct nlmsghdr *nlh, struct inet_diag_req *req)
23{ 34{
@@ -77,6 +88,49 @@ out_nosk:
77static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlink_callback *cb, 88static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlink_callback *cb,
78 struct inet_diag_req *r, struct nlattr *bc) 89 struct inet_diag_req *r, struct nlattr *bc)
79{ 90{
91 int num, s_num, slot, s_slot;
92
93 s_slot = cb->args[0];
94 num = s_num = cb->args[1];
95
96 for (slot = s_slot; slot <= table->mask; num = s_num = 0, slot++) {
97 struct sock *sk;
98 struct hlist_nulls_node *node;
99 struct udp_hslot *hslot = &table->hash[slot];
100
101 if (hlist_nulls_empty(&hslot->head))
102 continue;
103
104 spin_lock_bh(&hslot->lock);
105 sk_nulls_for_each(sk, node, &hslot->head) {
106 struct inet_sock *inet = inet_sk(sk);
107
108 if (num < s_num)
109 goto next;
110 if (!(r->idiag_states & (1 << sk->sk_state)))
111 goto next;
112 if (r->sdiag_family != AF_UNSPEC &&
113 sk->sk_family != r->sdiag_family)
114 goto next;
115 if (r->id.idiag_sport != inet->inet_sport &&
116 r->id.idiag_sport)
117 goto next;
118 if (r->id.idiag_dport != inet->inet_dport &&
119 r->id.idiag_dport)
120 goto next;
121
122 if (sk_diag_dump(sk, skb, cb, r, bc) < 0) {
123 spin_unlock_bh(&hslot->lock);
124 goto done;
125 }
126next:
127 num++;
128 }
129 spin_unlock_bh(&hslot->lock);
130 }
131done:
132 cb->args[0] = slot;
133 cb->args[1] = num;
80} 134}
81 135
82static void udp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, 136static void udp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,