]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
netlink: fix IPv6 prefix computation
authorEric Leblond <eric@regit.org>
Sun, 29 Sep 2013 09:53:28 +0000 (11:53 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 30 Sep 2013 10:51:03 +0000 (12:51 +0200)
The prefix building algorithm in netlink phase was incorrect in
IPv6.

For example, when adding the following rule
 nft add rule ip6 nat postrouting ip6 saddr 2::/64 --debug=all

we had:

 ip6 nat postrouting 0 0
  [ payload load 16b @ network header + 8 => reg 1 ]
  [ bitwise reg 1 = (reg=1 & 0x00000000 0x99361540 0x00007f8d 0x2e33a1eb ) ^ 0x00000000 0x00000000 0x00000000 0x00000000 ]
  [ cmp eq reg 1 0x00000200 0x00000000 0x00000000 0x00000000 ]

With the patch the result is as expected:

 ip6 nat postrouting 0 0
  [ payload load 16b @ network header + 8 => reg 1 ]
  [ bitwise reg 1 = (reg=1 & 0xffffffff 0xffffffff 0x00000000 0x00000000 ) ^ 0x00000000 0x00000000 0x00000000 0x00000000 ]
  [ cmp eq reg 1 0x00000200 0x00000000 0x00000000 0x00000000 ]

Signed-off-by: Eric Leblond <eric@regit.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/netlink.c

index c48e667b493ccb868980ec72aa3cbbfdacf7b88c..b1e44ad05dccc307d8282ac101fa4ea6cfea624b 100644 (file)
@@ -234,7 +234,8 @@ static void netlink_gen_verdict(const struct expr *expr,
 static void netlink_gen_prefix(const struct expr *expr,
                               struct nft_data_linearize *data)
 {
-       uint32_t i, cidr, idx;
+       uint32_t idx;
+       int32_t i, cidr;
        uint32_t mask;
 
        assert(expr->ops->type == EXPR_PREFIX);
@@ -242,11 +243,13 @@ static void netlink_gen_prefix(const struct expr *expr,
        data->len = div_round_up(expr->prefix->len, BITS_PER_BYTE);
        cidr = expr->prefix_len;
 
-       for (i = 0; i < data->len; i+= 32) {
+       for (i = 0; (uint32_t)i / BITS_PER_BYTE < data->len; i += 32) {
                if (cidr - i >= 32)
-                       mask = 0;
+                       mask = 0xffffffff;
+               else if (cidr - i > 0)
+                       mask = (1 << (cidr - i)) - 1;
                else
-                       mask = (1 << cidr) - 1;
+                       mask = 0;
 
                idx = i / 32;
                data->value[idx] = mask;