[PATCH v2 1/2] conntrack: Flush connections with a given mark

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux