]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
hash: generate a random seed if seed option is empty
authorLiping Zhang <zlpnobody@gmail.com>
Sat, 15 Apr 2017 09:22:17 +0000 (17:22 +0800)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sat, 15 Apr 2017 09:30:08 +0000 (11:30 +0200)
Typing the "nft add rule x y ct mark set jhash ip saddr mod 2" will
not generate a random seed, instead, the seed will always be zero.

So if seed option is empty, we shoulde not set the NFTA_HASH_SEED
attribute, then a random seed will be generated in the kernel.

Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/expression.h
include/hash.h
src/hash.c
src/netlink_delinearize.c
src/netlink_linearize.c
src/parser_bison.y
tests/py/ip/hash.t
tests/py/ip/hash.t.payload

index 94573de087ad7ad3a5f0907a04ffddb4c6eb9ce7..9ba87e8273a3a71577dc2028c43140723bfc2b01 100644 (file)
@@ -310,6 +310,7 @@ struct expr {
                        /* EXPR_HASH */
                        struct expr             *expr;
                        uint32_t                mod;
+                       bool                    seed_set;
                        uint32_t                seed;
                        uint32_t                offset;
                        enum nft_hash_types     type;
index 7f9c6f13d45484adbadb25cf99e5b615dbc96f69..693d08a253039ff9d059159cc0b44082863186e7 100644 (file)
@@ -2,7 +2,9 @@
 #define NFTABLES_HASH_H
 
 extern struct expr *hash_expr_alloc(const struct location *loc,
-                                   uint32_t modulus, uint32_t seed,
-                                   uint32_t offset, enum nft_hash_types type);
+                                   uint32_t modulus,
+                                   bool seed_set, uint32_t seed,
+                                   uint32_t offset,
+                                   enum nft_hash_types type);
 
 #endif /* NFTABLES_HASH_H */
index bec1684e07e6e34671290e6f7add500bab18d1bc..c738d0b65616de8783a3c19f204a0bcaa48cdd50 100644 (file)
@@ -28,7 +28,7 @@ static void hash_expr_print(const struct expr *expr)
        }
 
        printf(" mod %u", expr->hash.mod);
-       if ((expr->hash.type == NFT_HASH_JENKINS) && expr->hash.seed)
+       if (expr->hash.seed_set)
                printf(" seed 0x%x", expr->hash.seed);
        if (expr->hash.offset)
                printf(" offset %u", expr->hash.offset);
@@ -39,6 +39,7 @@ static bool hash_expr_cmp(const struct expr *e1, const struct expr *e2)
        return (e1->hash.expr ||
                expr_cmp(e1->hash.expr, e2->hash.expr)) &&
               e1->hash.mod == e2->hash.mod &&
+              e1->hash.seed_set == e2->hash.seed_set &&
               e1->hash.seed == e2->hash.seed &&
               e1->hash.offset == e2->hash.offset &&
               e1->hash.type == e2->hash.type;
@@ -49,6 +50,7 @@ static void hash_expr_clone(struct expr *new, const struct expr *expr)
        if (expr->hash.expr)
                new->hash.expr = expr_clone(expr->hash.expr);
        new->hash.mod = expr->hash.mod;
+       new->hash.seed_set = expr->hash.seed_set;
        new->hash.seed = expr->hash.seed;
        new->hash.offset = expr->hash.offset;
        new->hash.type = expr->hash.type;
@@ -62,8 +64,10 @@ static const struct expr_ops hash_expr_ops = {
        .clone          = hash_expr_clone,
 };
 
-struct expr *hash_expr_alloc(const struct location *loc, uint32_t mod,
-                            uint32_t seed, uint32_t offset,
+struct expr *hash_expr_alloc(const struct location *loc,
+                            uint32_t mod,
+                            bool seed_set, uint32_t seed,
+                            uint32_t offset,
                             enum nft_hash_types type)
 {
        struct expr *expr;
@@ -71,6 +75,7 @@ struct expr *hash_expr_alloc(const struct location *loc, uint32_t mod,
        expr = expr_alloc(loc, &hash_expr_ops, &integer_type,
                          BYTEORDER_HOST_ENDIAN, 4 * BITS_PER_BYTE);
        expr->hash.mod  = mod;
+       expr->hash.seed_set = seed_set;
        expr->hash.seed = seed;
        expr->hash.offset = offset;
        expr->hash.type = type;
index 9ad1e2c681c6424eac1141040b5e467d06abde61..4a0b8dcc56516e4243e42417eb0928e728a51a2d 100644 (file)
@@ -525,13 +525,15 @@ static void netlink_parse_hash(struct netlink_parse_ctx *ctx,
        struct expr *expr, *hexpr;
        uint32_t mod, seed, len, offset;
        enum nft_hash_types type;
+       bool seed_set;
 
        type = nftnl_expr_get_u32(nle, NFTNL_EXPR_HASH_TYPE);
        offset = nftnl_expr_get_u32(nle, NFTNL_EXPR_HASH_OFFSET);
+       seed_set = nftnl_expr_is_set(nle, NFTNL_EXPR_HASH_SEED);
        seed = nftnl_expr_get_u32(nle, NFTNL_EXPR_HASH_SEED);
        mod  = nftnl_expr_get_u32(nle, NFTNL_EXPR_HASH_MODULUS);
 
-       expr = hash_expr_alloc(loc, mod, seed, offset, type);
+       expr = hash_expr_alloc(loc, mod, seed_set, seed, offset, type);
 
        if (type != NFT_HASH_SYM) {
                sreg = netlink_parse_register(nle, NFTNL_EXPR_HASH_SREG);
index b2f27b7a35855aaac4c6f655574407cc5670b45c..3d684569cabff61d885b68adb9702ea7d08c7aad 100644 (file)
@@ -139,7 +139,8 @@ static void netlink_gen_hash(struct netlink_linearize_ctx *ctx,
        }
        netlink_put_register(nle, NFTNL_EXPR_HASH_DREG, dreg);
        nftnl_expr_set_u32(nle, NFTNL_EXPR_HASH_MODULUS, expr->hash.mod);
-       nftnl_expr_set_u32(nle, NFTNL_EXPR_HASH_SEED, expr->hash.seed);
+       if (expr->hash.seed_set)
+               nftnl_expr_set_u32(nle, NFTNL_EXPR_HASH_SEED, expr->hash.seed);
        nftnl_expr_set_u32(nle, NFTNL_EXPR_HASH_OFFSET, expr->hash.offset);
        nftnl_expr_set_u32(nle, NFTNL_EXPR_HASH_TYPE, expr->hash.type);
        nftnl_rule_add_expr(ctx->nlr, nle);
index 9f993fd377882c4ed964050be802e53f1bc99d56..8db887a47d3e5a869220b341cea8b2540c57aca1 100644 (file)
@@ -520,7 +520,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 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 <val>                    nf_nat_flags nf_nat_flag offset_opt seed_opt
+%type <val>                    nf_nat_flags nf_nat_flag offset_opt
 %type <stmt>                   queue_stmt queue_stmt_alloc
 %destructor { stmt_free($$); } queue_stmt queue_stmt_alloc
 %type <val>                    queue_stmt_flags queue_stmt_flag
@@ -3092,18 +3092,19 @@ numgen_expr             :       NUMGEN  numgen_type     MOD     NUM     offset_opt
                        }
                        ;
 
-seed_opt               :       /* empty */     { $$ = 0; }
-                       |       SEED    NUM     { $$ = $2; }
-                       ;
-
-hash_expr              :       JHASH           expr    MOD     NUM     seed_opt        offset_opt
+hash_expr              :       JHASH           expr    MOD     NUM     SEED    NUM     offset_opt
+                       {
+                               $$ = hash_expr_alloc(&@$, $4, true, $6, $7, NFT_HASH_JENKINS);
+                               $$->hash.expr = $2;
+                       }
+                       |       JHASH           expr    MOD     NUM     offset_opt
                        {
-                               $$ = hash_expr_alloc(&@$, $4, $5, $6, NFT_HASH_JENKINS);
+                               $$ = hash_expr_alloc(&@$, $4, false, 0, $5, NFT_HASH_JENKINS);
                                $$->hash.expr = $2;
                        }
                        |       SYMHASH         MOD     NUM     offset_opt
                        {
-                               $$ = hash_expr_alloc(&@$, $3, 0, $4, NFT_HASH_SYM);
+                               $$ = hash_expr_alloc(&@$, $3, false, 0, $4, NFT_HASH_SYM);
                        }
                        ;
 
index 2becef6214e170769ac697ce5ab9c37aa32f6b88..cbfc7eefc02060ee5e89e8cdc34aa904d050cc26 100644 (file)
@@ -3,6 +3,7 @@
 
 ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef;ok
 ct mark set jhash ip saddr . ip daddr mod 2;ok
+ct mark set jhash ip saddr . ip daddr mod 2 seed 0x0;ok
 ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef offset 100;ok
 ct mark set jhash ip saddr . ip daddr mod 2 offset 100;ok
 dnat to jhash ip saddr mod 2 seed 0xdeadbeef map { 0 : 192.168.20.100, 1 : 192.168.30.100 };ok
index 21227e913a5cb3224cb4dd31f5c1dc9a83a7e80a..71ab06522a73098125839c8277758d3ac9deddae 100644 (file)
@@ -12,6 +12,13 @@ ip test-ip4 pre
   [ hash reg 1 = jhash(reg 2, 8, 0x0) % mod 2 ]
   [ ct set mark with reg 1 ]
 
+# ct mark set jhash ip saddr . ip daddr mod 2 seed 0x0
+ip test-ip4 pre
+  [ payload load 4b @ network header + 12 => reg 2 ]
+  [ payload load 4b @ network header + 16 => reg 13 ]
+  [ hash reg 1 = jhash(reg 2, 8, 0x0) % mod 2 ]
+  [ ct set mark with reg 1 ]
+
 # ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef offset 100
 ip test-ip4 pre
   [ payload load 4b @ network header + 12 => reg 2 ]