mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-02-15 04:42:02 +00:00
223 lines
7.8 KiB
Diff
223 lines
7.8 KiB
Diff
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(-)
|
|
|
|
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
|
|
index 75df968..beab9d8 100644
|
|
--- a/include/linux/netfilter/nf_tables.h
|
|
+++ b/include/linux/netfilter/nf_tables.h
|
|
@@ -1409,6 +1409,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
|
|
*
|
|
diff --git a/include/statement.h b/include/statement.h
|
|
index 2a2d300..cbd48dd 100644
|
|
--- a/include/statement.h
|
|
+++ b/include/statement.h
|
|
@@ -122,6 +122,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,
|
|
};
|
|
|
|
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
|
index 068c3bb..8513113 100644
|
|
--- a/src/netlink_delinearize.c
|
|
+++ b/src/netlink_delinearize.c
|
|
@@ -1369,6 +1369,53 @@ static void netlink_parse_masq(struct netlink_parse_ctx *ctx,
|
|
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)
|
|
@@ -1787,6 +1834,7 @@ static const struct expr_handler netlink_parsers[] = {
|
|
{ .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 },
|
|
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
|
|
index c8bbcb7..505eafa 100644
|
|
--- a/src/netlink_linearize.c
|
|
+++ b/src/netlink_linearize.c
|
|
@@ -1140,6 +1140,13 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,
|
|
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");
|
|
|
|
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
|
index ca5c488..ec9fc9b 100644
|
|
--- a/src/parser_bison.y
|
|
+++ b/src/parser_bison.y
|
|
@@ -571,6 +571,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"
|
|
@@ -703,8 +704,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
|
|
@@ -2853,6 +2854,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
|
|
@@ -3753,6 +3755,28 @@ masq_stmt_args : TO COLON stmt_expr
|
|
}
|
|
;
|
|
|
|
+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;
|
|
+ $<stmt>0->nat.flags = $4;
|
|
+ }
|
|
+ | nf_nat_flags
|
|
+ {
|
|
+ $<stmt>0->nat.flags = $1;
|
|
+ }
|
|
+ ;
|
|
+
|
|
redir_stmt : redir_stmt_alloc redir_stmt_arg
|
|
| redir_stmt_alloc
|
|
;
|
|
diff --git a/src/scanner.l b/src/scanner.l
|
|
index 2154281..c389860 100644
|
|
--- a/src/scanner.l
|
|
+++ b/src/scanner.l
|
|
@@ -453,6 +453,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>{
|
|
diff --git a/src/statement.c b/src/statement.c
|
|
index 30caf9c..f4866c2 100644
|
|
--- a/src/statement.c
|
|
+++ b/src/statement.c
|
|
@@ -650,6 +650,7 @@ const char *nat_etype2str(enum nft_nat_etypes type)
|
|
[NFT_NAT_SNAT] = "snat",
|
|
[NFT_NAT_DNAT] = "dnat",
|
|
[NFT_NAT_MASQ] = "masquerade",
|
|
+ [NFT_NAT_FULLCONE] = "fullcone",
|
|
[NFT_NAT_REDIR] = "redirect",
|
|
};
|
|
|