]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: Support odd-sized payload matches
authorPhil Sutter <phil@nwl.cc>
Tue, 27 Oct 2020 16:05:25 +0000 (17:05 +0100)
committerPhil Sutter <phil@nwl.cc>
Wed, 4 Nov 2020 13:44:02 +0000 (14:44 +0100)
When expanding a payload match, don't disregard oversized templates at
the right offset. A more flexible user may extract less bytes from the
packet if only parts of a field are interesting, e.g. only the prefix of
source/destination address. Support that by using the template, but fix
the length. Later when creating a relational expression for it, detect
the unusually small payload expression length and turn the RHS value
into a prefix expression.

Signed-off-by: Phil Sutter <phil@nwl.cc>
src/netlink_delinearize.c
src/payload.c

index 43d7ff821504d08c8e8753d99ef99011922f58bb..b7876a8da83755fdecab7b2508f752c8dec527c7 100644 (file)
@@ -1776,6 +1776,12 @@ static void payload_match_expand(struct rule_pp_ctx *ctx,
                tmp = constant_expr_splice(right, left->len);
                expr_set_type(tmp, left->dtype, left->byteorder);
 
+               if (left->payload.tmpl && (left->len < left->payload.tmpl->len)) {
+                       mpz_lshift_ui(tmp->value, left->payload.tmpl->len - left->len);
+                       tmp->len = left->payload.tmpl->len;
+                       tmp = prefix_expr_alloc(&tmp->location, tmp, left->len);
+               }
+
                nexpr = relational_expr_alloc(&expr->location, expr->op,
                                              left, tmp);
                if (expr->op == OP_EQ)
index ca422d5bcd561d67a52791e1ed8f9300e179ede0..e51c5797c589ac325a7a1bf4e0bd8da213cd4bfc 100644 (file)
@@ -822,6 +822,11 @@ void payload_expr_expand(struct list_head *list, struct expr *expr,
                        expr->payload.offset += tmpl->len;
                        if (expr->len == 0)
                                return;
+               } else if (expr->len > 0) {
+                       new = payload_expr_alloc(&expr->location, desc, i);
+                       new->len = expr->len;
+                       list_add_tail(&new->list, list);
+                       return;
                } else
                        break;
        }