summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Ahern <dsa@cumulusnetworks.com>2016-06-23 18:42:51 -0700
committerBen Fennema <fennema@google.com>2017-01-17 15:30:02 -0800
commit8dba8544f680b049e063747eddd005eefa87e360 (patch)
tree43ca4aa40d6f72e1622f11e2d61b69001cb2ad70
parent4aa8c49b16abc55dc1d7118a2ef96f806d127f14 (diff)
downloadmediatek-8dba8544f680b049e063747eddd005eefa87e360.tar.gz
net: diag: Add support to filter on device index
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. [backport of net-next 637c841dd7a5f9bd97b75cbe90b526fa1a52e530] Change-Id: Ib430cfb44f1b3b1a771a561247ee9140737e52fd Signed-off-by: David Ahern <dsa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/uapi/linux/inet_diag.h1
-rw-r--r--net/ipv4/inet_diag.c25
2 files changed, 26 insertions, 0 deletions
diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h
index bbde90fa5838..43601eaf63ef 100644
--- a/include/uapi/linux/inet_diag.h
+++ b/include/uapi/linux/inet_diag.h
@@ -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 {
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index b7527bfdc6a7..8fd708193e42 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -48,6 +48,7 @@ struct inet_diag_entry {
struct in6_addr saddr_storage; /* for IPv4-mapped-IPv6 addresses */
struct in6_addr daddr_storage; /* for IPv4-mapped-IPv6 addresses */
#endif
+ u32 ifindex;
};
static DEFINE_MUTEX(inet_diag_table_mutex);
@@ -504,6 +505,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) {
@@ -540,6 +549,7 @@ int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
}
entry.sport = inet->inet_num;
entry.dport = ntohs(inet->inet_dport);
+ entry.ifindex = sk->sk_bound_dev_if;
entry.userlocks = sk->sk_userlocks;
return inet_diag_bc_run(bc, &entry);
@@ -563,6 +573,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)
@@ -628,6 +649,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: