diff mbox

[11/13] udp_diag: Implement the get_exact dumping functionality

Message ID 4EE23626.6000104@parallels.com
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Pavel Emelyanov Dec. 9, 2011, 4:24 p.m. UTC
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>

---
 net/ipv4/udp_diag.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 51 insertions(+), 1 deletions(-)

Comments

Eric Dumazet Dec. 9, 2011, 9:48 p.m. UTC | #1
Le vendredi 09 décembre 2011 à 20:24 +0400, Pavel Emelyanov a écrit :
> 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>

> +
> +	if (req->sdiag_family == AF_INET)
> +		sk = __udp4_lib_lookup(&init_net,
> +				req->id.idiag_src[0], req->id.idiag_sport,
> +				req->id.idiag_dst[0], req->id.idiag_dport,
> +				req->id.idiag_if, tbl);
> +	else if (req->sdiag_family == AF_INET6)
> +		sk = __udp6_lib_lookup(&init_net,
> +				(struct in6_addr *)req->id.idiag_src,
> +				req->id.idiag_sport,
> +				(struct in6_addr *)req->id.idiag_dst,
> +				req->id.idiag_dport,
> +				req->id.idiag_if, tbl);
> +	else

OK, but what happens if IPv6 is a module ?

  LD      .tmp_vmlinux1
net/built-in.o: In function `udp_dump_one':
udp_diag.c:(.text+0xa2b40): undefined reference to `__udp6_lib_lookup'
make: *** [.tmp_vmlinux1] Erreur 1


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pavel Emelyanov Dec. 10, 2011, 9:07 a.m. UTC | #2
On 12/10/2011 01:48 AM, Eric Dumazet wrote:
> Le vendredi 09 décembre 2011 à 20:24 +0400, Pavel Emelyanov a écrit :
>> 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>
> 
>> +
>> +	if (req->sdiag_family == AF_INET)
>> +		sk = __udp4_lib_lookup(&init_net,
>> +				req->id.idiag_src[0], req->id.idiag_sport,
>> +				req->id.idiag_dst[0], req->id.idiag_dport,
>> +				req->id.idiag_if, tbl);
>> +	else if (req->sdiag_family == AF_INET6)
>> +		sk = __udp6_lib_lookup(&init_net,
>> +				(struct in6_addr *)req->id.idiag_src,
>> +				req->id.idiag_sport,
>> +				(struct in6_addr *)req->id.idiag_dst,
>> +				req->id.idiag_dport,
>> +				req->id.idiag_if, tbl);
>> +	else
> 
> OK, but what happens if IPv6 is a module ?

And the udp_diag is built-in, right?

>   LD      .tmp_vmlinux1
> net/built-in.o: In function `udp_dump_one':
> udp_diag.c:(.text+0xa2b40): undefined reference to `__udp6_lib_lookup'
> make: *** [.tmp_vmlinux1] Erreur 1

Crap :( I suppose the Kconfig rule should be fixed, I will try to provide a fix...

Thanks,
Pavel
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index 15936a3..3938aef 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -21,7 +21,57 @@ 
 static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
 		const struct nlmsghdr *nlh, struct inet_diag_req *req)
 {
-	return 0;
+	int err = -EINVAL;
+	struct sock *sk;
+	struct sk_buff *rep;
+
+	if (req->sdiag_family == AF_INET)
+		sk = __udp4_lib_lookup(&init_net,
+				req->id.idiag_src[0], req->id.idiag_sport,
+				req->id.idiag_dst[0], req->id.idiag_dport,
+				req->id.idiag_if, tbl);
+	else if (req->sdiag_family == AF_INET6)
+		sk = __udp6_lib_lookup(&init_net,
+				(struct in6_addr *)req->id.idiag_src,
+				req->id.idiag_sport,
+				(struct in6_addr *)req->id.idiag_dst,
+				req->id.idiag_dport,
+				req->id.idiag_if, tbl);
+	else
+		goto out_nosk;
+
+	err = -ENOENT;
+	if (sk == NULL)
+		goto out_nosk;
+
+	err = inet_diag_check_cookie(sk, req);
+	if (err)
+		goto out;
+
+	err = -ENOMEM;
+	rep = alloc_skb(NLMSG_SPACE((sizeof(struct inet_diag_msg) +
+				     sizeof(struct inet_diag_meminfo) +
+				     64)), GFP_KERNEL);
+	if (!rep)
+		goto out;
+
+	err = inet_sk_diag_fill(sk, NULL, rep, req,
+			   NETLINK_CB(in_skb).pid,
+			   nlh->nlmsg_seq, 0, nlh);
+	if (err < 0) {
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(rep);
+		goto out;
+	}
+	err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
+			      MSG_DONTWAIT);
+	if (err > 0)
+		err = 0;
+out:
+	if (sk)
+		sock_put(sk);
+out_nosk:
+	return err;
 }
 
 static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlink_callback *cb,