summaryrefslogtreecommitdiffstats
path: root/iptables/nft-ipv6.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-ipv6.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-ipv6.c')
-rw-r--r--iptables/nft-ipv6.c45
1 files changed, 31 insertions, 14 deletions
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)