From 2c4a34c30cb4db93653dbd139e04f7df963c3a41 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 30 Sep 2014 13:07:18 +0200 Subject: 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 --- iptables/nft-ipv6.c | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) (limited to 'iptables/nft-ipv6.c') diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c index 52de5b69..a70afcca 100644 --- a/iptables/nft-ipv6.c +++ b/iptables/nft-ipv6.c @@ -38,14 +38,16 @@ static int nft_ipv6_add(struct nft_rule *r, void *data) add_proto(r, offsetof(struct ip6_hdr, ip6_nxt), 1, cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags); - if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src)) + if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src)) { add_addr(r, offsetof(struct ip6_hdr, ip6_src), - &cs->fw6.ipv6.src, 16, cs->fw6.ipv6.invflags); - - if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst)) + &cs->fw6.ipv6.src, &cs->fw6.ipv6.smsk, + sizeof(struct in6_addr), cs->fw6.ipv6.invflags); + } + if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst)) { add_addr(r, offsetof(struct ip6_hdr, ip6_dst), - &cs->fw6.ipv6.dst, 16, cs->fw6.ipv6.invflags); - + &cs->fw6.ipv6.dst, &cs->fw6.ipv6.dmsk, + sizeof(struct in6_addr), cs->fw6.ipv6.invflags); + } add_compat(r, cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags); for (matchp = cs->matches; matchp; matchp = matchp->next) { @@ -87,39 +89,54 @@ static bool nft_ipv6_is_same(const void *data_a, b->fw6.ipv6.outiface_mask); } -static void nft_ipv6_parse_meta(struct nft_rule_expr *e, uint8_t key, +static void nft_ipv6_parse_meta(struct nft_xt_ctx *ctx, struct nft_rule_expr *e, void *data) { struct iptables_command_state *cs = data; - parse_meta(e, key, cs->fw6.ipv6.iniface, + parse_meta(e, ctx->meta.key, cs->fw6.ipv6.iniface, cs->fw6.ipv6.iniface_mask, cs->fw6.ipv6.outiface, cs->fw6.ipv6.outiface_mask, &cs->fw6.ipv6.invflags); } -static void nft_ipv6_parse_payload(struct nft_rule_expr_iter *iter, - uint32_t offset, void *data) +static void parse_mask_ipv6(struct nft_xt_ctx *ctx, struct in6_addr *mask) +{ + memcpy(mask, ctx->bitwise.mask, sizeof(struct in6_addr)); +} + +static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx, + struct nft_rule_expr *e, void *data) { struct iptables_command_state *cs = data; - switch (offset) { struct in6_addr addr; uint8_t proto; bool inv; + switch (ctx->payload.offset) { case offsetof(struct ip6_hdr, ip6_src): - get_cmp_data(iter, &addr, sizeof(addr), &inv); + get_cmp_data(e, &addr, sizeof(addr), &inv); memcpy(cs->fw6.ipv6.src.s6_addr, &addr, sizeof(addr)); + if (ctx->flags & NFT_XT_CTX_BITWISE) + parse_mask_ipv6(ctx, &cs->fw6.ipv6.smsk); + else + memset(&cs->fw.ip.smsk, 0xff, sizeof(struct in6_addr)); + if (inv) cs->fw6.ipv6.invflags |= IPT_INV_SRCIP; break; case offsetof(struct ip6_hdr, ip6_dst): - get_cmp_data(iter, &addr, sizeof(addr), &inv); + get_cmp_data(e, &addr, sizeof(addr), &inv); memcpy(cs->fw6.ipv6.dst.s6_addr, &addr, sizeof(addr)); + if (ctx->flags & NFT_XT_CTX_BITWISE) + parse_mask_ipv6(ctx, &cs->fw6.ipv6.dmsk); + else + memset(&cs->fw.ip.dmsk, 0xff, sizeof(struct in6_addr)); + if (inv) cs->fw6.ipv6.invflags |= IPT_INV_DSTIP; break; case offsetof(struct ip6_hdr, ip6_nxt): - get_cmp_data(iter, &proto, sizeof(proto), &inv); + get_cmp_data(e, &proto, sizeof(proto), &inv); cs->fw6.ipv6.flags |= IP6T_F_PROTO; cs->fw6.ipv6.proto = proto; if (inv) -- cgit v1.2.3