summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/nf_conntrack_tuple_common.h32
-rw-r--r--include/linux/netfilter/nf_nat.h42
-rw-r--r--include/statement.h1
-rw-r--r--src/netlink_delinearize.c4
-rw-r--r--src/netlink_linearize.c3
-rw-r--r--src/parser.y21
-rw-r--r--src/scanner.l3
-rw-r--r--src/statement.c26
8 files changed, 130 insertions, 2 deletions
diff --git a/include/linux/netfilter/nf_conntrack_tuple_common.h b/include/linux/netfilter/nf_conntrack_tuple_common.h
index 8e145f0d..8ab31184 100644
--- a/include/linux/netfilter/nf_conntrack_tuple_common.h
+++ b/include/linux/netfilter/nf_conntrack_tuple_common.h
@@ -1,13 +1,41 @@
#ifndef _NF_CONNTRACK_TUPLE_COMMON_H
#define _NF_CONNTRACK_TUPLE_COMMON_H
-enum ip_conntrack_dir
-{
+#include <linux/types.h>
+
+enum ip_conntrack_dir {
IP_CT_DIR_ORIGINAL,
IP_CT_DIR_REPLY,
IP_CT_DIR_MAX
};
+/* The protocol-specific manipulable parts of the tuple: always in
+ * network order
+ */
+union nf_conntrack_man_proto {
+ /* Add other protocols here. */
+ __be16 all;
+
+ struct {
+ __be16 port;
+ } tcp;
+ struct {
+ __be16 port;
+ } udp;
+ struct {
+ __be16 id;
+ } icmp;
+ struct {
+ __be16 port;
+ } dccp;
+ struct {
+ __be16 port;
+ } sctp;
+ struct {
+ __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
+ } gre;
+};
+
#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
#endif /* _NF_CONNTRACK_TUPLE_COMMON_H */
diff --git a/include/linux/netfilter/nf_nat.h b/include/linux/netfilter/nf_nat.h
new file mode 100644
index 00000000..0880781a
--- /dev/null
+++ b/include/linux/netfilter/nf_nat.h
@@ -0,0 +1,42 @@
+#ifndef _NETFILTER_NF_NAT_H
+#define _NETFILTER_NF_NAT_H
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+
+#define NF_NAT_RANGE_MAP_IPS (1 << 0)
+#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1)
+#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2)
+#define NF_NAT_RANGE_PERSISTENT (1 << 3)
+#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4)
+
+#define NF_NAT_RANGE_PROTO_RANDOM_ALL \
+ (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+
+#define NF_NAT_RANGE_MASK \
+ (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | \
+ NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | \
+ NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+
+struct nf_nat_ipv4_range {
+ unsigned int flags;
+ __be32 min_ip;
+ __be32 max_ip;
+ union nf_conntrack_man_proto min;
+ union nf_conntrack_man_proto max;
+};
+
+struct nf_nat_ipv4_multi_range_compat {
+ unsigned int rangesize;
+ struct nf_nat_ipv4_range range[1];
+};
+
+struct nf_nat_range {
+ unsigned int flags;
+ union nf_inet_addr min_addr;
+ union nf_inet_addr max_addr;
+ union nf_conntrack_man_proto min_proto;
+ union nf_conntrack_man_proto max_proto;
+};
+
+#endif /* _NETFILTER_NF_NAT_H */
diff --git a/include/statement.h b/include/statement.h
index 574835cd..e5232542 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -68,6 +68,7 @@ struct nat_stmt {
enum nft_nat_types type;
struct expr *addr;
struct expr *proto;
+ uint32_t flags;
};
extern struct stmt *nat_stmt_alloc(const struct location *loc);
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 397b65c0..4bb4697c 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -501,6 +501,10 @@ static void netlink_parse_nat(struct netlink_parse_ctx *ctx,
family = nft_rule_expr_get_u32(nle, NFT_EXPR_NAT_FAMILY);
+ if (nft_rule_expr_is_set(nle, NFT_EXPR_NAT_FLAGS))
+ stmt->nat.flags = nft_rule_expr_get_u32(nle,
+ NFT_EXPR_NAT_FLAGS);
+
reg1 = nft_rule_expr_get_u32(nle, NFT_EXPR_NAT_REG_ADDR_MIN);
if (reg1) {
addr = netlink_get_register(ctx, loc, reg1);
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 29f8e9ae..895cfa99 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -634,6 +634,9 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,
family = nft_rule_attr_get_u32(ctx->nlr, NFT_RULE_ATTR_FAMILY);
nft_rule_expr_set_u32(nle, NFT_EXPR_NAT_FAMILY, family);
+ if (stmt->nat.flags != 0)
+ nft_rule_expr_set_u32(nle, NFT_EXPR_NAT_FLAGS, stmt->nat.flags);
+
if (stmt->nat.addr) {
amin_reg = get_register(ctx);
registers++;
diff --git a/src/parser.y b/src/parser.y
index 03d6d138..aac25679 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -19,6 +19,7 @@
#include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <linux/netfilter/nf_nat.h>
#include <netinet/ip_icmp.h>
#include <netinet/icmp6.h>
#include <libnftnl/common.h>
@@ -376,6 +377,9 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token SNAT "snat"
%token DNAT "dnat"
+%token RANDOM "random"
+%token RANDOM_FULLY "random-fully"
+%token PERSISTENT "persistent"
%token QUEUE "queue"
%token QUEUENUM "num"
@@ -440,6 +444,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%destructor { stmt_free($$); } reject_stmt reject_stmt_alloc
%type <stmt> nat_stmt nat_stmt_alloc
%destructor { stmt_free($$); } nat_stmt nat_stmt_alloc
+%type <val> nf_nat_flags nf_nat_flag
%type <stmt> queue_stmt queue_stmt_alloc
%destructor { stmt_free($$); } queue_stmt queue_stmt_alloc
%type <val> queue_stmt_flags queue_stmt_flag
@@ -1456,6 +1461,22 @@ nat_stmt_args : expr
{
$<stmt>0->nat.proto = $2;
}
+ | nat_stmt_args nf_nat_flags
+ {
+ $<stmt>0->nat.flags = $2;
+ }
+ ;
+
+nf_nat_flags : nf_nat_flag
+ | nf_nat_flags COMMA nf_nat_flag
+ {
+ $$ = $1 | $3;
+ }
+ ;
+
+nf_nat_flag : RANDOM { $$ = NF_NAT_RANGE_PROTO_RANDOM; }
+ | RANDOM_FULLY { $$ = NF_NAT_RANGE_PROTO_RANDOM_FULLY; }
+ | PERSISTENT { $$ = NF_NAT_RANGE_PERSISTENT; }
;
queue_stmt : queue_stmt_alloc
diff --git a/src/scanner.l b/src/scanner.l
index 9f054fdf..0955c4af 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -319,6 +319,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"snat" { return SNAT; }
"dnat" { return DNAT; }
+"random" { return RANDOM; }
+"random-fully" { return RANDOM_FULLY; }
+"persistent" { return PERSISTENT; }
"ll" { return LL_HDR; }
"nh" { return NETWORK_HDR; }
diff --git a/src/statement.c b/src/statement.c
index 357f0948..f1d83fcb 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -24,6 +24,9 @@
#include <utils.h>
#include <list.h>
+#include <netinet/in.h>
+#include <linux/netfilter/nf_nat.h>
+
struct stmt *stmt_alloc(const struct location *loc,
const struct stmt_ops *ops)
{
@@ -271,6 +274,27 @@ struct stmt *reject_stmt_alloc(const struct location *loc)
return stmt_alloc(loc, &reject_stmt_ops);
}
+static void print_nf_nat_flags(uint32_t flags)
+{
+ const char *delim = " ";
+
+ if (flags == 0)
+ return;
+
+ if (flags & NF_NAT_RANGE_PROTO_RANDOM) {
+ printf("%srandom", delim);
+ delim = ",";
+ }
+
+ if (flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) {
+ printf("%srandom-fully", delim);
+ delim = ",";
+ }
+
+ if (flags & NF_NAT_RANGE_PERSISTENT)
+ printf("%spersistent", delim);
+}
+
static void nat_stmt_print(const struct stmt *stmt)
{
static const char *nat_types[] = {
@@ -285,6 +309,8 @@ static void nat_stmt_print(const struct stmt *stmt)
printf(":");
expr_print(stmt->nat.proto);
}
+
+ print_nf_nat_flags(stmt->nat.flags);
}
static void nat_stmt_destroy(struct stmt *stmt)