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>
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"
29 static void nft_ipv6_parse_meta(struct nft_xt_ctx
*ctx
,
30 const struct nft_xt_ctx_reg
*reg
,
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
;
44 if (parse_meta(ctx
, e
, reg
->meta_dreg
.key
, cs
->fw6
.ipv6
.iniface
,
45 cs
->fw6
.ipv6
.outiface
, &cs
->fw6
.ipv6
.invflags
) == 0)
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
,
60 struct iptables_command_state
*cs
)
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
));
71 parse_mask_ipv6(reg
, &cs
->fw6
.ipv6
.smsk
);
73 memset(&cs
->fw6
.ipv6
.smsk
, 0xff,
74 min(reg
->payload
.len
, sizeof(struct in6_addr
)));
77 cs
->fw6
.ipv6
.invflags
|= IP6T_INV_SRCIP
;
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
));
83 parse_mask_ipv6(reg
, &cs
->fw6
.ipv6
.dmsk
);
85 memset(&cs
->fw6
.ipv6
.dmsk
, 0xff,
86 min(reg
->payload
.len
, sizeof(struct in6_addr
)));
89 cs
->fw6
.ipv6
.invflags
|= IP6T_INV_DSTIP
;
91 case offsetof(struct ip6_hdr
, ip6_nxt
):
92 get_cmp_data(e
, &proto
, sizeof(proto
), &inv
);
93 cs
->fw6
.ipv6
.proto
= proto
;
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";
101 DEBUGP("unknown payload offset %d\n", reg
->payload
.offset
);
102 ctx
->errmsg
= "unknown payload offset";
107 struct nft_ruleparse_ops nft_ruleparse_ops_ipv6
= {
108 .meta
= nft_ipv6_parse_meta
,
109 .payload
= nft_ipv6_parse_payload
,