]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: add nat persistent and random options
authorArturo Borrero <arturo.borrero.glez@gmail.com>
Fri, 3 Oct 2014 12:46:41 +0000 (14:46 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 9 Oct 2014 12:09:28 +0000 (14:09 +0200)
This patch adds more configuration options to the nat expression.

The syntax is as follow:
 % nft add rule nat postrouting <snat|dnat> <nat_arguments> [flags]

Flags are: random, persistent, random-fully.
Example:

 % nft add rule nat postrouting dnat 1.1.1.1 random,persistent

A requirement is to cache some [recent] copies of kernel headers.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/linux/netfilter/nf_conntrack_tuple_common.h
include/linux/netfilter/nf_nat.h [new file with mode: 0644]
include/statement.h
src/netlink_delinearize.c
src/netlink_linearize.c
src/parser.y
src/scanner.l
src/statement.c

index 8e145f0d61cb1c7aed4c7f23476086c16f9b99af..8ab311841fcc365989833dc8a3228f3f0eafd936 100644 (file)
@@ -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 (file)
index 0000000..0880781
--- /dev/null
@@ -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 */
index 574835cd4d4796595537fe8587fe860896b41362..e523254288b5049660e7e6a38e01e419b659cd89 100644 (file)
@@ -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);
index 397b65c0179e53f285fc9d30189c8112be891fb8..4bb4697cf11c5ab67dc5bbf7f79813afb09d50b6 100644 (file)
@@ -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);
index 29f8e9ae40dff67ba8fc1673739a8656b44d656f..895cfa995e4c34c85d1b3b0de48f1dd1f61c4360 100644 (file)
@@ -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++;
index 03d6d1384aea3631d02ded5da60742d28381cace..aac25679630b5256d8f57d156bc9374d519bd86c 100644 (file)
@@ -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
index 9f054fdf6068fc0b2f46d66fe9151f102c77e2cc..0955c4afa4eab068879fb9049966b7a1509176e0 100644 (file)
@@ -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; }
index 357f094894e8ebadd1af861908a8fa9e2f983768..f1d83fcbe972c3d2089ecff053a1f4a370b22550 100644 (file)
@@ -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)