Message ID | 20151128132023.GC17106@macbook.localdomain |
---|---|
State | RFC |
Delegated to: | Pablo Neira |
Headers | show |
On Sat, Nov 28, 2015 at 01:20:23PM +0000, Patrick McHardy wrote: > On 28.11, Pablo Neira Ayuso wrote: > > I'm not working on the protocol definition problem: > > http://marc.info/?l=netfilter-devel&m=144862242521205&w=2, but I also > > need this gets fixed. Let me know if you will be looking into this, just > > to avoid overlap. > > It kinds of depends on the sub-byte handling, so we should get this done > first. Looking into this. > From my previous work on this I still have this patch, which allows you to > generate an rshift to get the payload to offset 0, then transfers it to the > LHS during binop simplification if its used in a relational expression. > > The upside is that is generic and reuses what we already have. I like the shift approach based on binop transfer. But I think this will not to cover this case, on IPv6 the DSCP field is split between two bytes. 4 bits 6 bits +-+-+-+-+-+-+-+-+-+-+ | vers | dscp | +-+-+-+-+-+-+-+-+-+-+ | 1st bytes | 2nd byte So 4 bit are on the 1st byte and 2 bit are placed on the second byte. I think this needs a binary-and to get rid of the bits that we dont need from the 1st and 2nd byte, in this case I'm not sure we can use your transfer trick. > The load masking should IMO not be done in eval but netlink_linearize. I think we can't handle the following case with this approach, eg. ip dscp & 0xf == 0xf then we get two bitwise in the code generation: payload bitwise bitwise cmp If we perform that transformation from the evaluation step, we can merge those two bitwise into one. > We don't even know yet if the payload expression is actually used in > a relational expression or f.i. in a statement, where handling needs > to be different. But these two cases, payload expression and statement, I think they need different handling both for evaluation and code generation. For payload statements, the bitwise will need to be retain the bits that we don't want to mangle, then inclusive-OR them with the value that we want to set, ie. r1 = payload(offset, base, len) r1 = bitwise(r1, AND, mask) r1 = bitwise(r1, OR, r2) payload_set(r1, ...) Cheers, Pablo -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/src/evaluate.c b/src/evaluate.c index b64c231..22d5601 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -463,6 +463,7 @@ static int constant_binop_simplify(struct eval_ctx *ctx, struct expr **expr) break; case OP_LSHIFT: assert(left->byteorder == BYTEORDER_HOST_ENDIAN); + mpz_set(val, left->value); mpz_lshift_ui(val, mpz_get_uint32(right->value)); mpz_and(val, val, mask); break; @@ -833,6 +834,8 @@ static int binop_can_transfer(struct eval_ctx *ctx, return expr_binary_error(ctx->msgs, right, left, "Comparison is always false"); return 1; + case OP_RSHIFT: + return 1; case OP_XOR: return 1; default: @@ -850,6 +853,10 @@ static int binop_transfer_one(struct eval_ctx *ctx, (*right) = binop_expr_alloc(&(*right)->location, OP_RSHIFT, *right, expr_get(left->right)); break; + case OP_RSHIFT: + (*right) = binop_expr_alloc(&(*right)->location, OP_LSHIFT, + *right, expr_get(left->right)); + break; case OP_XOR: (*right) = binop_expr_alloc(&(*right)->location, OP_XOR, *right, expr_get(left->right)); @@ -864,6 +871,7 @@ static int binop_transfer_one(struct eval_ctx *ctx, static int binop_transfer(struct eval_ctx *ctx, struct expr **expr) { struct expr *left = (*expr)->left, *i, *next; + unsigned int shift; int err; if (left->ops->type != EXPR_BINOP) @@ -895,10 +903,24 @@ static int binop_transfer(struct eval_ctx *ctx, struct expr **expr) return 0; } - left = expr_get((*expr)->left->left); - left->dtype = (*expr)->left->dtype; - expr_free((*expr)->left); - (*expr)->left = left; + switch (left->op) { + case OP_RSHIFT: + /* Mask out the bits the shift would have masked out */ + shift = mpz_get_uint8(left->right->value); + mpz_bitmask(left->right->value, left->left->len); + mpz_lshift_ui(left->right->value, shift); + left->op = OP_AND; + break; + case OP_LSHIFT: + case OP_XOR: + left = expr_get((*expr)->left->left); + left->dtype = (*expr)->left->dtype; + expr_free((*expr)->left); + (*expr)->left = left; + break; + default: + BUG("invalid binop operation %u", left->op); + } return 0; }