]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
extensions: libxt_connlimit: add translation
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 2 Jun 2021 17:57:37 +0000 (19:57 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 7 Jun 2021 19:35:27 +0000 (21:35 +0200)
This patch adds a translation for connlimit matches which requires
the definition of a set and the family context (either IPv4 or IPv6)
which is required to display the netmask accordingly.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
extensions/libxt_connlimit.c
extensions/libxt_connlimit.txlate [new file with mode: 0644]

index a569f86aa6b223e007c4473d918cd0adb9b44a24..118faea560f73cfefc6e60db2b65634889d68e48 100644 (file)
@@ -2,6 +2,8 @@
 #include <netdb.h>
 #include <string.h>
 #include <xtables.h>
+#include <arpa/inet.h>
+
 #include <linux/netfilter/xt_connlimit.h>
 
 enum {
@@ -183,6 +185,51 @@ static void connlimit_save6(const void *ip, const struct xt_entry_match *match)
        }
 }
 
+static int connlimit_xlate(struct xt_xlate *xl,
+                          const struct xt_xlate_mt_params *params)
+{
+       const struct xt_connlimit_info *info = (const void *)params->match->data;
+       static uint32_t connlimit_id;
+       char netmask[128] = {};
+       char addr[64] = {};
+       uint32_t mask;
+
+       switch (xt_xlate_get_family(xl)) {
+       case AF_INET:
+               mask = count_bits4(info->v4_mask);
+               if (mask != 32) {
+                       struct in_addr *in = (struct in_addr *)&info->v4_mask;
+
+                       inet_ntop(AF_INET, in, addr, sizeof(addr));
+                       snprintf(netmask, sizeof(netmask), "and %s ", addr);
+               }
+               break;
+       case AF_INET6:
+               mask = count_bits6(info->v6_mask);
+               if (mask != 128) {
+                       struct in6_addr *in6 = (struct in6_addr *)&info->v6_mask;
+
+                       inet_ntop(AF_INET6, in6, addr, sizeof(addr));
+                       snprintf(netmask, sizeof(netmask), "and %s ", addr);
+               }
+               break;
+       default:
+               return 0;
+       }
+
+       xt_xlate_set_add(xl, "connlimit%u { type ipv4_addr; flags dynamic; }",
+                        connlimit_id);
+       xt_xlate_rule_add(xl, "add @connlimit%u { %s %s %sct count %s%u }",
+                         connlimit_id++,
+                         xt_xlate_get_family(xl) == AF_INET ? "ip" : "ip6",
+                         info->flags & XT_CONNLIMIT_DADDR ? "daddr" : "saddr",
+                         netmask,
+                         info->flags & XT_CONNLIMIT_INVERT ? "" : "over ",
+                         info->limit);
+
+       return 1;
+}
+
 static struct xtables_match connlimit_mt_reg[] = {
        {
                .name          = "connlimit",
@@ -228,6 +275,7 @@ static struct xtables_match connlimit_mt_reg[] = {
                .print         = connlimit_print4,
                .save          = connlimit_save4,
                .x6_options    = connlimit_opts,
+               .xlate         = connlimit_xlate,
        },
        {
                .name          = "connlimit",
@@ -243,6 +291,7 @@ static struct xtables_match connlimit_mt_reg[] = {
                .print         = connlimit_print6,
                .save          = connlimit_save6,
                .x6_options    = connlimit_opts,
+               .xlate         = connlimit_xlate,
        },
 };
 
diff --git a/extensions/libxt_connlimit.txlate b/extensions/libxt_connlimit.txlate
new file mode 100644 (file)
index 0000000..758868c
--- /dev/null
@@ -0,0 +1,15 @@
+iptables-translate -A INPUT -m connlimit --connlimit-above 2
+nft add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }
+nft add rule ip filter INPUT add @connlimit0 { ip saddr ct count over 2 } counter
+
+iptables-translate -A INPUT -m connlimit --connlimit-upto 2
+nft add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }
+nft add rule ip filter INPUT add @connlimit0 { ip saddr ct count 2 } counter
+
+iptables-translate -A INPUT -m connlimit --connlimit-upto 2 --connlimit-mask 24
+nft add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }
+nft add rule ip filter INPUT add @connlimit0 { ip saddr and 255.255.255.0 ct count 2 } counter
+
+iptables-translate -A INPUT -m connlimit --connlimit-upto 2 --connlimit-daddr
+nft add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }
+nft add rule ip filter INPUT add @connlimit0 { ip daddr ct count 2 } counter