nft: Drop interface mask leftovers from post_parse callbacks
[iptables-mirror.git] / iptables / nft-ruleparse-ipv6.c
blob29b085802f76c391511c81984997020ca84d4768
1 /*
2 * (C) 2012-2014 by Pablo Neira Ayuso <pablo@netfilter.org>
3 * (C) 2013 by Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This code has been sponsored by Sophos Astaro <http://www.sophos.com>
13 #include <stddef.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <netdb.h>
18 #include <net/if.h>
19 #include <netinet/if_ether.h>
20 #include <netinet/ip6.h>
22 #include <libnftnl/rule.h>
23 #include <libnftnl/expr.h>
25 #include "nft-shared.h"
26 #include "nft-ruleparse.h"
27 #include "xshared.h"
29 static void nft_ipv6_parse_meta(struct nft_xt_ctx *ctx,
30 const struct nft_xt_ctx_reg *reg,
31 struct nftnl_expr *e,
32 struct iptables_command_state *cs)
34 switch (reg->meta_dreg.key) {
35 case NFT_META_L4PROTO:
36 cs->fw6.ipv6.proto = nftnl_expr_get_u8(e, NFTNL_EXPR_CMP_DATA);
37 if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
38 cs->fw6.ipv6.invflags |= XT_INV_PROTO;
39 return;
40 default:
41 break;
44 if (parse_meta(ctx, e, reg->meta_dreg.key, cs->fw6.ipv6.iniface,
45 cs->fw6.ipv6.outiface, &cs->fw6.ipv6.invflags) == 0)
46 return;
48 ctx->errmsg = "unknown ipv6 meta key";
51 static void parse_mask_ipv6(const struct nft_xt_ctx_reg *reg,
52 struct in6_addr *mask)
54 memcpy(mask, reg->bitwise.mask, sizeof(struct in6_addr));
57 static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
58 const struct nft_xt_ctx_reg *reg,
59 struct nftnl_expr *e,
60 struct iptables_command_state *cs)
62 struct in6_addr addr;
63 uint8_t proto;
64 bool inv;
66 switch (reg->payload.offset) {
67 case offsetof(struct ip6_hdr, ip6_src):
68 get_cmp_data(e, &addr, sizeof(addr), &inv);
69 memcpy(cs->fw6.ipv6.src.s6_addr, &addr, sizeof(addr));
70 if (reg->bitwise.set)
71 parse_mask_ipv6(reg, &cs->fw6.ipv6.smsk);
72 else
73 memset(&cs->fw6.ipv6.smsk, 0xff,
74 min(reg->payload.len, sizeof(struct in6_addr)));
76 if (inv)
77 cs->fw6.ipv6.invflags |= IP6T_INV_SRCIP;
78 break;
79 case offsetof(struct ip6_hdr, ip6_dst):
80 get_cmp_data(e, &addr, sizeof(addr), &inv);
81 memcpy(cs->fw6.ipv6.dst.s6_addr, &addr, sizeof(addr));
82 if (reg->bitwise.set)
83 parse_mask_ipv6(reg, &cs->fw6.ipv6.dmsk);
84 else
85 memset(&cs->fw6.ipv6.dmsk, 0xff,
86 min(reg->payload.len, sizeof(struct in6_addr)));
88 if (inv)
89 cs->fw6.ipv6.invflags |= IP6T_INV_DSTIP;
90 break;
91 case offsetof(struct ip6_hdr, ip6_nxt):
92 get_cmp_data(e, &proto, sizeof(proto), &inv);
93 cs->fw6.ipv6.proto = proto;
94 if (inv)
95 cs->fw6.ipv6.invflags |= IP6T_INV_PROTO;
96 case offsetof(struct ip6_hdr, ip6_hlim):
97 if (nft_parse_hl(ctx, e, cs) < 0)
98 ctx->errmsg = "invalid ttl field match";
99 break;
100 default:
101 DEBUGP("unknown payload offset %d\n", reg->payload.offset);
102 ctx->errmsg = "unknown payload offset";
103 break;
107 struct nft_ruleparse_ops nft_ruleparse_ops_ipv6 = {
108 .meta = nft_ipv6_parse_meta,
109 .payload = nft_ipv6_parse_payload,