inet_diag: Introduce socket family checks
authorPavel Emelyanov <xemul@parallels.com>
Tue, 6 Dec 2011 07:59:15 +0000 (07:59 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 6 Dec 2011 18:58:02 +0000 (13:58 -0500)
The new API will specify family to work with. Teach the existing
socket walking code to bypass not interesting ones.

To preserve compatibility with existing behavior the _compat code
sets interesting family to AF_UNSPEC to dump them all.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/inet_diag.c

index 57a1bd97ea35e69264cf120ab499b5163061666d..2642f317af8f655ea03b99b1b6a10471b3adbfa6 100644 (file)
@@ -743,6 +743,10 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
                                        continue;
                                }
 
+                               if (r->sdiag_family != AF_UNSPEC &&
+                                               sk->sk_family != r->sdiag_family)
+                                       goto next_listen;
+
                                if (r->id.idiag_sport != inet->inet_sport &&
                                    r->id.idiag_sport)
                                        goto next_listen;
@@ -808,6 +812,9 @@ skip_listen_ht:
                                goto next_normal;
                        if (!(r->idiag_states & (1 << sk->sk_state)))
                                goto next_normal;
+                       if (r->sdiag_family != AF_UNSPEC &&
+                                       sk->sk_family != r->sdiag_family)
+                               goto next_normal;
                        if (r->id.idiag_sport != inet->inet_sport &&
                            r->id.idiag_sport)
                                goto next_normal;
@@ -830,6 +837,9 @@ next_normal:
 
                                if (num < s_num)
                                        goto next_dying;
+                               if (r->sdiag_family != AF_UNSPEC &&
+                                               tw->tw_family != r->sdiag_family)
+                                       goto next_dying;
                                if (r->id.idiag_sport != tw->tw_sport &&
                                    r->id.idiag_sport)
                                        goto next_dying;
@@ -873,7 +883,7 @@ static int inet_diag_dump_compat(struct sk_buff *skb, struct netlink_callback *c
        struct nlattr *bc = NULL;
        int hdrlen = sizeof(struct inet_diag_req_compat);
 
-       req.sdiag_family = rc->idiag_family;
+       req.sdiag_family = AF_UNSPEC; /* compatibility */
        req.sdiag_protocol = inet_diag_type2proto(cb->nlh->nlmsg_type);
        req.idiag_ext = rc->idiag_ext;
        req.idiag_states = rc->idiag_states;