diff options
| author | Lorenzo Colitti <lorenzo@google.com> | 2015-12-16 12:30:02 +0900 |
|---|---|---|
| committer | Moyster <oysterized@gmail.com> | 2016-09-10 16:51:10 +0200 |
| commit | 6fcea3cc56858aa54811c30b1de1528ac87ef7f1 (patch) | |
| tree | 8d19788e8ab9283e52a5c29c514627860338c5f7 | |
| parent | e9333d2f8d89d0ccc07e9f205db302b04b4faf31 (diff) | |
| download | android_kernel_m2note-6fcea3cc56858aa54811c30b1de1528ac87ef7f1.tar.gz | |
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>
| -rw-r--r-- | include/linux/inet_diag.h | 5 | ||||
| -rw-r--r-- | net/ipv4/inet_diag.c | 46 |
2 files changed, 37 insertions, 14 deletions
diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h index 46da02410..0f3eddff8 100644 --- a/include/linux/inet_diag.h +++ b/include/linux/inet_diag.h @@ -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); diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 14a1ed611..103f3ca53 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -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); |
