aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter/nf_conntrack_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netfilter/nf_conntrack_netlink.c')
-rw-r--r--net/netfilter/nf_conntrack_netlink.c73
1 files changed, 42 insertions, 31 deletions
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 036207ecaf16..4ae8e528943a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -135,8 +135,7 @@ static int ctnetlink_dump_tuples(struct sk_buff *skb,
ret = ctnetlink_dump_tuples_ip(skb, tuple);
if (ret >= 0) {
- l4proto = __nf_ct_l4proto_find(tuple->src.l3num,
- tuple->dst.protonum);
+ l4proto = __nf_ct_l4proto_find(tuple->dst.protonum);
ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto);
}
rcu_read_unlock();
@@ -184,7 +183,7 @@ static int ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct)
struct nlattr *nest_proto;
int ret;
- l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ l4proto = __nf_ct_l4proto_find(nf_ct_protonum(ct));
if (!l4proto->to_nlattr)
return 0;
@@ -592,7 +591,7 @@ static size_t ctnetlink_proto_size(const struct nf_conn *ct)
len = nla_policy_len(cta_ip_nla_policy, CTA_IP_MAX + 1);
len *= 3u; /* ORIG, REPLY, MASTER */
- l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ l4proto = __nf_ct_l4proto_find(nf_ct_protonum(ct));
len += l4proto->nlattr_size;
if (l4proto->nlattr_tuple_size) {
len4 = l4proto->nlattr_tuple_size();
@@ -821,6 +820,7 @@ static int ctnetlink_done(struct netlink_callback *cb)
}
struct ctnetlink_filter {
+ u8 family;
struct {
u_int32_t val;
u_int32_t mask;
@@ -828,31 +828,39 @@ struct ctnetlink_filter {
};
static struct ctnetlink_filter *
-ctnetlink_alloc_filter(const struct nlattr * const cda[])
+ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
{
-#ifdef CONFIG_NF_CONNTRACK_MARK
struct ctnetlink_filter *filter;
+#ifndef CONFIG_NF_CONNTRACK_MARK
+ if (cda[CTA_MARK] && cda[CTA_MARK_MASK])
+ return ERR_PTR(-EOPNOTSUPP);
+#endif
+
filter = kzalloc(sizeof(*filter), GFP_KERNEL);
if (filter == NULL)
return ERR_PTR(-ENOMEM);
- filter->mark.val = ntohl(nla_get_be32(cda[CTA_MARK]));
- filter->mark.mask = ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
+ filter->family = family;
- return filter;
-#else
- return ERR_PTR(-EOPNOTSUPP);
+#ifdef CONFIG_NF_CONNTRACK_MARK
+ if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
+ filter->mark.val = ntohl(nla_get_be32(cda[CTA_MARK]));
+ filter->mark.mask = ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
+ }
#endif
+ return filter;
}
static int ctnetlink_start(struct netlink_callback *cb)
{
const struct nlattr * const *cda = cb->data;
struct ctnetlink_filter *filter = NULL;
+ struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
+ u8 family = nfmsg->nfgen_family;
- if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
- filter = ctnetlink_alloc_filter(cda);
+ if (family || (cda[CTA_MARK] && cda[CTA_MARK_MASK])) {
+ filter = ctnetlink_alloc_filter(cda, family);
if (IS_ERR(filter))
return PTR_ERR(filter);
}
@@ -866,13 +874,24 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
struct ctnetlink_filter *filter = data;
if (filter == NULL)
- return 1;
+ goto out;
+
+ /* Match entries of a given L3 protocol number.
+ * If it is not specified, ie. l3proto == 0,
+ * then match everything.
+ */
+ if (filter->family && nf_ct_l3num(ct) != filter->family)
+ goto ignore_entry;
#ifdef CONFIG_NF_CONNTRACK_MARK
- if ((ct->mark & filter->mark.mask) == filter->mark.val)
- return 1;
+ if ((ct->mark & filter->mark.mask) != filter->mark.val)
+ goto ignore_entry;
#endif
+out:
+ return 1;
+
+ignore_entry:
return 0;
}
@@ -883,8 +902,6 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
struct nf_conn *ct, *last;
struct nf_conntrack_tuple_hash *h;
struct hlist_nulls_node *n;
- struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
- u_int8_t l3proto = nfmsg->nfgen_family;
struct nf_conn *nf_ct_evict[8];
int res, i;
spinlock_t *lockp;
@@ -923,11 +940,6 @@ restart:
if (!net_eq(net, nf_ct_net(ct)))
continue;
- /* Dump entries of a given L3 protocol number.
- * If it is not specified, ie. l3proto == 0,
- * then dump everything. */
- if (l3proto && nf_ct_l3num(ct) != l3proto)
- continue;
if (cb->args[1]) {
if (ct != last)
continue;
@@ -1048,7 +1060,7 @@ static int ctnetlink_parse_tuple_proto(struct nlattr *attr,
tuple->dst.protonum = nla_get_u8(tb[CTA_PROTO_NUM]);
rcu_read_lock();
- l4proto = __nf_ct_l4proto_find(tuple->src.l3num, tuple->dst.protonum);
+ l4proto = __nf_ct_l4proto_find(tuple->dst.protonum);
if (likely(l4proto->nlattr_to_tuple)) {
ret = nla_validate_nested(attr, CTA_PROTO_MAX,
@@ -1213,12 +1225,12 @@ static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data)
static int ctnetlink_flush_conntrack(struct net *net,
const struct nlattr * const cda[],
- u32 portid, int report)
+ u32 portid, int report, u8 family)
{
struct ctnetlink_filter *filter = NULL;
- if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
- filter = ctnetlink_alloc_filter(cda);
+ if (family || (cda[CTA_MARK] && cda[CTA_MARK_MASK])) {
+ filter = ctnetlink_alloc_filter(cda, family);
if (IS_ERR(filter))
return PTR_ERR(filter);
}
@@ -1257,7 +1269,7 @@ static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,
else {
return ctnetlink_flush_conntrack(net, cda,
NETLINK_CB(skb).portid,
- nlmsg_report(nlh));
+ nlmsg_report(nlh), u3);
}
if (err < 0)
@@ -1696,7 +1708,7 @@ static int ctnetlink_change_protoinfo(struct nf_conn *ct,
return err;
rcu_read_lock();
- l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ l4proto = __nf_ct_l4proto_find(nf_ct_protonum(ct));
if (l4proto->from_nlattr)
err = l4proto->from_nlattr(tb, ct);
rcu_read_unlock();
@@ -2656,8 +2668,7 @@ static int ctnetlink_exp_dump_mask(struct sk_buff *skb,
rcu_read_lock();
ret = ctnetlink_dump_tuples_ip(skb, &m);
if (ret >= 0) {
- l4proto = __nf_ct_l4proto_find(tuple->src.l3num,
- tuple->dst.protonum);
+ l4proto = __nf_ct_l4proto_find(tuple->dst.protonum);
ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto);
}
rcu_read_unlock();