net: diag: split inet_diag_dump_one_icsk into two

Currently, inet_diag_dump_one_icsk finds a socket and then dumps
its information to userspace. Split it into a part that finds the
socket and a part that dumps the information.

[Backport of net-next b613f56ec9baf30edf5d9d607b822532a273dad7]

Change-Id: I7aec27aca9c3e395e41332fe4e59d720042e0609
Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Lorenzo Colitti 2015-12-16 12:30:02 +09:00 committed by Srinivasarao P
parent ba88acf8c2
commit 70718dc2f7
2 changed files with 37 additions and 14 deletions

View File

@ -3,6 +3,7 @@
#include <uapi/linux/inet_diag.h>
struct net;
struct sock;
struct inet_hashinfo;
struct nlattr;
@ -39,6 +40,10 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo,
struct sk_buff *in_skb, const struct nlmsghdr *nlh,
struct inet_diag_req_v2 *req);
struct sock *inet_diag_find_one_icsk(struct net *net,
struct inet_hashinfo *hashinfo,
struct inet_diag_req_v2 *req);
int inet_diag_bc_sk(const struct nlattr *_bc, struct sock *sk);
extern int inet_diag_register(const struct inet_diag_handler *handler);

View File

@ -304,15 +304,12 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq, nlmsg_flags, unlh);
}
int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb,
const struct nlmsghdr *nlh, struct inet_diag_req_v2 *req)
struct sock *inet_diag_find_one_icsk(struct net *net,
struct inet_hashinfo *hashinfo,
struct inet_diag_req_v2 *req)
{
int err;
struct sock *sk;
struct sk_buff *rep;
struct net *net = sock_net(in_skb->sk);
err = -EINVAL;
if (req->sdiag_family == AF_INET) {
sk = inet_lookup(net, hashinfo, req->id.idiag_dst[0],
req->id.idiag_dport, req->id.idiag_src[0],
@ -329,16 +326,38 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s
}
#endif
else {
goto out_nosk;
return ERR_PTR(-EINVAL);
}
err = -ENOENT;
if (sk == NULL)
goto out_nosk;
if (!sk)
return ERR_PTR(-ENOENT);
err = sock_diag_check_cookie(sk, req->id.idiag_cookie);
if (err)
goto out;
if (sock_diag_check_cookie(sk, req->id.idiag_cookie)) {
/* NOTE: forward-ports should use sock_gen_put(sk) instead. */
if (sk->sk_state == TCP_TIME_WAIT)
inet_twsk_put((struct inet_timewait_sock *)sk);
else
sock_put(sk);
return ERR_PTR(-ENOENT);
}
return sk;
}
EXPORT_SYMBOL_GPL(inet_diag_find_one_icsk);
int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo,
struct sk_buff *in_skb,
const struct nlmsghdr *nlh,
struct inet_diag_req_v2 *req)
{
struct net *net = sock_net(in_skb->sk);
struct sk_buff *rep;
struct sock *sk;
int err;
sk = inet_diag_find_one_icsk(net, hashinfo, req);
if (IS_ERR(sk))
return PTR_ERR(sk);
rep = nlmsg_new(inet_sk_attr_size(), GFP_KERNEL);
if (!rep) {
@ -367,7 +386,6 @@ out:
else
sock_put(sk);
}
out_nosk:
return err;
}
EXPORT_SYMBOL_GPL(inet_diag_dump_one_icsk);