diff options
author | Pavel Emelyanov <xemul@parallels.com> | 2011-12-09 01:24:06 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-09 14:15:00 -0500 |
commit | a925aa00a55e3b72bd38bfdd3d6f97c0d900c949 (patch) | |
tree | c3a713175d2fa0ea295bd20143bd9b0d938c2bb5 /net/ipv4 | |
parent | 52b7c59bc34c1eb73c46e023c9c01231e1cb637a (diff) |
udp_diag: Implement the get_exact dumping functionality
Do the same as TCP does -- lookup a socket in the given udp_table,
check cookie, fill the reply message with existing inet socket dumping
helper and send one back.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/udp_diag.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 75e4e4ada545..caa164dcd30f 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c | |||
@@ -21,7 +21,57 @@ | |||
21 | static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, | 21 | static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, |
22 | const struct nlmsghdr *nlh, struct inet_diag_req *req) | 22 | const struct nlmsghdr *nlh, struct inet_diag_req *req) |
23 | { | 23 | { |
24 | return 0; | 24 | int err = -EINVAL; |
25 | struct sock *sk; | ||
26 | struct sk_buff *rep; | ||
27 | |||
28 | if (req->sdiag_family == AF_INET) | ||
29 | sk = __udp4_lib_lookup(&init_net, | ||
30 | req->id.idiag_src[0], req->id.idiag_sport, | ||
31 | req->id.idiag_dst[0], req->id.idiag_dport, | ||
32 | req->id.idiag_if, tbl); | ||
33 | else if (req->sdiag_family == AF_INET6) | ||
34 | sk = __udp6_lib_lookup(&init_net, | ||
35 | (struct in6_addr *)req->id.idiag_src, | ||
36 | req->id.idiag_sport, | ||
37 | (struct in6_addr *)req->id.idiag_dst, | ||
38 | req->id.idiag_dport, | ||
39 | req->id.idiag_if, tbl); | ||
40 | else | ||
41 | goto out_nosk; | ||
42 | |||
43 | err = -ENOENT; | ||
44 | if (sk == NULL) | ||
45 | goto out_nosk; | ||
46 | |||
47 | err = inet_diag_check_cookie(sk, req); | ||
48 | if (err) | ||
49 | goto out; | ||
50 | |||
51 | err = -ENOMEM; | ||
52 | rep = alloc_skb(NLMSG_SPACE((sizeof(struct inet_diag_msg) + | ||
53 | sizeof(struct inet_diag_meminfo) + | ||
54 | 64)), GFP_KERNEL); | ||
55 | if (!rep) | ||
56 | goto out; | ||
57 | |||
58 | err = inet_sk_diag_fill(sk, NULL, rep, req, | ||
59 | NETLINK_CB(in_skb).pid, | ||
60 | nlh->nlmsg_seq, 0, nlh); | ||
61 | if (err < 0) { | ||
62 | WARN_ON(err == -EMSGSIZE); | ||
63 | kfree_skb(rep); | ||
64 | goto out; | ||
65 | } | ||
66 | err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, | ||
67 | MSG_DONTWAIT); | ||
68 | if (err > 0) | ||
69 | err = 0; | ||
70 | out: | ||
71 | if (sk) | ||
72 | sock_put(sk); | ||
73 | out_nosk: | ||
74 | return err; | ||
25 | } | 75 | } |
26 | 76 | ||
27 | static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlink_callback *cb, | 77 | static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlink_callback *cb, |