* [PATCH v2 0/2] conntrack: Support flushing connections with given mark
@ 2014-12-24 8:57 Kristian Evensen
2014-12-24 8:57 ` [PATCH v2 1/2] conntrack: Flush connections with a " Kristian Evensen
2014-12-24 8:57 ` [PATCH v2 2/2] conntrack: Remove nf_ct_conntrack_flush_report Kristian Evensen
0 siblings, 2 replies; 8+ messages in thread
From: Kristian Evensen @ 2014-12-24 8:57 UTC (permalink / raw)
To: netfilter-devel; +Cc: Kristian Evensen
This patch adds support for selective flushing of conntrack mappings. By adding
CTA_MARK and CTA_MARK_MASK to a delete-message, the mark is checked before a
connection is deleted while flushing.
One use-case for this feature is on multihomed systems using policy routing
(based on marks). If say for example the next-hop's internet connection goes
down, it is desirable to be able to "reset" all connections using that
interface. However, since the device might be communicating with other devices
on the local network, it is not desitable to set the interface as down.
An iptables-rules can then be used to match not NEW connections without a mark.
generating for example a TCP RST.
v1->v2:
* Fix typo in commit.
* Reduce ifdef pollution by moving filter check to a separate function, used in
both dump and flush path.
* Consolidate code for setting up flush in a separate function, remove use of
nf_conntrack_flush_report.
Kristian Evensen (2):
conntrack: Flush connections with a given mark
conntrack: Remove nf_ct_conntrack_flush_report
include/net/netfilter/nf_conntrack.h | 2 --
net/netfilter/nf_conntrack_core.c | 6 ----
net/netfilter/nf_conntrack_netlink.c | 57 ++++++++++++++++++++++++++++--------
3 files changed, 45 insertions(+), 20 deletions(-)
--
2.1.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 1/2] conntrack: Flush connections with a given mark
2014-12-24 8:57 [PATCH v2 0/2] conntrack: Support flushing connections with given mark Kristian Evensen
@ 2014-12-24 8:57 ` Kristian Evensen
2015-01-07 18:56 ` Pablo Neira Ayuso
2014-12-24 8:57 ` [PATCH v2 2/2] conntrack: Remove nf_ct_conntrack_flush_report Kristian Evensen
1 sibling, 1 reply; 8+ messages in thread
From: Kristian Evensen @ 2014-12-24 8:57 UTC (permalink / raw)
To: netfilter-devel; +Cc: Kristian Evensen
This patch adds support for selective flushing of conntrack mappings. By adding
CTA_MARK and CTA_MARK_MASK to a delete-message, the mark (and mask) is checked
before a connection is deleted while flushing.
Configuring the flush is moved out of ctnetlink_del_conntrack(), and instead of
calling nf_conntrack_flush_report(), we always call nf_ct_iterate_cleanup().
This enables us to only make one call from the new ctnetlink_flush_conntrack()
and makes it easy to add more filter parameters.
Filtering is done in the ctnetlink_apply_filter()-function, which is also called
from ctnetlink_dump_table(). ctnetlink_dump_filter has been renamed
ctnetlink_filter, to indicated that it is no longer only used when dumping
conntrack entries.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
---
net/netfilter/nf_conntrack_netlink.c | 57 ++++++++++++++++++++++++++++--------
1 file changed, 45 insertions(+), 12 deletions(-)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 1bd9ed9..85046d3 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -749,13 +749,29 @@ static int ctnetlink_done(struct netlink_callback *cb)
return 0;
}
-struct ctnetlink_dump_filter {
+struct ctnetlink_filter {
struct {
u_int32_t val;
u_int32_t mask;
} mark;
};
+static int ctnetlink_apply_filter(struct nf_conn *i, void *data)
+{
+ struct ctnetlink_filter *filter = data;
+
+ if (!filter)
+ return 1;
+
+#ifdef CONFIG_NF_CONNTRACK_MARK
+ if ((filter->mark.val && filter->mark.mask) &&
+ (i->mark & filter->mark.mask) != filter->mark.val)
+ return 0;
+#endif
+
+ return 1;
+}
+
static int
ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
{
@@ -769,7 +785,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
spinlock_t *lockp;
#ifdef CONFIG_NF_CONNTRACK_MARK
- const struct ctnetlink_dump_filter *filter = cb->data;
+ const struct ctnetlink_filter *filter = cb->data;
#endif
last = (struct nf_conn *)cb->args[1];
@@ -799,10 +815,9 @@ restart:
cb->args[1] = 0;
}
#ifdef CONFIG_NF_CONNTRACK_MARK
- if (filter && !((ct->mark & filter->mark.mask) ==
- filter->mark.val)) {
+ if (filter &&
+ !ctnetlink_apply_filter(ct, (void *)filter))
continue;
- }
#endif
rcu_read_lock();
res =
@@ -1001,6 +1016,25 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
.len = NF_CT_LABELS_MAX_SIZE },
};
+static void ctnetlink_flush_conntrack(struct net *net,
+ const struct nlattr * const cda[],
+ u32 portid, int report)
+{
+ struct ctnetlink_filter filter;
+
+ memset(&filter, 0, sizeof(filter));
+
+#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
+
+ nf_ct_iterate_cleanup(net, ctnetlink_apply_filter, &filter,
+ portid, report);
+}
+
static int
ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
const struct nlmsghdr *nlh,
@@ -1024,10 +1058,9 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
else if (cda[CTA_TUPLE_REPLY])
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
else {
- /* Flush the whole table */
- nf_conntrack_flush_report(net,
- NETLINK_CB(skb).portid,
- nlmsg_report(nlh));
+ /* Flush the table */
+ ctnetlink_flush_conntrack(net, cda, NETLINK_CB(skb).portid,
+ nlmsg_report(nlh));
return 0;
}
@@ -1075,13 +1108,13 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
struct netlink_dump_control c = {
.dump = ctnetlink_dump_table,
.done = ctnetlink_done,
+ .data = NULL,
};
#ifdef CONFIG_NF_CONNTRACK_MARK
if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
- struct ctnetlink_dump_filter *filter;
+ struct ctnetlink_filter *filter;
- filter = kzalloc(sizeof(struct ctnetlink_dump_filter),
- GFP_ATOMIC);
+ filter = kzalloc(sizeof(*filter), GFP_ATOMIC);
if (filter == NULL)
return -ENOMEM;
--
2.1.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 2/2] conntrack: Remove nf_ct_conntrack_flush_report
2014-12-24 8:57 [PATCH v2 0/2] conntrack: Support flushing connections with given mark Kristian Evensen
2014-12-24 8:57 ` [PATCH v2 1/2] conntrack: Flush connections with a " Kristian Evensen
@ 2014-12-24 8:57 ` Kristian Evensen
1 sibling, 0 replies; 8+ messages in thread
From: Kristian Evensen @ 2014-12-24 8:57 UTC (permalink / raw)
To: netfilter-devel; +Cc: Kristian Evensen
The only user of nf_ct_conntrack_flush_report() was ctnetlink_del_conntrack().
After adding support for flushing connections with a given mark, this function
is no longer called.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
---
include/net/netfilter/nf_conntrack.h | 2 --
net/netfilter/nf_conntrack_core.c | 6 ------
2 files changed, 8 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index f0daed2..74f271a 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -191,8 +191,6 @@ __nf_conntrack_find(struct net *net, u16 zone,
int nf_conntrack_hash_check_insert(struct nf_conn *ct);
bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report);
-void nf_conntrack_flush_report(struct net *net, u32 portid, int report);
-
bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,
u_int16_t l3num, struct nf_conntrack_tuple *tuple);
bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index a116748..9f31938 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1426,12 +1426,6 @@ void nf_ct_free_hashtable(void *hash, unsigned int size)
}
EXPORT_SYMBOL_GPL(nf_ct_free_hashtable);
-void nf_conntrack_flush_report(struct net *net, u32 portid, int report)
-{
- nf_ct_iterate_cleanup(net, kill_all, NULL, portid, report);
-}
-EXPORT_SYMBOL_GPL(nf_conntrack_flush_report);
-
static int untrack_refs(void)
{
int cnt = 0, cpu;
--
2.1.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/2] conntrack: Flush connections with a given mark
2014-12-24 8:57 ` [PATCH v2 1/2] conntrack: Flush connections with a " Kristian Evensen
@ 2015-01-07 18:56 ` Pablo Neira Ayuso
2015-01-07 20:05 ` Kristian Evensen
2015-01-07 20:16 ` Kristian Evensen
0 siblings, 2 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2015-01-07 18:56 UTC (permalink / raw)
To: Kristian Evensen; +Cc: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 1570 bytes --]
Hi Kristian,
On Wed, Dec 24, 2014 at 09:57:10AM +0100, Kristian Evensen wrote:
> This patch adds support for selective flushing of conntrack mappings. By adding
> CTA_MARK and CTA_MARK_MASK to a delete-message, the mark (and mask) is checked
> before a connection is deleted while flushing.
>
> Configuring the flush is moved out of ctnetlink_del_conntrack(), and instead of
> calling nf_conntrack_flush_report(), we always call nf_ct_iterate_cleanup().
> This enables us to only make one call from the new ctnetlink_flush_conntrack()
> and makes it easy to add more filter parameters.
>
> Filtering is done in the ctnetlink_apply_filter()-function, which is also called
> from ctnetlink_dump_table(). ctnetlink_dump_filter has been renamed
> ctnetlink_filter, to indicated that it is no longer only used when dumping
> conntrack entries.
I'm attaching a revisited version of your patch, main changes are:
1) strict type checking in the dump case (for the ctnetlink_filter
object), instead of relying on the genering void * to keep the
ct_iterate happy. It adds a bit more code but I prefer it like this.
2) Explicitly reject mark filters when marks are not supported. This
changes the previous behaviour, but I think this is good to have so
userspace knows that what it is requesting is not support (instead of
silently ignoring it).
3) add helper function to allocate the filter object, so this always
needs explicit release.
Please, have a look a it and let me know if you're fine with it. I'll
pass it to net-next (upcoming 3.20).
Thanks for your patience.
[-- Attachment #2: 0001-netfilter-conntrack-Flush-connections-with-a-given-m.patch --]
[-- Type: text/x-diff, Size: 5171 bytes --]
>From 2ee5d3941fd06694ddb945e2b96795e8693bfef1 Mon Sep 17 00:00:00 2001
From: Kristian Evensen <kristian.evensen@gmail.com>
Date: Wed, 24 Dec 2014 09:57:10 +0100
Subject: [PATCH] netfilter: conntrack: Flush connections with a given mark
This patch adds support for selective flushing of conntrack mappings.
By adding CTA_MARK and CTA_MARK_MASK to a delete-message, the mark (and
mask) is checked before a connection is deleted while flushing.
Configuring the flush is moved out of ctnetlink_del_conntrack(), and
instead of calling nf_conntrack_flush_report(), we always call
nf_ct_iterate_cleanup(). This enables us to only make one call from the
new ctnetlink_flush_conntrack() and makes it easy to add more filter
parameters.
Filtering is done in the ctnetlink_apply_filter()-function, which is
also called from ctnetlink_dump_table(). ctnetlink_dump_filter has been
renamed ctnetlink_filter, to indicated that it is no longer only used
when dumping conntrack entries.
Moreover, reject mark filters with -EOPNOTSUPP if no ct mark support is
available.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_conntrack_netlink.c | 90 ++++++++++++++++++++++++----------
1 file changed, 65 insertions(+), 25 deletions(-)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 1bd9ed9..5df801a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -749,13 +749,44 @@ static int ctnetlink_done(struct netlink_callback *cb)
return 0;
}
-struct ctnetlink_dump_filter {
+struct ctnetlink_filter {
struct {
u_int32_t val;
u_int32_t mask;
} mark;
};
+static struct ctnetlink_filter *
+ctnetlink_alloc_filter(const struct nlattr * const cda[])
+{
+#ifdef CONFIG_NF_CONNTRACK_MARK
+ struct ctnetlink_filter *filter;
+
+ 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]));
+
+ return filter;
+#endif
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
+static int ctnetlink_filter(struct nf_conn *i, struct ctnetlink_filter *filter)
+{
+ if (filter == NULL)
+ return 0;
+
+#ifdef CONFIG_NF_CONNTRACK_MARK
+ if ((i->mark & filter->mark.mask) == filter->mark.val)
+ return 0;
+#endif
+
+ return 1;
+}
+
static int
ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
{
@@ -768,10 +799,6 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
int res;
spinlock_t *lockp;
-#ifdef CONFIG_NF_CONNTRACK_MARK
- const struct ctnetlink_dump_filter *filter = cb->data;
-#endif
-
last = (struct nf_conn *)cb->args[1];
local_bh_disable();
@@ -798,12 +825,9 @@ restart:
continue;
cb->args[1] = 0;
}
-#ifdef CONFIG_NF_CONNTRACK_MARK
- if (filter && !((ct->mark & filter->mark.mask) ==
- filter->mark.val)) {
+ if (ctnetlink_filter(ct, cb->data))
continue;
- }
-#endif
+
rcu_read_lock();
res =
ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid,
@@ -1001,6 +1025,29 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
.len = NF_CT_LABELS_MAX_SIZE },
};
+static int ctnl_flush_filter(struct nf_conn *i, void *data)
+{
+ return ctnetlink_filter(i, data) == 0;
+}
+
+static int ctnetlink_flush_conntrack(struct net *net,
+ const struct nlattr * const cda[],
+ u32 portid, int report)
+{
+ struct ctnetlink_filter *filter = NULL;
+
+ if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
+ filter = ctnetlink_alloc_filter(cda);
+ if (IS_ERR(filter))
+ return PTR_ERR(filter);
+ }
+
+ nf_ct_iterate_cleanup(net, ctnl_flush_filter, filter, portid, report);
+ kfree(filter);
+
+ return 0;
+}
+
static int
ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
const struct nlmsghdr *nlh,
@@ -1024,11 +1071,9 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
else if (cda[CTA_TUPLE_REPLY])
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
else {
- /* Flush the whole table */
- nf_conntrack_flush_report(net,
- NETLINK_CB(skb).portid,
- nlmsg_report(nlh));
- return 0;
+ return ctnetlink_flush_conntrack(net, cda,
+ NETLINK_CB(skb).portid,
+ nlmsg_report(nlh));
}
if (err < 0)
@@ -1076,21 +1121,16 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
.dump = ctnetlink_dump_table,
.done = ctnetlink_done,
};
-#ifdef CONFIG_NF_CONNTRACK_MARK
+
if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
- struct ctnetlink_dump_filter *filter;
+ struct ctnetlink_filter *filter;
- filter = kzalloc(sizeof(struct ctnetlink_dump_filter),
- GFP_ATOMIC);
- if (filter == NULL)
- return -ENOMEM;
+ filter = ctnetlink_alloc_filter(cda);
+ if (IS_ERR(filter))
+ return PTR_ERR(filter);
- filter->mark.val = ntohl(nla_get_be32(cda[CTA_MARK]));
- filter->mark.mask =
- ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
c.data = filter;
}
-#endif
return netlink_dump_start(ctnl, skb, nlh, &c);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/2] conntrack: Flush connections with a given mark
2015-01-07 18:56 ` Pablo Neira Ayuso
@ 2015-01-07 20:05 ` Kristian Evensen
2015-01-08 13:13 ` Pablo Neira Ayuso
2015-01-07 20:16 ` Kristian Evensen
1 sibling, 1 reply; 8+ messages in thread
From: Kristian Evensen @ 2015-01-07 20:05 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Netfilter Development Mailing list
Hi Pablo,
On Wed, Jan 7, 2015 at 7:56 PM, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> 1) strict type checking in the dump case (for the ctnetlink_filter
> object), instead of relying on the genering void * to keep the
> ct_iterate happy. It adds a bit more code but I prefer it like this.
>
> 2) Explicitly reject mark filters when marks are not supported. This
> changes the previous behaviour, but I think this is good to have so
> userspace knows that what it is requesting is not support (instead of
> silently ignoring it).
>
> 3) add helper function to allocate the filter object, so this always
> needs explicit release.
>
> Please, have a look a it and let me know if you're fine with it. I'll
> pass it to net-next (upcoming 3.20).
Thank you for making the improvements, the patch looks a lot better
now! I only have on question/comment. What is the reason behind adding
the ctnl_flush_filter()? Isn't it enough to have ctnetlink_filter()
return 1 in case of match and 0 otherwise. At least, the way I think,
it makes more sense when I read the code that if this function returns
false, we should ignore conntrack entry due to no match. So the check
in ctnetlink_dump_table() should read !ctnetlink_filter(). In
addition, there is a small typo in the commit log. In the last
paragraph it says ctnetlink_apply_filter(). After your changes, it is
just called ctnetlink_filter().
Thanks again for your help.
-Kristian
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/2] conntrack: Flush connections with a given mark
2015-01-07 18:56 ` Pablo Neira Ayuso
2015-01-07 20:05 ` Kristian Evensen
@ 2015-01-07 20:16 ` Kristian Evensen
1 sibling, 0 replies; 8+ messages in thread
From: Kristian Evensen @ 2015-01-07 20:16 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Netfilter Development Mailing list
On Wed, Jan 7, 2015 at 7:56 PM, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
>
> Please, have a look a it and let me know if you're fine with it. I'll
> pass it to net-next (upcoming 3.20).
I forgot to say that I am fine with the updated patch either way.
Sorry about that.
-Kristian
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/2] conntrack: Flush connections with a given mark
2015-01-07 20:05 ` Kristian Evensen
@ 2015-01-08 13:13 ` Pablo Neira Ayuso
2015-01-08 13:28 ` Kristian Evensen
0 siblings, 1 reply; 8+ messages in thread
From: Pablo Neira Ayuso @ 2015-01-08 13:13 UTC (permalink / raw)
To: Kristian Evensen; +Cc: Netfilter Development Mailing list
[-- Attachment #1: Type: text/plain, Size: 1598 bytes --]
On Wed, Jan 07, 2015 at 09:05:22PM +0100, Kristian Evensen wrote:
> Hi Pablo,
>
> On Wed, Jan 7, 2015 at 7:56 PM, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > 1) strict type checking in the dump case (for the ctnetlink_filter
> > object), instead of relying on the genering void * to keep the
> > ct_iterate happy. It adds a bit more code but I prefer it like this.
> >
> > 2) Explicitly reject mark filters when marks are not supported. This
> > changes the previous behaviour, but I think this is good to have so
> > userspace knows that what it is requesting is not support (instead of
> > silently ignoring it).
> >
> > 3) add helper function to allocate the filter object, so this always
> > needs explicit release.
> >
> > Please, have a look a it and let me know if you're fine with it. I'll
> > pass it to net-next (upcoming 3.20).
>
> Thank you for making the improvements, the patch looks a lot better
> now! I only have on question/comment. What is the reason behind adding
> the ctnl_flush_filter()? Isn't it enough to have ctnetlink_filter()
> return 1 in case of match and 0 otherwise. At least, the way I think,
> it makes more sense when I read the code that if this function returns
> false, we should ignore conntrack entry due to no match. So the check
> in ctnetlink_dump_table() should read !ctnetlink_filter(). In
> addition, there is a small typo in the commit log. In the last
> paragraph it says ctnetlink_apply_filter(). After your changes, it is
> just called ctnetlink_filter().
I made some changes based on your comments, attached a new version of
your patch.
[-- Attachment #2: 0001-netfilter-conntrack-Flush-connections-with-a-given-m.patch --]
[-- Type: text/x-diff, Size: 5130 bytes --]
>From 866476f323465a8afef10b14b48d5136bf5c51fe Mon Sep 17 00:00:00 2001
From: Kristian Evensen <kristian.evensen@gmail.com>
Date: Wed, 24 Dec 2014 09:57:10 +0100
Subject: [PATCH nf-next] netfilter: conntrack: Flush connections with a given
mark
This patch adds support for selective flushing of conntrack mappings.
By adding CTA_MARK and CTA_MARK_MASK to a delete-message, the mark (and
mask) is checked before a connection is deleted while flushing.
Configuring the flush is moved out of ctnetlink_del_conntrack(), and
instead of calling nf_conntrack_flush_report(), we always call
nf_ct_iterate_cleanup(). This enables us to only make one call from the
new ctnetlink_flush_conntrack() and makes it easy to add more filter
parameters.
Filtering is done in the ctnetlink_filter_match()-function, which is
also called from ctnetlink_dump_table(). ctnetlink_dump_filter has been
renamed ctnetlink_filter, to indicated that it is no longer only used
when dumping conntrack entries.
Moreover, reject mark filters with -EOPNOTSUPP if no ct mark support is
available.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_conntrack_netlink.c | 89 ++++++++++++++++++++++++----------
1 file changed, 64 insertions(+), 25 deletions(-)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 1bd9ed9..d1c2394 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -749,13 +749,47 @@ static int ctnetlink_done(struct netlink_callback *cb)
return 0;
}
-struct ctnetlink_dump_filter {
+struct ctnetlink_filter {
struct {
u_int32_t val;
u_int32_t mask;
} mark;
};
+static struct ctnetlink_filter *
+ctnetlink_alloc_filter(const struct nlattr * const cda[])
+{
+#ifdef CONFIG_NF_CONNTRACK_MARK
+ struct ctnetlink_filter *filter;
+
+ 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]));
+
+ return filter;
+#else
+ return ERR_PTR(-EOPNOTSUPP);
+#endif
+}
+
+static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
+{
+ struct ctnetlink_filter *filter = data;
+
+ if (filter == NULL)
+ return 1;
+
+#ifdef CONFIG_NF_CONNTRACK_MARK
+ if ((ct->mark & filter->mark.mask) == filter->mark.val)
+ return 1;
+#endif
+
+ return 0;
+}
+
static int
ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
{
@@ -768,10 +802,6 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
int res;
spinlock_t *lockp;
-#ifdef CONFIG_NF_CONNTRACK_MARK
- const struct ctnetlink_dump_filter *filter = cb->data;
-#endif
-
last = (struct nf_conn *)cb->args[1];
local_bh_disable();
@@ -798,12 +828,9 @@ restart:
continue;
cb->args[1] = 0;
}
-#ifdef CONFIG_NF_CONNTRACK_MARK
- if (filter && !((ct->mark & filter->mark.mask) ==
- filter->mark.val)) {
+ if (!ctnetlink_filter_match(ct, cb->data))
continue;
- }
-#endif
+
rcu_read_lock();
res =
ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid,
@@ -1001,6 +1028,25 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
.len = NF_CT_LABELS_MAX_SIZE },
};
+static int ctnetlink_flush_conntrack(struct net *net,
+ const struct nlattr * const cda[],
+ u32 portid, int report)
+{
+ struct ctnetlink_filter *filter = NULL;
+
+ if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
+ filter = ctnetlink_alloc_filter(cda);
+ if (IS_ERR(filter))
+ return PTR_ERR(filter);
+ }
+
+ nf_ct_iterate_cleanup(net, ctnetlink_filter_match, filter,
+ portid, report);
+ kfree(filter);
+
+ return 0;
+}
+
static int
ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
const struct nlmsghdr *nlh,
@@ -1024,11 +1070,9 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
else if (cda[CTA_TUPLE_REPLY])
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
else {
- /* Flush the whole table */
- nf_conntrack_flush_report(net,
- NETLINK_CB(skb).portid,
- nlmsg_report(nlh));
- return 0;
+ return ctnetlink_flush_conntrack(net, cda,
+ NETLINK_CB(skb).portid,
+ nlmsg_report(nlh));
}
if (err < 0)
@@ -1076,21 +1120,16 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
.dump = ctnetlink_dump_table,
.done = ctnetlink_done,
};
-#ifdef CONFIG_NF_CONNTRACK_MARK
+
if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
- struct ctnetlink_dump_filter *filter;
+ struct ctnetlink_filter *filter;
- filter = kzalloc(sizeof(struct ctnetlink_dump_filter),
- GFP_ATOMIC);
- if (filter == NULL)
- return -ENOMEM;
+ filter = ctnetlink_alloc_filter(cda);
+ if (IS_ERR(filter))
+ return PTR_ERR(filter);
- filter->mark.val = ntohl(nla_get_be32(cda[CTA_MARK]));
- filter->mark.mask =
- ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
c.data = filter;
}
-#endif
return netlink_dump_start(ctnl, skb, nlh, &c);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/2] conntrack: Flush connections with a given mark
2015-01-08 13:13 ` Pablo Neira Ayuso
@ 2015-01-08 13:28 ` Kristian Evensen
0 siblings, 0 replies; 8+ messages in thread
From: Kristian Evensen @ 2015-01-08 13:28 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Netfilter Development Mailing list
Hi Pablo,
On Thu, Jan 8, 2015 at 2:13 PM, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> I made some changes based on your comments, attached a new version of
> your patch.
Thanks a lot for all the help, patch looks great :)
-Kristian
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-01-08 13:28 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-24 8:57 [PATCH v2 0/2] conntrack: Support flushing connections with given mark Kristian Evensen
2014-12-24 8:57 ` [PATCH v2 1/2] conntrack: Flush connections with a " Kristian Evensen
2015-01-07 18:56 ` Pablo Neira Ayuso
2015-01-07 20:05 ` Kristian Evensen
2015-01-08 13:13 ` Pablo Neira Ayuso
2015-01-08 13:28 ` Kristian Evensen
2015-01-07 20:16 ` Kristian Evensen
2014-12-24 8:57 ` [PATCH v2 2/2] conntrack: Remove nf_ct_conntrack_flush_report Kristian Evensen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).