]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
ebtables: Fix among match
authorPhil Sutter <phil@nwl.cc>
Thu, 4 Aug 2022 15:01:26 +0000 (17:01 +0200)
committerPhil Sutter <phil@nwl.cc>
Wed, 28 Sep 2022 17:21:16 +0000 (19:21 +0200)
Fixed commit broke among match in two ways:

1) The two lookup sizes are 12 and 6, not 12 and 4 - among supports
   either ether+IP or ether only, not IP only.

2) Adding two to sreg_count to get the second register is too simple: It
   works only for four byte regs, not the 16 byte ones. The first
   register is always a 16 byte one, though.

Fixing (1) is trivial, fix (2) by introduction of nft_get_next_reg()
doing the right thing. For consistency, use it for among match creation,
too.

Fixes: f315af1cf8871 ("nft: track each register individually")
Signed-off-by: Phil Sutter <phil@nwl.cc>
iptables/nft-bridge.c
iptables/nft-shared.c
iptables/nft-shared.h
iptables/nft.c

index 659c5b58ba633e7056f4d6387fc33541dd3b66be..596dfdf8991f172369eca5d9f90fe04d0335523f 100644 (file)
@@ -349,7 +349,7 @@ static int lookup_analyze_payloads(struct nft_xt_ctx *ctx,
                        return -1;
                }
 
-               sreg_count += 2;
+               sreg_count = nft_get_next_reg(sreg_count, ETH_ALEN);
 
                reg = nft_xt_ctx_get_sreg(ctx, sreg_count);
                if (!reg) {
@@ -375,7 +375,7 @@ static int lookup_analyze_payloads(struct nft_xt_ctx *ctx,
                        return -1;
                }
                break;
-       case 4: /* ipv4addr */
+       case 6: /* ether */
                val = lookup_check_ether_payload(reg->payload.base,
                                                 reg->payload.offset,
                                                 reg->payload.len);
index f8de2b715dd610a82457fa00ded4c85651b6c033..909fe6483205c8cf3767988ef60034008e04f659 100644 (file)
@@ -10,6 +10,7 @@
  * This code has been sponsored by Sophos Astaro <http://www.sophos.com>
  */
 
+#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -1603,3 +1604,18 @@ int nft_parse_hl(struct nft_xt_ctx *ctx,
 
        return 0;
 }
+
+enum nft_registers nft_get_next_reg(enum nft_registers reg, size_t size)
+{
+       /* convert size to NETLINK_ALIGN-sized chunks */
+       size = (size + NETLINK_ALIGN - 1) / NETLINK_ALIGN;
+
+       /* map 16byte reg to 4byte one */
+       if (reg < __NFT_REG_MAX)
+               reg = NFT_REG32_00 + (reg - 1) * NFT_REG_SIZE / NFT_REG32_SIZE;
+
+       reg += size;
+       assert(reg <= NFT_REG32_15);
+
+       return reg;
+}
index 8fcedcdd78fbe9465d6745e2078e936d465b5cfe..c07d3270a407eac3c8c41d7bf90ce909f0281c93 100644 (file)
@@ -276,4 +276,9 @@ int nft_parse_hl(struct nft_xt_ctx *ctx, struct nftnl_expr *e, struct iptables_c
 #define min(x, y) ((x) < (y) ? (x) : (y))
 #define max(x, y) ((x) > (y) ? (x) : (y))
 
+/* simplified nftables:include/netlink.h, netlink_padded_len() */
+#define NETLINK_ALIGN          4
+
+enum nft_registers nft_get_next_reg(enum nft_registers reg, size_t size);
+
 #endif
index 2165733ff74e9c6870f0187b009745f53a2b13c4..09cb19c987322f58b75370d1e5857b21b306baa2 100644 (file)
@@ -1133,9 +1133,6 @@ gen_lookup(uint32_t sreg, const char *set_name, uint32_t set_id, uint32_t flags)
        return e;
 }
 
-/* simplified nftables:include/netlink.h, netlink_padded_len() */
-#define NETLINK_ALIGN          4
-
 /* from nftables:include/datatype.h, TYPE_BITS */
 #define CONCAT_TYPE_BITS       6
 
@@ -1208,8 +1205,9 @@ static int __add_nft_among(struct nft_handle *h, const char *table,
        nftnl_rule_add_expr(r, e);
 
        if (ip) {
+               reg = nft_get_next_reg(reg, ETH_ALEN);
                e = __gen_payload(NFT_PAYLOAD_NETWORK_HEADER, ip_addr_off[dst],
-                               sizeof(struct in_addr), NFT_REG32_02);
+                                 sizeof(struct in_addr), reg);
                if (!e)
                        return -ENOMEM;
                nftnl_rule_add_expr(r, e);