]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
nft: Optimize class-based IP prefix matches
authorPhil Sutter <phil@nwl.cc>
Fri, 2 Oct 2020 07:44:38 +0000 (09:44 +0200)
committerPhil Sutter <phil@nwl.cc>
Wed, 4 Nov 2020 14:39:23 +0000 (15:39 +0100)
Payload expression works on byte-boundaries, leverage this with suitable
prefix lengths.

Signed-off-by: Phil Sutter <phil@nwl.cc>
iptables/nft-arp.c
iptables/nft-ipv4.c
iptables/nft-ipv6.c
iptables/nft-shared.c
iptables/nft-shared.h

index 67f4529d93652915e72f29ed2ac40556e53bf60e..952f0c6916e59008d70ad493ea31d1c33667a2e1 100644 (file)
@@ -303,7 +303,8 @@ static bool nft_arp_parse_devaddr(struct nft_xt_ctx *ctx,
                memcpy(info->mask, ctx->bitwise.mask, ETH_ALEN);
                ctx->flags &= ~NFT_XT_CTX_BITWISE;
        } else {
-               memset(info->mask, 0xff, ETH_ALEN);
+               memset(info->mask, 0xff,
+                      min(ctx->payload.len, ETH_ALEN));
        }
 
        return inv;
@@ -360,7 +361,9 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
                                parse_mask_ipv4(ctx, &fw->arp.smsk);
                                ctx->flags &= ~NFT_XT_CTX_BITWISE;
                        } else {
-                               fw->arp.smsk.s_addr = 0xffffffff;
+                               memset(&fw->arp.smsk, 0xff,
+                                      min(ctx->payload.len,
+                                          sizeof(struct in_addr)));
                        }
 
                        if (inv)
@@ -380,7 +383,9 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
                                parse_mask_ipv4(ctx, &fw->arp.tmsk);
                                ctx->flags &= ~NFT_XT_CTX_BITWISE;
                        } else {
-                               fw->arp.tmsk.s_addr = 0xffffffff;
+                               memset(&fw->arp.tmsk, 0xff,
+                                      min(ctx->payload.len,
+                                          sizeof(struct in_addr)));
                        }
 
                        if (inv)
index afdecf9711e647aa6e3d8a20c3eac54c6f24c928..ce702041af0f41bb1c80039940c4098e61ae11d9 100644 (file)
@@ -199,7 +199,8 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
                        parse_mask_ipv4(ctx, &cs->fw.ip.smsk);
                        ctx->flags &= ~NFT_XT_CTX_BITWISE;
                } else {
-                       cs->fw.ip.smsk.s_addr = 0xffffffff;
+                       memset(&cs->fw.ip.smsk, 0xff,
+                              min(ctx->payload.len, sizeof(struct in_addr)));
                }
 
                if (inv)
@@ -212,7 +213,8 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
                        parse_mask_ipv4(ctx, &cs->fw.ip.dmsk);
                        ctx->flags &= ~NFT_XT_CTX_BITWISE;
                } else {
-                       cs->fw.ip.dmsk.s_addr = 0xffffffff;
+                       memset(&cs->fw.ip.dmsk, 0xff,
+                              min(ctx->payload.len, sizeof(struct in_addr)));
                }
 
                if (inv)
index 4008b7eab4f2a01dc56db7e726dacc68cd724d42..c877ec6d108877acef6cbf11134b92bf55d0c879 100644 (file)
@@ -146,7 +146,8 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
                        parse_mask_ipv6(ctx, &cs->fw6.ipv6.smsk);
                        ctx->flags &= ~NFT_XT_CTX_BITWISE;
                } else {
-                       memset(&cs->fw6.ipv6.smsk, 0xff, sizeof(struct in6_addr));
+                       memset(&cs->fw6.ipv6.smsk, 0xff,
+                              min(ctx->payload.len, sizeof(struct in6_addr)));
                }
 
                if (inv)
@@ -159,7 +160,8 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
                        parse_mask_ipv6(ctx, &cs->fw6.ipv6.dmsk);
                        ctx->flags &= ~NFT_XT_CTX_BITWISE;
                } else {
-                       memset(&cs->fw6.ipv6.dmsk, 0xff, sizeof(struct in6_addr));
+                       memset(&cs->fw6.ipv6.dmsk, 0xff,
+                              min(ctx->payload.len, sizeof(struct in6_addr)));
                }
 
                if (inv)
index 7741d23befc5af99a79a015595d6427b7c2257a1..545e9c60fa015ce9911aa55e3e0d468120b92982 100644 (file)
@@ -166,16 +166,22 @@ void add_addr(struct nftnl_rule *r, int offset,
              void *data, void *mask, size_t len, uint32_t op)
 {
        const unsigned char *m = mask;
+       bool bitwise = false;
        int i;
 
-       add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
-
        for (i = 0; i < len; i++) {
-               if (m[i] != 0xff)
+               if (m[i] != 0xff) {
+                       bitwise = m[i] != 0;
                        break;
+               }
        }
 
-       if (i != len)
+       if (!bitwise)
+               len = i;
+
+       add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
+
+       if (bitwise)
                add_bitwise(r, mask, len);
 
        add_cmp_ptr(r, op, data, len);
index 4440fd17bfeac22ff9f6229df21d3cb2270e3d9a..a52463342b30a31d13533b9b5b21a4f416486ac2 100644 (file)
@@ -247,4 +247,8 @@ void xtables_restore_parse(struct nft_handle *h,
                           const struct nft_xt_restore_parse *p);
 
 void nft_check_xt_legacy(int family, bool is_ipt_save);
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+#define max(x, y) ((x) > (y) ? (x) : (y))
+
 #endif