summaryrefslogtreecommitdiffstats
path: root/iptables/nft-shared.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2014-09-30 13:07:18 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2014-09-30 14:45:07 +0200
commit2c4a34c30cb4db93653dbd139e04f7df963c3a41 (patch)
tree17261327e3fb010eefe5e745e3ead71430363e9f /iptables/nft-shared.c
parent93ad9ea1b86bdaacffd8e33654abcea3d4e148b2 (diff)
iptables-compat: fix address prefix
This patch fixes: # iptables-compat -I INPUT -s 1.2.3.0/24 generates this bytecode: ip filter INPUT 20 [ payload load 4b @ network header + 12 => reg 1 ] [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ] [ cmp eq reg 1 0x00030201 ] [ counter pkts 0 bytes 0 ] and it displays: # iptables-compat-save ... -A INPUT -s 1.2.3.0/24 ip6tables-compat and arptables-compat are also fixed. This patch uses the new context structure to annotate payload, meta and bitwise, so it interprets the cmp expression based on the context. This provides a rudimentary way to delinearize the iptables-compat rule-set, but it should be enough for the built-in xtables selectors since we still use the xtables extensions. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'iptables/nft-shared.c')
-rw-r--r--iptables/nft-shared.c90
1 files changed, 58 insertions, 32 deletions
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 0a4b85a3..c22e83d3 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -82,6 +82,24 @@ void add_bitwise_u16(struct nft_rule *r, int mask, int xor)
nft_rule_add_expr(r, expr);
}
+static void add_bitwise(struct nft_rule *r, uint8_t *mask, size_t len)
+{
+ struct nft_rule_expr *expr;
+ uint32_t xor[4] = { 0 };
+
+ expr = nft_rule_expr_alloc("bitwise");
+ if (expr == NULL)
+ return;
+
+ nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_SREG, NFT_REG_1);
+ nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_DREG, NFT_REG_1);
+ nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_LEN, len);
+ nft_rule_expr_set(expr, NFT_EXPR_BITWISE_MASK, mask, len);
+ nft_rule_expr_set(expr, NFT_EXPR_BITWISE_XOR, &xor, len);
+
+ nft_rule_add_expr(r, expr);
+}
+
void add_cmp_ptr(struct nft_rule *r, uint32_t op, void *data, size_t len)
{
struct nft_rule_expr *expr;
@@ -151,11 +169,12 @@ void add_outiface(struct nft_rule *r, char *iface, int invflags)
}
void add_addr(struct nft_rule *r, int offset,
- void *data, size_t len, int invflags)
+ void *data, void *mask, size_t len, int invflags)
{
uint32_t op;
add_payload(r, offset, len);
+ add_bitwise(r, mask, len);
if (invflags & IPT_INV_SRCIP || invflags & IPT_INV_DSTIP)
op = NFT_CMP_NEQ;
@@ -298,8 +317,8 @@ void nft_parse_target(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
const void *targinfo = nft_rule_expr_get(e, NFT_EXPR_TG_INFO, &tg_len);
struct xtables_target *target;
struct xt_entry_target *t;
- struct nft_family_ops *ops;
size_t size;
+ struct nft_family_ops *ops;
void *data = nft_get_data(ctx);
target = xtables_find_target(targname, XTF_TRY_LOAD);
@@ -365,24 +384,11 @@ void print_proto(uint16_t proto, int invert)
printf("-p %u ", proto);
}
-void get_cmp_data(struct nft_rule_expr_iter *iter,
- void *data, size_t dlen, bool *inv)
+void get_cmp_data(struct nft_rule_expr *e, void *data, size_t dlen, bool *inv)
{
- struct nft_rule_expr *e;
- const char *name;
uint32_t len;
uint8_t op;
- e = nft_rule_expr_iter_next(iter);
- if (e == NULL)
- return;
-
- name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
- if (strcmp(name, "cmp") != 0) {
- DEBUGP("skipping no cmp after meta\n");
- return;
- }
-
memcpy(data, nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len), dlen);
op = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_OP);
if (op == NFT_CMP_NEQ)
@@ -393,33 +399,49 @@ void get_cmp_data(struct nft_rule_expr_iter *iter,
void nft_parse_meta(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
{
- uint8_t key = nft_rule_expr_get_u32(e, NFT_EXPR_META_KEY);
- struct nft_family_ops *ops = nft_family_ops_lookup(ctx->family);
- const char *name;
- void *data = nft_get_data(ctx);
+ ctx->reg = nft_rule_expr_get_u32(e, NFT_EXPR_META_DREG);
+ ctx->meta.key = nft_rule_expr_get_u32(e, NFT_EXPR_META_KEY);
+ ctx->flags |= NFT_XT_CTX_META;
+}
- e = nft_rule_expr_iter_next(ctx->iter);
- if (e == NULL)
- return;
+void nft_parse_payload(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
+{
+ ctx->reg = nft_rule_expr_get_u32(e, NFT_EXPR_META_DREG);
+ ctx->payload.offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
+ ctx->flags |= NFT_XT_CTX_PAYLOAD;
+}
+
+void nft_parse_bitwise(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
+{
+ uint32_t reg, len;
+ const void *data;
- name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
- if (strcmp(name, "cmp") != 0) {
- DEBUGP("skipping no cmp after meta\n");
+ reg = nft_rule_expr_get_u32(e, NFT_EXPR_BITWISE_SREG);
+ if (ctx->reg && reg != ctx->reg)
return;
- }
- ops->parse_meta(e, key, data);
+ data = nft_rule_expr_get(e, NFT_EXPR_BITWISE_XOR, &len);
+ memcpy(ctx->bitwise.xor, data, len);
+ data = nft_rule_expr_get(e, NFT_EXPR_BITWISE_MASK, &len);
+ memcpy(ctx->bitwise.mask, data, len);
+ ctx->flags |= NFT_XT_CTX_BITWISE;
}
-void nft_parse_payload(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
+void nft_parse_cmp(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
{
struct nft_family_ops *ops = nft_family_ops_lookup(ctx->family);
- uint32_t offset;
void *data = nft_get_data(ctx);
+ uint32_t reg;
- offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
+ reg = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_SREG);
+ if (ctx->reg && reg != ctx->reg)
+ return;
- ops->parse_payload(ctx->iter, offset, data);
+ if (ctx->flags & NFT_XT_CTX_META)
+ ops->parse_meta(ctx, e, data);
+ /* bitwise context is interpreted from payload */
+ if (ctx->flags & NFT_XT_CTX_PAYLOAD);
+ ops->parse_payload(ctx, e, data);
}
void nft_parse_counter(struct nft_rule_expr *e, struct xt_counters *counters)
@@ -486,6 +508,10 @@ void nft_rule_to_iptables_command_state(struct nft_rule *r,
nft_parse_payload(&ctx, expr);
else if (strcmp(name, "meta") == 0)
nft_parse_meta(&ctx, expr);
+ else if (strcmp(name, "bitwise") == 0)
+ nft_parse_bitwise(&ctx, expr);
+ else if (strcmp(name, "cmp") == 0)
+ nft_parse_cmp(&ctx, expr);
else if (strcmp(name, "immediate") == 0)
nft_parse_immediate(&ctx, expr);
else if (strcmp(name, "match") == 0)