Skip to contentSkip to conversation

netfilter: connlimit: split xt_connlimit into front/backend

PATCH Superseded Florian Westphal 2 participants 3 messages Dec 2, 2017 – Dec 6, 2017

Subsystems (2)

v2 of 5 Superseded Latest is v5 →

lore
Share & tools
lore

Florian Westphal

author maintainer
#0 lore raw

PATCH v2 1/1 netfilter: connlimit: split xt_connlimit into front/backend

This allows to reuse xt_connlimit infrastructure from nf_tables.

The upcoming nf_tables frontend can just pass in an nftables register as input key, this allows limiting by arbitrary keys via concatenations.

For xt_connlimit, pass in the zone and the ip/ipv6 address as key to keep same behaviour.

---
V2: add missing EXPORT_SYMBOL annotations

 include/net/netfilter/nf_conntrack_count.h  |  13 +
 include/uapi/linux/netfilter/xt_connlimit.h |   2 +-
 net/netfilter/Kconfig                       |   3 +
 net/netfilter/Makefile                      |   2 +
 net/netfilter/nf_conncount.c                | 371 ++++++++++++++++++++++++++++
 net/netfilter/xt_connlimit.c                | 367 ++-------------------------
 6 files changed, 414 insertions(+), 344 deletions(-)
 create mode 100644 include/net/netfilter/nf_conntrack_count.h
 create mode 100644 net/netfilter/nf_conncount.c
include/net/netfilter/nf_conntrack_count.h new file +13 -0
new file mode 100644
index 000000000000..eafaabb9e2f9
@@ -0,0 +1,13 @@
+struct nf_conncount_data;
+
+struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family,
+					    unsigned int keylen);
+void nf_conncount_destroy(struct net *net, unsigned int family,
+			  struct nf_conncount_data *data);
+
+unsigned int nf_conncount_count(struct net *net,
+				struct nf_conncount_data *data,
+				const u32 *key,
+				unsigned int family,
+				const struct nf_conntrack_tuple *tuple,
+				const struct nf_conntrack_zone *zone);
include/uapi/linux/netfilter/xt_connlimit.h +1 -1
index 07e5e9d47882..d4d1943dcd11 100644
@@ -27,7 +27,7 @@ struct xt_connlimit_info {
 	__u32 flags;
 
 	/* Used internally by the kernel */
-	struct xt_connlimit_data *data __attribute__((aligned(8)));
+	struct nf_conncount_data *data __attribute__((aligned(8)));
 };
 
 #endif /* _XT_CONNLIMIT_H */
net/netfilter/Kconfig +3 -0
index e4a13cc8a2e7..8a043b85fc07 100644
@@ -62,6 +62,8 @@ config NF_LOG_NETDEV
 	select NF_LOG_COMMON
 
 if NF_CONNTRACK
+config NETFILTER_CONNCOUNT
+	tristate
 
 config NF_CONNTRACK_MARK
 	bool  'Connection mark tracking support'
@@ -1120,6 +1122,7 @@ config NETFILTER_XT_MATCH_CONNLIMIT
 	tristate '"connlimit" match support'
 	depends on NF_CONNTRACK
 	depends on NETFILTER_ADVANCED
+	select NETFILTER_CONNCOUNT
 	---help---
 	  This match allows you to match against the number of parallel
 	  connections to a server per client IP address (or address block).
net/netfilter/Makefile +2 -0
index f78ed2470831..490a55e7166d 100644
@@ -67,6 +67,8 @@ obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o
 # SYNPROXY
 obj-$(CONFIG_NETFILTER_SYNPROXY) += nf_synproxy_core.o
 
+obj-$(CONFIG_NETFILTER_CONNCOUNT) += nf_conncount.o
+
 # generic packet duplication from netdev family
 obj-$(CONFIG_NF_DUP_NETDEV)	+= nf_dup_netdev.o
 
net/netfilter/nf_conncount.c new file +371 -0

371 lines not on this page · raw message

net/netfilter/xt_connlimit.c +24 -343

445 lines not on this page · raw message

Signature · 1 line
2.13.6
#1 lore raw

Thanks for working on this patch.

include/net/netfilter/nf_conntrack_count.h

Quoted 3 lines
include/net/netfilter/nf_conntrack_count.h new file +0 -0
@@ -0,0 +1,13 @@

Should it have something like the following in the header file?

#ifdef _NF_CONNTRACK_COUNT_H
#define _NF_CONNTRACK_COUNT_H

include/net/netfilter/nf_conntrack_count.h line 13

Quoted 13 lines
include/net/netfilter/nf_conntrack_count.h new file +13 -0
+struct nf_conncount_data;
+
+struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family,
+                                           unsigned int keylen);
+void nf_conncount_destroy(struct net *net, unsigned int family,
+                         struct nf_conncount_data *data);
+
+unsigned int nf_conncount_count(struct net *net,
+                               struct nf_conncount_data *data,
+                               const u32 *key,
+                               unsigned int family,
+                               const struct nf_conntrack_tuple *tuple,
+                               const struct nf_conntrack_zone *zone);

#endif /*_NF_CONNTRACK_COUNT_H*/

net/netfilter/nf_conncount.c line 279

Quoted 13 lines
net/netfilter/nf_conncount.c new file +11 -0
+
+struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family,
+                                           unsigned int keylen)
+{
+       struct nf_conncount_data *data;
+       int ret, i;
+
+       if (keylen % sizeof(u32) ||
+           keylen / sizeof(u32) > MAX_KEYLEN ||
+           keylen == 0)
+               return ERR_PTR(-EINVAL);

Just wanna to check the case that if users want to count only by zone, since zone id is only 2 bytes, the user should claim 4 bytes as the keylen right?

net/netfilter/nf_conncount.c line 289

Quoted 10 lines
net/netfilter/nf_conncount.c new file +10 -0
+
+       net_get_random_once(&conncount_rnd, sizeof(conncount_rnd));
+
+       ret = nf_ct_netns_get(net, family);
+       if (ret < 0)
+               return ERR_PTR(ret);
+
+       data = kmalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return ERR_PTR(-ENOMEM);

Should we call nf_ct_netns_put() in the error case?

net/netfilter/nf_conncount.c line 298

Quoted 9 lines
net/netfilter/nf_conncount.c new file +9 -0
+
+       for (i = 0; i < ARRAY_SIZE(data->root); ++i)
+               data->root[i] = RB_ROOT;
+
+       data->keylen = keylen / sizeof(u32);
+
+       return data;
+}
+EXPORT_SYMBOL_GPL(nf_conncount_init);

Thanks,

-Yi-Hung

author maintainer
#2 lore raw
Quoted 9 lines · Yi-Hung Wei

Thanks for working on this patch.

include/net/netfilter/nf_conntrack_count.h

Quoted 3 lines
include/net/netfilter/nf_conntrack_count.h new file +0 -0
@@ -0,0 +1,13 @@

Should it have something like the following in the header file?

#ifdef _NF_CONNTRACK_COUNT_H
#define _NF_CONNTRACK_COUNT_H

I can add it, sure.

Quoted 8 lines
Quoted 8 lines
net/netfilter/nf_conncount.c new file +6 -0
+
+struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family,
+                                           unsigned int keylen)
+{
+       struct nf_conncount_data *data;
+       int ret, i;
Quoted 8 lines

net/netfilter/nf_conncount.c line 279

Quoted 5 lines
net/netfilter/nf_conncount.c new file +5 -0
+
+       if (keylen % sizeof(u32) ||
+           keylen / sizeof(u32) > MAX_KEYLEN ||
+           keylen == 0)
+               return ERR_PTR(-EINVAL);

Just wanna to check the case that if users want to count only by zone, since zone id is only 2 bytes, the user should claim 4 bytes as the keylen right?

Yes, I used jhash2 internally which requires input in u32-sized chunks.

Quoted 8 lines

net/netfilter/nf_conncount.c line 289

Quoted 7 lines
net/netfilter/nf_conncount.c new file +7 -0
+       ret = nf_ct_netns_get(net, family);
+       if (ret < 0)
+               return ERR_PTR(ret);
+
+       data = kmalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return ERR_PTR(-ENOMEM);

Should we call nf_ct_netns_put() in the error case?

Indeed, I'll fix this, thanks for the review!