summaryrefslogtreecommitdiffstats
path: root/extensions/libxt_connlimit.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2021-06-02 19:57:37 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2021-06-07 21:35:27 +0200
commitbb01e33d3828d08cd77cc3c9664b2a995ee150cc (patch)
treed51cd9287d7d570a48e8544aa336b1e5ba2182ab /extensions/libxt_connlimit.c
parent62828a6aff231e9f7f40c0321f7740f53070c2fb (diff)
extensions: libxt_connlimit: add translation
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>
Diffstat (limited to 'extensions/libxt_connlimit.c')
-rw-r--r--extensions/libxt_connlimit.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/extensions/libxt_connlimit.c b/extensions/libxt_connlimit.c
index a569f86a..118faea5 100644
--- a/extensions/libxt_connlimit.c
+++ b/extensions/libxt_connlimit.c
@@ -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,
},
};