mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-07-04 05:27:06 +08:00
firewall4: add fullconenat-nf NAT1 support
This commit is contained in:
parent
acc2592fe6
commit
771e27b030
@ -9,19 +9,21 @@ include $(TOPDIR)/rules.mk
|
|||||||
|
|
||||||
PKG_NAME:=libnftnl
|
PKG_NAME:=libnftnl
|
||||||
PKG_CPE_ID:=cpe:/a:netfilter:libnftnl
|
PKG_CPE_ID:=cpe:/a:netfilter:libnftnl
|
||||||
PKG_VERSION:=1.2.4
|
PKG_VERSION:=1.2.8
|
||||||
PKG_RELEASE:=$(AUTORELEASE)
|
PKG_RELEASE:=2
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||||
PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files
|
PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files
|
||||||
PKG_HASH:=c0fe233be4cdfd703e7d5977ef8eb63fcbf1d0052b6044e1b23d47ca3562477f
|
PKG_HASH:=37fea5d6b5c9b08de7920d298de3cdc942e7ae64b1a3e8b880b2d390ae67ad95
|
||||||
|
|
||||||
PKG_MAINTAINER:=Steven Barth <steven@midlink.org>
|
PKG_MAINTAINER:=Steven Barth <steven@midlink.org>
|
||||||
PKG_LICENSE:=GPL-2.0-or-later
|
PKG_LICENSE:=GPL-2.0-or-later
|
||||||
PKG_LICENSE_FILES:=COPYING
|
PKG_LICENSE_FILES:=COPYING
|
||||||
|
|
||||||
|
PKG_FIXUP:=autoreconf
|
||||||
PKG_INSTALL:=1
|
PKG_INSTALL:=1
|
||||||
PKG_BUILD_PARALLEL:=1
|
PKG_BUILD_PARALLEL:=1
|
||||||
|
PKG_BUILD_FLAGS:=lto
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/package.mk
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
@ -41,8 +43,7 @@ define Package/libnftnl/description
|
|||||||
programming interface (API) to the in-kernel nf_tables subsystem.
|
programming interface (API) to the in-kernel nf_tables subsystem.
|
||||||
endef
|
endef
|
||||||
|
|
||||||
TARGET_CFLAGS += $(FPIC) -flto
|
TARGET_CFLAGS += $(FPIC)
|
||||||
TARGET_LDFLAGS += -flto
|
|
||||||
|
|
||||||
CONFIGURE_ARGS += \
|
CONFIGURE_ARGS += \
|
||||||
--enable-static \
|
--enable-static \
|
||||||
|
@ -0,0 +1,261 @@
|
|||||||
|
From 6c39f04febd7cfdbd474233379416babcd0fc341 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
Date: Fri, 8 Apr 2022 23:52:11 +0800
|
||||||
|
Subject: [PATCH] libnftnl: add fullcone expression support
|
||||||
|
|
||||||
|
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
---
|
||||||
|
include/libnftnl/expr.h | 6 +
|
||||||
|
include/linux/netfilter/nf_tables.h | 16 +++
|
||||||
|
src/Makefile.am | 1 +
|
||||||
|
src/expr/fullcone.c | 167 ++++++++++++++++++++++++++++
|
||||||
|
src/expr_ops.c | 2 +
|
||||||
|
5 files changed, 192 insertions(+)
|
||||||
|
create mode 100644 src/expr/fullcone.c
|
||||||
|
|
||||||
|
--- a/include/libnftnl/expr.h
|
||||||
|
+++ b/include/libnftnl/expr.h
|
||||||
|
@@ -272,6 +272,13 @@ enum {
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
+ NFTNL_EXPR_FULLCONE_FLAGS = NFTNL_EXPR_BASE,
|
||||||
|
+ NFTNL_EXPR_FULLCONE_REG_PROTO_MIN,
|
||||||
|
+ NFTNL_EXPR_FULLCONE_REG_PROTO_MAX,
|
||||||
|
+ __NFTNL_EXPR_FULLCONE_MAX
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+enum {
|
||||||
|
NFTNL_EXPR_REDIR_REG_PROTO_MIN = NFTNL_EXPR_BASE,
|
||||||
|
NFTNL_EXPR_REDIR_REG_PROTO_MAX,
|
||||||
|
NFTNL_EXPR_REDIR_FLAGS,
|
||||||
|
--- a/include/linux/netfilter/nf_tables.h
|
||||||
|
+++ b/include/linux/netfilter/nf_tables.h
|
||||||
|
@@ -1464,6 +1464,22 @@ enum nft_masq_attributes {
|
||||||
|
#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
+ * enum nft_fullcone_attributes - nf_tables fullcone expression attributes
|
||||||
|
+ *
|
||||||
|
+ * @NFTA_FULLCONE_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
|
||||||
|
+ * @NFTA_FULLCONE_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
|
||||||
|
+ * @NFTA_FULLCONE_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
|
||||||
|
+ */
|
||||||
|
+enum nft_fullcone_attributes {
|
||||||
|
+ NFTA_FULLCONE_UNSPEC,
|
||||||
|
+ NFTA_FULLCONE_FLAGS,
|
||||||
|
+ NFTA_FULLCONE_REG_PROTO_MIN,
|
||||||
|
+ NFTA_FULLCONE_REG_PROTO_MAX,
|
||||||
|
+ __NFTA_FULLCONE_MAX
|
||||||
|
+};
|
||||||
|
+#define NFTA_FULLCONE_MAX (__NFTA_FULLCONE_MAX - 1)
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
* enum nft_redir_attributes - nf_tables redirect expression netlink attributes
|
||||||
|
*
|
||||||
|
* @NFTA_REDIR_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
|
||||||
|
--- a/src/Makefile.am
|
||||||
|
+++ b/src/Makefile.am
|
||||||
|
@@ -55,6 +55,7 @@ libnftnl_la_SOURCES = utils.c \
|
||||||
|
expr/target.c \
|
||||||
|
expr/tunnel.c \
|
||||||
|
expr/masq.c \
|
||||||
|
+ expr/fullcone.c \
|
||||||
|
expr/redir.c \
|
||||||
|
expr/hash.c \
|
||||||
|
expr/socket.c \
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/expr/fullcone.c
|
||||||
|
@@ -0,0 +1,174 @@
|
||||||
|
+/*
|
||||||
|
+ * (C) 2022-2025 wongsyrone
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published
|
||||||
|
+ * by the Free Software Foundation; either version 2 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdint.h>
|
||||||
|
+#include <arpa/inet.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <inttypes.h>
|
||||||
|
+
|
||||||
|
+#include <linux/netfilter/nf_tables.h>
|
||||||
|
+
|
||||||
|
+#include "internal.h"
|
||||||
|
+#include <libmnl/libmnl.h>
|
||||||
|
+#include <libnftnl/expr.h>
|
||||||
|
+#include <libnftnl/rule.h>
|
||||||
|
+
|
||||||
|
+struct nftnl_expr_fullcone {
|
||||||
|
+ uint32_t flags;
|
||||||
|
+ enum nft_registers sreg_proto_min;
|
||||||
|
+ enum nft_registers sreg_proto_max;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+nftnl_expr_fullcone_set(struct nftnl_expr *e, uint16_t type,
|
||||||
|
+ const void *data, uint32_t data_len)
|
||||||
|
+{
|
||||||
|
+ struct nftnl_expr_fullcone *fullcone = nftnl_expr_data(e);
|
||||||
|
+
|
||||||
|
+ switch (type) {
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_FLAGS:
|
||||||
|
+ memcpy(&fullcone->flags, data, data_len);
|
||||||
|
+ break;
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_REG_PROTO_MIN:
|
||||||
|
+ memcpy(&fullcone->sreg_proto_min, data, data_len);
|
||||||
|
+ break;
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_REG_PROTO_MAX:
|
||||||
|
+ memcpy(&fullcone->sreg_proto_max, data, data_len);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const void *
|
||||||
|
+nftnl_expr_fullcone_get(const struct nftnl_expr *e, uint16_t type,
|
||||||
|
+ uint32_t *data_len)
|
||||||
|
+{
|
||||||
|
+ struct nftnl_expr_fullcone *fullcone = nftnl_expr_data(e);
|
||||||
|
+
|
||||||
|
+ switch (type) {
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_FLAGS:
|
||||||
|
+ *data_len = sizeof(fullcone->flags);
|
||||||
|
+ return &fullcone->flags;
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_REG_PROTO_MIN:
|
||||||
|
+ *data_len = sizeof(fullcone->sreg_proto_min);
|
||||||
|
+ return &fullcone->sreg_proto_min;
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_REG_PROTO_MAX:
|
||||||
|
+ *data_len = sizeof(fullcone->sreg_proto_max);
|
||||||
|
+ return &fullcone->sreg_proto_max;
|
||||||
|
+ }
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int nftnl_expr_fullcone_cb(const struct nlattr *attr, void *data)
|
||||||
|
+{
|
||||||
|
+ const struct nlattr **tb = data;
|
||||||
|
+ int type = mnl_attr_get_type(attr);
|
||||||
|
+
|
||||||
|
+ if (mnl_attr_type_valid(attr, NFTA_FULLCONE_MAX) < 0)
|
||||||
|
+ return MNL_CB_OK;
|
||||||
|
+
|
||||||
|
+ switch (type) {
|
||||||
|
+ case NFTA_FULLCONE_REG_PROTO_MIN:
|
||||||
|
+ case NFTA_FULLCONE_REG_PROTO_MAX:
|
||||||
|
+ case NFTA_FULLCONE_FLAGS:
|
||||||
|
+ if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
|
||||||
|
+ abi_breakage();
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ tb[type] = attr;
|
||||||
|
+ return MNL_CB_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+nftnl_expr_fullcone_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
|
||||||
|
+{
|
||||||
|
+ struct nftnl_expr_fullcone *fullcone = nftnl_expr_data(e);
|
||||||
|
+
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_FLAGS))
|
||||||
|
+ mnl_attr_put_u32(nlh, NFTA_FULLCONE_FLAGS, htobe32(fullcone->flags));
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MIN))
|
||||||
|
+ mnl_attr_put_u32(nlh, NFTA_FULLCONE_REG_PROTO_MIN,
|
||||||
|
+ htobe32(fullcone->sreg_proto_min));
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MAX))
|
||||||
|
+ mnl_attr_put_u32(nlh, NFTA_FULLCONE_REG_PROTO_MAX,
|
||||||
|
+ htobe32(fullcone->sreg_proto_max));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+nftnl_expr_fullcone_parse(struct nftnl_expr *e, struct nlattr *attr)
|
||||||
|
+{
|
||||||
|
+ struct nftnl_expr_fullcone *fullcone = nftnl_expr_data(e);
|
||||||
|
+ struct nlattr *tb[NFTA_FULLCONE_MAX+1] = {};
|
||||||
|
+
|
||||||
|
+ if (mnl_attr_parse_nested(attr, nftnl_expr_fullcone_cb, tb) < 0)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ if (tb[NFTA_FULLCONE_FLAGS]) {
|
||||||
|
+ fullcone->flags = be32toh(mnl_attr_get_u32(tb[NFTA_FULLCONE_FLAGS]));
|
||||||
|
+ e->flags |= (1 << NFTNL_EXPR_FULLCONE_FLAGS);
|
||||||
|
+ }
|
||||||
|
+ if (tb[NFTA_FULLCONE_REG_PROTO_MIN]) {
|
||||||
|
+ fullcone->sreg_proto_min =
|
||||||
|
+ be32toh(mnl_attr_get_u32(tb[NFTA_FULLCONE_REG_PROTO_MIN]));
|
||||||
|
+ e->flags |= (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MIN);
|
||||||
|
+ }
|
||||||
|
+ if (tb[NFTA_FULLCONE_REG_PROTO_MAX]) {
|
||||||
|
+ fullcone->sreg_proto_max =
|
||||||
|
+ be32toh(mnl_attr_get_u32(tb[NFTA_FULLCONE_REG_PROTO_MAX]));
|
||||||
|
+ e->flags |= (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MAX);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int nftnl_expr_fullcone_snprintf(char *buf, size_t remain,
|
||||||
|
+ uint32_t flags, const struct nftnl_expr *e)
|
||||||
|
+{
|
||||||
|
+ struct nftnl_expr_fullcone *fullcone = nftnl_expr_data(e);
|
||||||
|
+ int offset = 0, ret = 0;
|
||||||
|
+
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MIN)) {
|
||||||
|
+ ret = snprintf(buf + offset, remain, "proto_min reg %u ",
|
||||||
|
+ fullcone->sreg_proto_min);
|
||||||
|
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
|
||||||
|
+ }
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MAX)) {
|
||||||
|
+ ret = snprintf(buf + offset, remain, "proto_max reg %u ",
|
||||||
|
+ fullcone->sreg_proto_max);
|
||||||
|
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
|
||||||
|
+ }
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_FLAGS)) {
|
||||||
|
+ ret = snprintf(buf + offset, remain, "flags 0x%x ", fullcone->flags);
|
||||||
|
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return offset;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct attr_policy fullcone_attr_policy[__NFTNL_EXPR_FULLCONE_MAX] = {
|
||||||
|
+ [NFTNL_EXPR_FULLCONE_FLAGS] = { .maxlen = sizeof(uint32_t) },
|
||||||
|
+ [NFTNL_EXPR_FULLCONE_REG_PROTO_MIN] = { .maxlen = sizeof(uint32_t) },
|
||||||
|
+ [NFTNL_EXPR_FULLCONE_REG_PROTO_MAX] = { .maxlen = sizeof(uint32_t) },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct expr_ops expr_ops_fullcone = {
|
||||||
|
+ .name = "fullcone",
|
||||||
|
+ .alloc_len = sizeof(struct nftnl_expr_fullcone),
|
||||||
|
+ .nftnl_max_attr = __NFTNL_EXPR_FULLCONE_MAX - 1,
|
||||||
|
+ .attr_policy = fullcone_attr_policy,
|
||||||
|
+ .set = nftnl_expr_fullcone_set,
|
||||||
|
+ .get = nftnl_expr_fullcone_get,
|
||||||
|
+ .parse = nftnl_expr_fullcone_parse,
|
||||||
|
+ .build = nftnl_expr_fullcone_build,
|
||||||
|
+ .output = nftnl_expr_fullcone_snprintf,
|
||||||
|
+};
|
||||||
|
--- a/src/expr_ops.c
|
||||||
|
+++ b/src/expr_ops.c
|
||||||
|
@@ -20,6 +20,7 @@ extern struct expr_ops expr_ops_limit;
|
||||||
|
extern struct expr_ops expr_ops_log;
|
||||||
|
extern struct expr_ops expr_ops_lookup;
|
||||||
|
extern struct expr_ops expr_ops_masq;
|
||||||
|
+extern struct expr_ops expr_ops_fullcone;
|
||||||
|
extern struct expr_ops expr_ops_match;
|
||||||
|
extern struct expr_ops expr_ops_meta;
|
||||||
|
extern struct expr_ops expr_ops_ng;
|
||||||
|
@@ -65,6 +66,7 @@ static struct expr_ops *expr_ops[] = {
|
||||||
|
&expr_ops_log,
|
||||||
|
&expr_ops_lookup,
|
||||||
|
&expr_ops_masq,
|
||||||
|
+ &expr_ops_fullcone,
|
||||||
|
&expr_ops_match,
|
||||||
|
&expr_ops_meta,
|
||||||
|
&expr_ops_ng,
|
@ -0,0 +1,216 @@
|
|||||||
|
From aa3b56e289fba7425e649a608c333622ffd9c367 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
Date: Sat, 9 Apr 2022 13:24:19 +0800
|
||||||
|
Subject: [PATCH] firewall4: add fullcone support
|
||||||
|
|
||||||
|
fullcone is drop-in replacement of masq for non-udp traffic
|
||||||
|
|
||||||
|
add runtime fullcone rule check, disable it globally if fullcone expr is
|
||||||
|
invalid
|
||||||
|
|
||||||
|
defaults.fullcone and defaults.fullcone6 are switches for IPv4 and IPv6
|
||||||
|
respectively, most IPv6 traffic do NOT need this FullCone NAT functionality.
|
||||||
|
|
||||||
|
Renew: ZiMing Mo <msylgj@immortalwrt.org>
|
||||||
|
---
|
||||||
|
root/etc/config/firewall | 2 ++
|
||||||
|
root/usr/share/firewall4/templates/ruleset.uc | 16 ++++++++++++++--
|
||||||
|
.../firewall4/templates/zone-fullcone.uc | 4 ++++
|
||||||
|
root/usr/share/ucode/fw4.uc | 69 ++++++++++++++++++-
|
||||||
|
4 files changed, 89 insertions(+), 4 deletions(-)
|
||||||
|
create mode 100644 root/usr/share/firewall4/templates/zone-fullcone.uc
|
||||||
|
|
||||||
|
--- a/root/etc/config/firewall
|
||||||
|
+++ b/root/etc/config/firewall
|
||||||
|
@@ -5,6 +5,10 @@ config defaults
|
||||||
|
option forward REJECT
|
||||||
|
# Uncomment this line to disable ipv6 rules
|
||||||
|
# option disable_ipv6 1
|
||||||
|
+ option flow_offloading 1
|
||||||
|
+ option flow_offloading_hw 1
|
||||||
|
+ option fullcone 1
|
||||||
|
+ option fullcone6 0
|
||||||
|
|
||||||
|
config zone
|
||||||
|
option name lan
|
||||||
|
--- a/root/usr/share/firewall4/templates/ruleset.uc
|
||||||
|
+++ b/root/usr/share/firewall4/templates/ruleset.uc
|
||||||
|
@@ -327,6 +327,12 @@ table inet fw4 {
|
||||||
|
{% for (let redirect in fw4.redirects(`dstnat_${zone.name}`)): %}
|
||||||
|
{%+ include("redirect.uc", { fw4, zone, redirect }) %}
|
||||||
|
{% endfor %}
|
||||||
|
+{% if (zone.masq && fw4.default_option("fullcone")): %}
|
||||||
|
+ {%+ include("zone-fullcone.uc", { fw4, zone, family: 4, direction: "dstnat" }) %}
|
||||||
|
+{% endif %}
|
||||||
|
+{% if (zone.masq6 && fw4.default_option("fullcone6")): %}
|
||||||
|
+ {%+ include("zone-fullcone.uc", { fw4, zone, family: 6, direction: "dstnat" }) %}
|
||||||
|
+{% endif %}
|
||||||
|
{% fw4.includes('chain-append', `dstnat_${zone.name}`) %}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -337,20 +343,26 @@ table inet fw4 {
|
||||||
|
{% for (let redirect in fw4.redirects(`srcnat_${zone.name}`)): %}
|
||||||
|
{%+ include("redirect.uc", { fw4, zone, redirect }) %}
|
||||||
|
{% endfor %}
|
||||||
|
-{% if (zone.masq): %}
|
||||||
|
+{% if (zone.masq && !fw4.default_option("fullcone")): %}
|
||||||
|
{% for (let saddrs in zone.masq4_src_subnets): %}
|
||||||
|
{% for (let daddrs in zone.masq4_dest_subnets): %}
|
||||||
|
{%+ include("zone-masq.uc", { fw4, zone, family: 4, saddrs, daddrs }) %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
-{% if (zone.masq6): %}
|
||||||
|
+{% if (zone.masq6 && !fw4.default_option("fullcone6")): %}
|
||||||
|
{% for (let saddrs in zone.masq6_src_subnets): %}
|
||||||
|
{% for (let daddrs in zone.masq6_dest_subnets): %}
|
||||||
|
{%+ include("zone-masq.uc", { fw4, zone, family: 6, saddrs, daddrs }) %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
+{% if (zone.masq && fw4.default_option("fullcone")): %}
|
||||||
|
+ {%+ include("zone-fullcone.uc", { fw4, zone, family: 4, direction: "srcnat" }) %}
|
||||||
|
+{% endif %}
|
||||||
|
+{% if (zone.masq6 && fw4.default_option("fullcone6")): %}
|
||||||
|
+ {%+ include("zone-fullcone.uc", { fw4, zone, family: 6, direction: "srcnat" }) %}
|
||||||
|
+{% endif %}
|
||||||
|
{% fw4.includes('chain-append', `srcnat_${zone.name}`) %}
|
||||||
|
}
|
||||||
|
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/root/usr/share/firewall4/templates/zone-fullcone.uc
|
||||||
|
@@ -0,0 +1,4 @@
|
||||||
|
+{# /usr/share/firewall4/templates/zone-fullcone.uc #}
|
||||||
|
+ meta nfproto {{ fw4.nfproto(family) }} fullcone comment "!fw4: Handle {{
|
||||||
|
+ zone.name
|
||||||
|
+}} {{ fw4.nfproto(family, true) }} fullcone NAT {{ direction }} traffic"
|
||||||
|
--- a/root/usr/share/ucode/fw4.uc
|
||||||
|
+++ b/root/usr/share/ucode/fw4.uc
|
||||||
|
@@ -1,3 +1,5 @@
|
||||||
|
+// /usr/share/ucode/fw4.uc
|
||||||
|
+
|
||||||
|
const fs = require("fs");
|
||||||
|
const uci = require("uci");
|
||||||
|
const ubus = require("ubus");
|
||||||
|
@@ -489,6 +491,25 @@ function nft_try_hw_offload(devices) {
|
||||||
|
return (rc == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+function nft_try_fullcone() {
|
||||||
|
+ let nft_test =
|
||||||
|
+ 'add table inet fw4-fullcone-test; ' +
|
||||||
|
+ 'add chain inet fw4-fullcone-test dstnat { ' +
|
||||||
|
+ 'type nat hook prerouting priority -100; policy accept; ' +
|
||||||
|
+ 'fullcone; ' +
|
||||||
|
+ '}; ' +
|
||||||
|
+ 'add chain inet fw4-fullcone-test srcnat { ' +
|
||||||
|
+ 'type nat hook postrouting priority -100; policy accept; ' +
|
||||||
|
+ 'fullcone; ' +
|
||||||
|
+ '}; ';
|
||||||
|
+ let cmd = sprintf("/usr/sbin/nft -c '%s' 2>/dev/null", replace(nft_test, "'", "'\\''"));
|
||||||
|
+ let ok = system(cmd) == 0;
|
||||||
|
+ if (!ok) {
|
||||||
|
+ warn("nft_try_fullcone: cmd "+ cmd + "\n");
|
||||||
|
+ }
|
||||||
|
+ return ok;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
return {
|
||||||
|
read_kernel_version: function() {
|
||||||
|
@@ -855,6 +876,18 @@ return {
|
||||||
|
warn(`[!] ${msg}\n`);
|
||||||
|
},
|
||||||
|
|
||||||
|
+ myinfo: function(fmt, ...args) {
|
||||||
|
+ if (getenv("QUIET"))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ let msg = sprintf(fmt, ...args);
|
||||||
|
+
|
||||||
|
+ if (getenv("TTY"))
|
||||||
|
+ warn(`\033[32m${msg}\033[m\n`);
|
||||||
|
+ else
|
||||||
|
+ warn(`[I] ${msg}\n`);
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
get: function(sid, opt) {
|
||||||
|
return this.cursor.get("firewall", sid, opt);
|
||||||
|
},
|
||||||
|
@@ -1036,6 +1069,21 @@ return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
+ myinfo_section: function(s, msg) {
|
||||||
|
+ if (s[".name"]) {
|
||||||
|
+ if (s.name)
|
||||||
|
+ this.myinfo("Section %s (%s) %s", this.section_id(s[".name"]), s.name, msg);
|
||||||
|
+ else
|
||||||
|
+ this.myinfo("Section %s %s", this.section_id(s[".name"]), msg);
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ if (s.name)
|
||||||
|
+ this.myinfo("ubus %s (%s) %s", s.type || "rule", s.name, msg);
|
||||||
|
+ else
|
||||||
|
+ this.myinfo("ubus %s %s", s.type || "rule", msg);
|
||||||
|
+ }
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
parse_policy: function(val) {
|
||||||
|
return this.parse_enum(val, [
|
||||||
|
"accept",
|
||||||
|
@@ -1475,6 +1523,7 @@ return {
|
||||||
|
"dnat",
|
||||||
|
"snat",
|
||||||
|
"masquerade",
|
||||||
|
+ "fullcone",
|
||||||
|
"accept",
|
||||||
|
"reject",
|
||||||
|
"drop"
|
||||||
|
@@ -1946,6 +1995,8 @@ return {
|
||||||
|
}
|
||||||
|
|
||||||
|
let defs = this.parse_options(data, {
|
||||||
|
+ fullcone: [ "bool", "0" ],
|
||||||
|
+ fullcone6: [ "bool", "0" ],
|
||||||
|
input: [ "policy", "drop" ],
|
||||||
|
output: [ "policy", "drop" ],
|
||||||
|
forward: [ "policy", "drop" ],
|
||||||
|
@@ -1980,6 +2031,11 @@ return {
|
||||||
|
|
||||||
|
delete defs.syn_flood;
|
||||||
|
|
||||||
|
+ if (!nft_try_fullcone()) {
|
||||||
|
+ delete defs.fullcone;
|
||||||
|
+ warn("nft_try_fullcone failed, disable fullcone globally\n");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
this.state.defaults = defs;
|
||||||
|
},
|
||||||
|
|
||||||
|
@@ -2205,10 +2261,23 @@ return {
|
||||||
|
zone.related_subnets = related_subnets;
|
||||||
|
zone.related_physdevs = related_physdevs;
|
||||||
|
|
||||||
|
- if (zone.masq || zone.masq6)
|
||||||
|
+ if (zone.masq) {
|
||||||
|
zone.dflags.snat = true;
|
||||||
|
+ if (this.state.defaults.fullcone) {
|
||||||
|
+ zone.dflags.dnat = true;
|
||||||
|
+ this.myinfo_section(data, "IPv4 fullcone enabled for zone '" + zone.name + "'");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (zone.masq6) {
|
||||||
|
+ zone.dflags.snat = true;
|
||||||
|
+ if (this.state.defaults.fullcone6) {
|
||||||
|
+ zone.dflags.dnat = true;
|
||||||
|
+ this.myinfo_section(data, "IPv6 fullcone enabled for zone '" + zone.name + "'");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if ((zone.auto_helper && !(zone.masq || zone.masq6)) || length(zone.helper)) {
|
||||||
|
+ if ((zone.auto_helper && !(zone.masq || zone.masq6 || this.state.defaults.fullcone || this.state.defaults.fullcone6)) || length(zone.helper)) {
|
||||||
|
zone.dflags.helper = true;
|
||||||
|
|
||||||
|
for (let helper in (length(zone.helper) ? zone.helper : this.state.helpers)) {
|
50
package/network/services/fullconenat-nft/Makefile
Normal file
50
package/network/services/fullconenat-nft/Makefile
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
# Copyright (c) 2018 Chion Tang <tech@chionlab.moe>
|
||||||
|
# Original xt_FULLCONENAT and related iptables extension author
|
||||||
|
# Copyright (c) 2019-2022 GitHub/llccd Twitter/@gNodeB
|
||||||
|
# Added IPv6 support for xt_FULLCONENAT and ip6tables extension
|
||||||
|
# Ported to recent kernel versions
|
||||||
|
# Copyright (c) 2022 Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
# Massively rewrite the whole module, split the original code into library and nftables 'fullcone' expression module
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
include $(INCLUDE_DIR)/kernel.mk
|
||||||
|
|
||||||
|
PKG_NAME:=fullconenat-nft
|
||||||
|
PKG_RELEASE:=2
|
||||||
|
|
||||||
|
PKG_SOURCE_PROTO:=git
|
||||||
|
PKG_SOURCE_URL:=https://github.com/fullcone-nat-nftables/nft-fullcone.git
|
||||||
|
PKG_SOURCE_DATE:=2023-05-17
|
||||||
|
PKG_SOURCE_VERSION:=07d93b626ce5ea885cd16f9ab07fac3213c355d9
|
||||||
|
PKG_MIRROR_HASH:=b89c68c68b5912f20cefed703c993498fed612ba4860fa75ef50037cb79a32f5
|
||||||
|
|
||||||
|
PKG_LICENSE:=GPL-2.0-only
|
||||||
|
PKG_LICENSE_FILES:=LICENSE
|
||||||
|
PKG_MAINTAINER:=Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
define KernelPackage/nft-fullcone
|
||||||
|
SUBMENU:=Netfilter Extensions
|
||||||
|
DEPENDS:=+kmod-nft-nat
|
||||||
|
TITLE:=nftables fullcone expression support
|
||||||
|
FILES:= $(PKG_BUILD_DIR)/src/nft_fullcone.ko
|
||||||
|
KCONFIG:= \
|
||||||
|
CONFIG_NF_CONNTRACK_EVENTS=y \
|
||||||
|
CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y
|
||||||
|
AUTOLOAD:=$(call AutoProbe,nft_fullcone)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define KernelPackage/nft-fullcone/Description
|
||||||
|
Kernel module adds the fullcone expression that you can use
|
||||||
|
to perform NAT in the RFC3489-compatible full cone SNAT flavour.
|
||||||
|
Currently only UDP traffic is supported for full-cone NAT.
|
||||||
|
For other protos FULLCONENAT is equivalent to MASQUERADE.
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Compile
|
||||||
|
+$(KERNEL_MAKE) M="$(PKG_BUILD_DIR)/src" modules
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call KernelPackage,nft-fullcone))
|
@ -0,0 +1,14 @@
|
|||||||
|
--- a/src/nft_ext_fullcone.c
|
||||||
|
+++ b/src/nft_ext_fullcone.c
|
||||||
|
@@ -121,7 +121,11 @@ static int exp_event_cb(unsigned int eve
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
|
||||||
|
+static int nft_fullcone_validate(const struct nft_ctx *ctx, const struct nft_expr *expr)
|
||||||
|
+#else
|
||||||
|
static int nft_fullcone_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nft_data **data)
|
||||||
|
+#endif
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
@ -6,12 +6,12 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=nftables
|
PKG_NAME:=nftables
|
||||||
PKG_VERSION:=1.0.6
|
PKG_VERSION:=1.1.1
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||||
PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files
|
PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files
|
||||||
PKG_HASH:=2407430ddd82987670e48dc2fda9e280baa8307abec04ab18d609df3db005e4c
|
PKG_HASH:=6358830f3a64f31e39b0ad421d7dadcd240b72343ded48d8ef13b8faf204865a
|
||||||
|
|
||||||
PKG_MAINTAINER:=
|
PKG_MAINTAINER:=
|
||||||
PKG_LICENSE:=GPL-2.0
|
PKG_LICENSE:=GPL-2.0
|
||||||
@ -20,6 +20,8 @@ PKG_LICENSE_FILES:=COPYING
|
|||||||
PKG_FIXUP:=autoreconf
|
PKG_FIXUP:=autoreconf
|
||||||
PKG_INSTALL:=1
|
PKG_INSTALL:=1
|
||||||
|
|
||||||
|
PKG_BUILD_FLAGS:=lto
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/package.mk
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
DISABLE_NLS:=
|
DISABLE_NLS:=
|
||||||
@ -36,7 +38,7 @@ define Package/nftables/Default
|
|||||||
CATEGORY:=Network
|
CATEGORY:=Network
|
||||||
SUBMENU:=Firewall
|
SUBMENU:=Firewall
|
||||||
TITLE:=nftables userspace utility
|
TITLE:=nftables userspace utility
|
||||||
DEPENDS:=+kmod-nft-core +libnftnl
|
DEPENDS:=+kmod-nft-core +libnftnl +kmod-nft-fullcone
|
||||||
URL:=http://netfilter.org/projects/nftables/
|
URL:=http://netfilter.org/projects/nftables/
|
||||||
PROVIDES:=nftables
|
PROVIDES:=nftables
|
||||||
endef
|
endef
|
||||||
@ -60,9 +62,6 @@ ifeq ($(BUILD_VARIANT),json)
|
|||||||
CONFIGURE_ARGS += --with-json
|
CONFIGURE_ARGS += --with-json
|
||||||
endif
|
endif
|
||||||
|
|
||||||
TARGET_CFLAGS += -flto
|
|
||||||
TARGET_LDFLAGS += -flto
|
|
||||||
|
|
||||||
define Build/InstallDev
|
define Build/InstallDev
|
||||||
$(INSTALL_DIR) $(1)/usr/lib $(1)/usr/include
|
$(INSTALL_DIR) $(1)/usr/lib $(1)/usr/include
|
||||||
$(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
--- a/tests/shell/run-tests.sh.rej
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,15 +0,0 @@
|
||||||
|
---- run-tests.sh
|
||||||
|
-+++ run-tests.sh
|
||||||
|
-@@ -565,11 +565,8 @@ feature_probe()
|
||||||
|
- fi
|
||||||
|
-
|
||||||
|
- if [ -x "$with_path.sh" ] ; then
|
||||||
|
-- echo $with_path
|
||||||
|
- NFT="$NFT_REAL" $NFT_TEST_UNSHARE_CMD "$with_path.sh" &>/dev/null
|
||||||
|
-- RET=$?
|
||||||
|
-- echo $?
|
||||||
|
-- return $RET
|
||||||
|
-+ return $?
|
||||||
|
- fi
|
||||||
|
-
|
||||||
|
- return 1
|
@ -0,0 +1,209 @@
|
|||||||
|
From 58c89e8768711a959fdc6e953df3ea2254ff93c1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
Date: Sat, 9 Apr 2022 00:38:51 +0800
|
||||||
|
Subject: [PATCH] nftables: add fullcone expression support
|
||||||
|
|
||||||
|
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
---
|
||||||
|
include/linux/netfilter/nf_tables.h | 16 ++++++++++
|
||||||
|
include/statement.h | 1 +
|
||||||
|
src/netlink_delinearize.c | 48 +++++++++++++++++++++++++++++
|
||||||
|
src/netlink_linearize.c | 7 +++++
|
||||||
|
src/parser_bison.y | 28 +++++++++++++++--
|
||||||
|
src/scanner.l | 1 +
|
||||||
|
src/statement.c | 1 +
|
||||||
|
7 files changed, 100 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
--- a/include/linux/netfilter/nf_tables.h
|
||||||
|
+++ b/include/linux/netfilter/nf_tables.h
|
||||||
|
@@ -1485,6 +1485,22 @@ enum nft_masq_attributes {
|
||||||
|
#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
+ * enum nft_fullcone_attributes - nf_tables fullcone expression attributes
|
||||||
|
+ *
|
||||||
|
+ * @NFTA_FULLCONE_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
|
||||||
|
+ * @NFTA_FULLCONE_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
|
||||||
|
+ * @NFTA_FULLCONE_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
|
||||||
|
+ */
|
||||||
|
+enum nft_fullcone_attributes {
|
||||||
|
+ NFTA_FULLCONE_UNSPEC,
|
||||||
|
+ NFTA_FULLCONE_FLAGS,
|
||||||
|
+ NFTA_FULLCONE_REG_PROTO_MIN,
|
||||||
|
+ NFTA_FULLCONE_REG_PROTO_MAX,
|
||||||
|
+ __NFTA_FULLCONE_MAX
|
||||||
|
+};
|
||||||
|
+#define NFTA_FULLCONE_MAX (__NFTA_FULLCONE_MAX - 1)
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
* enum nft_redir_attributes - nf_tables redirect expression netlink attributes
|
||||||
|
*
|
||||||
|
* @NFTA_REDIR_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
|
||||||
|
--- a/include/statement.h
|
||||||
|
+++ b/include/statement.h
|
||||||
|
@@ -129,6 +129,7 @@ enum nft_nat_etypes {
|
||||||
|
__NFT_NAT_SNAT = NFT_NAT_SNAT,
|
||||||
|
__NFT_NAT_DNAT = NFT_NAT_DNAT,
|
||||||
|
NFT_NAT_MASQ,
|
||||||
|
+ NFT_NAT_FULLCONE,
|
||||||
|
NFT_NAT_REDIR,
|
||||||
|
};
|
||||||
|
|
||||||
|
--- a/src/netlink_delinearize.c
|
||||||
|
+++ b/src/netlink_delinearize.c
|
||||||
|
@@ -1467,6 +1467,53 @@ out_err:
|
||||||
|
stmt_free(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void netlink_parse_fullcone(struct netlink_parse_ctx *ctx,
|
||||||
|
+ const struct location *loc,
|
||||||
|
+ const struct nftnl_expr *nle)
|
||||||
|
+{
|
||||||
|
+ enum nft_registers reg1, reg2;
|
||||||
|
+ struct expr *proto;
|
||||||
|
+ struct stmt *stmt;
|
||||||
|
+ uint32_t flags = 0;
|
||||||
|
+
|
||||||
|
+ if (nftnl_expr_is_set(nle, NFTNL_EXPR_FULLCONE_FLAGS))
|
||||||
|
+ flags = nftnl_expr_get_u32(nle, NFTNL_EXPR_FULLCONE_FLAGS);
|
||||||
|
+
|
||||||
|
+ stmt = nat_stmt_alloc(loc, NFT_NAT_FULLCONE);
|
||||||
|
+ stmt->nat.flags = flags;
|
||||||
|
+
|
||||||
|
+ reg1 = netlink_parse_register(nle, NFTNL_EXPR_FULLCONE_REG_PROTO_MIN);
|
||||||
|
+ if (reg1) {
|
||||||
|
+ proto = netlink_get_register(ctx, loc, reg1);
|
||||||
|
+ if (proto == NULL) {
|
||||||
|
+ netlink_error(ctx, loc,
|
||||||
|
+ "fullcone statement has no proto expression");
|
||||||
|
+ goto out_err;
|
||||||
|
+ }
|
||||||
|
+ expr_set_type(proto, &inet_service_type, BYTEORDER_BIG_ENDIAN);
|
||||||
|
+ stmt->nat.proto = proto;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ reg2 = netlink_parse_register(nle, NFTNL_EXPR_FULLCONE_REG_PROTO_MAX);
|
||||||
|
+ if (reg2 && reg2 != reg1) {
|
||||||
|
+ proto = netlink_get_register(ctx, loc, reg2);
|
||||||
|
+ if (proto == NULL) {
|
||||||
|
+ netlink_error(ctx, loc,
|
||||||
|
+ "fullcone statement has no proto expression");
|
||||||
|
+ goto out_err;
|
||||||
|
+ }
|
||||||
|
+ expr_set_type(proto, &inet_service_type, BYTEORDER_BIG_ENDIAN);
|
||||||
|
+ if (stmt->nat.proto != NULL)
|
||||||
|
+ proto = range_expr_alloc(loc, stmt->nat.proto, proto);
|
||||||
|
+ stmt->nat.proto = proto;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ctx->stmt = stmt;
|
||||||
|
+ return;
|
||||||
|
+out_err:
|
||||||
|
+ stmt_free(stmt);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void netlink_parse_redir(struct netlink_parse_ctx *ctx,
|
||||||
|
const struct location *loc,
|
||||||
|
const struct nftnl_expr *nle)
|
||||||
|
@@ -1897,6 +1944,7 @@ static const struct expr_handler netlink
|
||||||
|
{ .name = "tproxy", .parse = netlink_parse_tproxy },
|
||||||
|
{ .name = "notrack", .parse = netlink_parse_notrack },
|
||||||
|
{ .name = "masq", .parse = netlink_parse_masq },
|
||||||
|
+ { .name = "fullcone", .parse = netlink_parse_fullcone },
|
||||||
|
{ .name = "redir", .parse = netlink_parse_redir },
|
||||||
|
{ .name = "dup", .parse = netlink_parse_dup },
|
||||||
|
{ .name = "queue", .parse = netlink_parse_queue },
|
||||||
|
--- a/src/netlink_linearize.c
|
||||||
|
+++ b/src/netlink_linearize.c
|
||||||
|
@@ -1226,6 +1226,13 @@ static void netlink_gen_nat_stmt(struct
|
||||||
|
nftnl_reg_pmin = NFTNL_EXPR_MASQ_REG_PROTO_MIN;
|
||||||
|
nftnl_reg_pmax = NFTNL_EXPR_MASQ_REG_PROTO_MAX;
|
||||||
|
break;
|
||||||
|
+ case NFT_NAT_FULLCONE:
|
||||||
|
+ nle = alloc_nft_expr("fullcone");
|
||||||
|
+
|
||||||
|
+ nftnl_flag_attr = NFTNL_EXPR_FULLCONE_FLAGS;
|
||||||
|
+ nftnl_reg_pmin = NFTNL_EXPR_FULLCONE_REG_PROTO_MIN;
|
||||||
|
+ nftnl_reg_pmax = NFTNL_EXPR_FULLCONE_REG_PROTO_MAX;
|
||||||
|
+ break;
|
||||||
|
case NFT_NAT_REDIR:
|
||||||
|
nle = alloc_nft_expr("redir");
|
||||||
|
|
||||||
|
--- a/src/parser_bison.y
|
||||||
|
+++ b/src/parser_bison.y
|
||||||
|
@@ -643,6 +643,7 @@ int nft_lex(void *, void *, void *);
|
||||||
|
%token SNAT "snat"
|
||||||
|
%token DNAT "dnat"
|
||||||
|
%token MASQUERADE "masquerade"
|
||||||
|
+%token FULLCONE "fullcone"
|
||||||
|
%token REDIRECT "redirect"
|
||||||
|
%token RANDOM "random"
|
||||||
|
%token FULLY_RANDOM "fully-random"
|
||||||
|
@@ -784,8 +785,8 @@ int nft_lex(void *, void *, void *);
|
||||||
|
%type <val> limit_burst_pkts limit_burst_bytes limit_mode limit_bytes time_unit quota_mode
|
||||||
|
%type <stmt> reject_stmt reject_stmt_alloc
|
||||||
|
%destructor { stmt_free($$); } reject_stmt reject_stmt_alloc
|
||||||
|
-%type <stmt> nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc redir_stmt redir_stmt_alloc
|
||||||
|
-%destructor { stmt_free($$); } nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc redir_stmt redir_stmt_alloc
|
||||||
|
+%type <stmt> nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc fullcone_stmt fullcone_stmt_alloc redir_stmt redir_stmt_alloc
|
||||||
|
+%destructor { stmt_free($$); } nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc fullcone_stmt fullcone_stmt_alloc redir_stmt redir_stmt_alloc
|
||||||
|
%type <val> nf_nat_flags nf_nat_flag offset_opt
|
||||||
|
%type <stmt> tproxy_stmt
|
||||||
|
%destructor { stmt_free($$); } tproxy_stmt
|
||||||
|
@@ -3216,6 +3217,7 @@ stmt : verdict_stmt
|
||||||
|
| queue_stmt
|
||||||
|
| ct_stmt
|
||||||
|
| masq_stmt close_scope_nat
|
||||||
|
+ | fullcone_stmt close_scope_nat
|
||||||
|
| redir_stmt close_scope_nat
|
||||||
|
| dup_stmt close_scope_dup
|
||||||
|
| fwd_stmt close_scope_fwd
|
||||||
|
@@ -3999,6 +4001,28 @@ masq_stmt_args : TO COLON stmt_expr
|
||||||
|
{
|
||||||
|
$<stmt>0->nat.proto = $3;
|
||||||
|
}
|
||||||
|
+ | TO COLON stmt_expr nf_nat_flags
|
||||||
|
+ {
|
||||||
|
+ $<stmt>0->nat.proto = $3;
|
||||||
|
+ $<stmt>0->nat.flags = $4;
|
||||||
|
+ }
|
||||||
|
+ | nf_nat_flags
|
||||||
|
+ {
|
||||||
|
+ $<stmt>0->nat.flags = $1;
|
||||||
|
+ }
|
||||||
|
+ ;
|
||||||
|
+
|
||||||
|
+fullcone_stmt : fullcone_stmt_alloc fullcone_stmt_args
|
||||||
|
+ | fullcone_stmt_alloc
|
||||||
|
+ ;
|
||||||
|
+
|
||||||
|
+fullcone_stmt_alloc : FULLCONE { $$ = nat_stmt_alloc(&@$, NFT_NAT_FULLCONE); }
|
||||||
|
+ ;
|
||||||
|
+
|
||||||
|
+fullcone_stmt_args : TO COLON stmt_expr
|
||||||
|
+ {
|
||||||
|
+ $<stmt>0->nat.proto = $3;
|
||||||
|
+ }
|
||||||
|
| TO COLON stmt_expr nf_nat_flags
|
||||||
|
{
|
||||||
|
$<stmt>0->nat.proto = $3;
|
||||||
|
--- a/src/scanner.l
|
||||||
|
+++ b/src/scanner.l
|
||||||
|
@@ -462,6 +462,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr
|
||||||
|
"snat" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return SNAT; }
|
||||||
|
"dnat" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return DNAT; }
|
||||||
|
"masquerade" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return MASQUERADE; }
|
||||||
|
+"fullcone" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return FULLCONE; }
|
||||||
|
"redirect" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return REDIRECT; }
|
||||||
|
"random" { return RANDOM; }
|
||||||
|
<SCANSTATE_STMT_NAT>{
|
||||||
|
--- a/src/statement.c
|
||||||
|
+++ b/src/statement.c
|
||||||
|
@@ -674,6 +674,7 @@ const char *nat_etype2str(enum nft_nat_e
|
||||||
|
[NFT_NAT_SNAT] = "snat",
|
||||||
|
[NFT_NAT_DNAT] = "dnat",
|
||||||
|
[NFT_NAT_MASQ] = "masquerade",
|
||||||
|
+ [NFT_NAT_FULLCONE] = "fullcone",
|
||||||
|
[NFT_NAT_REDIR] = "redirect",
|
||||||
|
};
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user