net: diag: Add support to filter on device index
authorDavid Ahern <dsa@cumulusnetworks.com>
Fri, 24 Jun 2016 01:42:51 +0000 (18:42 -0700)
committerLorenzo Colitti <lorenzo@google.com>
Sun, 18 Sep 2016 16:51:21 +0000 (01:51 +0900)
Add support to inet_diag facility to filter sockets based on device
index. If an interface index is in the filter only sockets bound
to that index (sk_bound_dev_if) are returned.

[cherry-pick of net-next 637c841dd7a5f9bd97b75cbe90b526fa1a52e530]

Change-Id: I6b6bcdcf15d3142003f1ee53b4d82f2fabbb8250
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/inet_diag.h
net/ipv4/inet_diag.c

index 68a1f71fde9f7bcc90c21f586b57f1eab61de941..b49bfb6ea22a90d760186cb06b579f76d6398ce8 100644 (file)
@@ -72,6 +72,7 @@ enum {
        INET_DIAG_BC_AUTO,
        INET_DIAG_BC_S_COND,
        INET_DIAG_BC_D_COND,
+       INET_DIAG_BC_DEV_COND,   /* u32 ifindex */
 };
 
 struct inet_diag_hostcond {
index a403a676d452d050f4518cec52631aa6823800cf..e532671c3f4f9aded1e03760e6301a6679df8f1a 100644 (file)
@@ -44,6 +44,7 @@ struct inet_diag_entry {
        u16 dport;
        u16 family;
        u16 userlocks;
+       u32 ifindex;
 };
 
 static DEFINE_MUTEX(inet_diag_table_mutex);
@@ -552,6 +553,14 @@ static int inet_diag_bc_run(const struct nlattr *_bc,
                        yes = 0;
                        break;
                }
+               case INET_DIAG_BC_DEV_COND: {
+                       u32 ifindex;
+
+                       ifindex = *((const u32 *)(op + 1));
+                       if (ifindex != entry->ifindex)
+                               yes = 0;
+                       break;
+               }
                }
 
                if (yes) {
@@ -594,6 +603,7 @@ int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
        entry_fill_addrs(&entry, sk);
        entry.sport = inet->inet_num;
        entry.dport = ntohs(inet->inet_dport);
+       entry.ifindex = sk->sk_bound_dev_if;
        entry.userlocks = sk_fullsock(sk) ? sk->sk_userlocks : 0;
 
        return inet_diag_bc_run(bc, &entry);
@@ -617,6 +627,17 @@ static int valid_cc(const void *bc, int len, int cc)
        return 0;
 }
 
+/* data is u32 ifindex */
+static bool valid_devcond(const struct inet_diag_bc_op *op, int len,
+                         int *min_len)
+{
+       /* Check ifindex space. */
+       *min_len += sizeof(u32);
+       if (len < *min_len)
+               return false;
+
+       return true;
+}
 /* Validate an inet_diag_hostcond. */
 static bool valid_hostcond(const struct inet_diag_bc_op *op, int len,
                           int *min_len)
@@ -681,6 +702,10 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
                        if (!valid_hostcond(bc, len, &min_len))
                                return -EINVAL;
                        break;
+               case INET_DIAG_BC_DEV_COND:
+                       if (!valid_devcond(bc, len, &min_len))
+                               return -EINVAL;
+                       break;
                case INET_DIAG_BC_S_GE:
                case INET_DIAG_BC_S_LE:
                case INET_DIAG_BC_D_GE: