diff options
| author | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-10-13 18:06:06 -0400 |
|---|---|---|
| committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-10-14 12:00:04 -0400 |
| commit | 0ca743a5599199152a31a7146b83213c786c2eb2 (patch) | |
| tree | fd5cd87e1e1cf3f43d5868304c7c45f9bf11cef5 /include/net | |
| parent | 9370761c56b66aa5c65e069a7b010111a025018d (diff) | |
netfilter: nf_tables: add compatibility layer for x_tables
This patch adds the x_tables compatibility layer. This allows you
to use existing x_tables matches and targets from nf_tables.
This compatibility later allows us to use existing matches/targets
for features that are still missing in nf_tables. We can progressively
replace them with native nf_tables extensions. It also provides the
userspace compatibility software that allows you to express the
rule-set using the iptables syntax but using the nf_tables kernel
components.
In order to get this compatibility layer working, I've done the
following things:
* add NFNL_SUBSYS_NFT_COMPAT: this new nfnetlink subsystem is used
to query the x_tables match/target revision, so we don't need to
use the native x_table getsockopt interface.
* emulate xt structures: this required extending the struct nft_pktinfo
to include the fragment offset, which is already obtained from
ip[6]_tables and that is used by some matches/targets.
* add support for default policy to base chains, required to emulate
x_tables.
* add NFTA_CHAIN_USE attribute to obtain the number of references to
chains, required by x_tables emulation.
* add chain packet/byte counters using per-cpu.
* support 32-64 bits compat.
For historical reasons, this patch includes the following patches
that were posted in the netfilter-devel mailing list.
From Pablo Neira Ayuso:
* nf_tables: add default policy to base chains
* netfilter: nf_tables: add NFTA_CHAIN_USE attribute
* nf_tables: nft_compat: private data of target and matches in contiguous area
* nf_tables: validate hooks for compat match/target
* nf_tables: nft_compat: release cached matches/targets
* nf_tables: x_tables support as a compile time option
* nf_tables: fix alias for xtables over nftables module
* nf_tables: add packet and byte counters per chain
* nf_tables: fix per-chain counter stats if no counters are passed
* nf_tables: don't bump chain stats
* nf_tables: add protocol and flags for xtables over nf_tables
* nf_tables: add ip[6]t_entry emulation
* nf_tables: move specific layer 3 compat code to nf_tables_ipv[4|6]
* nf_tables: support 32bits-64bits x_tables compat
* nf_tables: fix compilation if CONFIG_COMPAT is disabled
From Patrick McHardy:
* nf_tables: move policy to struct nft_base_chain
* nf_tables: send notifications for base chain policy changes
From Alexander Primak:
* nf_tables: remove the duplicate NF_INET_LOCAL_OUT
From Nicolas Dichtel:
* nf_tables: fix compilation when nf-netlink is a module
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'include/net')
| -rw-r--r-- | include/net/netfilter/nf_tables.h | 44 | ||||
| -rw-r--r-- | include/net/netfilter/nf_tables_ipv4.h | 23 | ||||
| -rw-r--r-- | include/net/netfilter/nf_tables_ipv6.h | 30 |
3 files changed, 90 insertions, 7 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 8403f7f52e81..a68f45f0fe2e 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/list.h> | 4 | #include <linux/list.h> |
| 5 | #include <linux/netfilter.h> | 5 | #include <linux/netfilter.h> |
| 6 | #include <linux/netfilter/x_tables.h> | ||
| 6 | #include <linux/netfilter/nf_tables.h> | 7 | #include <linux/netfilter/nf_tables.h> |
| 7 | #include <net/netlink.h> | 8 | #include <net/netlink.h> |
| 8 | 9 | ||
| @@ -15,8 +16,23 @@ struct nft_pktinfo { | |||
| 15 | u8 hooknum; | 16 | u8 hooknum; |
| 16 | u8 nhoff; | 17 | u8 nhoff; |
| 17 | u8 thoff; | 18 | u8 thoff; |
| 19 | /* for x_tables compatibility */ | ||
| 20 | struct xt_action_param xt; | ||
| 18 | }; | 21 | }; |
| 19 | 22 | ||
| 23 | static inline void nft_set_pktinfo(struct nft_pktinfo *pkt, | ||
| 24 | const struct nf_hook_ops *ops, | ||
| 25 | struct sk_buff *skb, | ||
| 26 | const struct net_device *in, | ||
| 27 | const struct net_device *out) | ||
| 28 | { | ||
| 29 | pkt->skb = skb; | ||
| 30 | pkt->in = pkt->xt.in = in; | ||
| 31 | pkt->out = pkt->xt.out = out; | ||
| 32 | pkt->hooknum = pkt->xt.hooknum = ops->hooknum; | ||
| 33 | pkt->xt.family = ops->pf; | ||
| 34 | } | ||
| 35 | |||
| 20 | struct nft_data { | 36 | struct nft_data { |
| 21 | union { | 37 | union { |
| 22 | u32 data[4]; | 38 | u32 data[4]; |
| @@ -57,6 +73,7 @@ static inline void nft_data_debug(const struct nft_data *data) | |||
| 57 | * @afi: address family info | 73 | * @afi: address family info |
| 58 | * @table: the table the chain is contained in | 74 | * @table: the table the chain is contained in |
| 59 | * @chain: the chain the rule is contained in | 75 | * @chain: the chain the rule is contained in |
| 76 | * @nla: netlink attributes | ||
| 60 | */ | 77 | */ |
| 61 | struct nft_ctx { | 78 | struct nft_ctx { |
| 62 | const struct sk_buff *skb; | 79 | const struct sk_buff *skb; |
| @@ -64,6 +81,7 @@ struct nft_ctx { | |||
| 64 | const struct nft_af_info *afi; | 81 | const struct nft_af_info *afi; |
| 65 | const struct nft_table *table; | 82 | const struct nft_table *table; |
| 66 | const struct nft_chain *chain; | 83 | const struct nft_chain *chain; |
| 84 | const struct nlattr * const *nla; | ||
| 67 | }; | 85 | }; |
| 68 | 86 | ||
| 69 | struct nft_data_desc { | 87 | struct nft_data_desc { |
| @@ -235,7 +253,8 @@ extern void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, | |||
| 235 | * @maxattr: highest netlink attribute number | 253 | * @maxattr: highest netlink attribute number |
| 236 | */ | 254 | */ |
| 237 | struct nft_expr_type { | 255 | struct nft_expr_type { |
| 238 | const struct nft_expr_ops *(*select_ops)(const struct nlattr * const tb[]); | 256 | const struct nft_expr_ops *(*select_ops)(const struct nft_ctx *, |
| 257 | const struct nlattr * const tb[]); | ||
| 239 | const struct nft_expr_ops *ops; | 258 | const struct nft_expr_ops *ops; |
| 240 | struct list_head list; | 259 | struct list_head list; |
| 241 | const char *name; | 260 | const char *name; |
| @@ -253,6 +272,8 @@ struct nft_expr_type { | |||
| 253 | * @destroy: destruction function | 272 | * @destroy: destruction function |
| 254 | * @dump: function to dump parameters | 273 | * @dump: function to dump parameters |
| 255 | * @type: expression type | 274 | * @type: expression type |
| 275 | * @validate: validate expression, called during loop detection | ||
| 276 | * @data: extra data to attach to this expression operation | ||
| 256 | */ | 277 | */ |
| 257 | struct nft_expr; | 278 | struct nft_expr; |
| 258 | struct nft_expr_ops { | 279 | struct nft_expr_ops { |
| @@ -267,8 +288,11 @@ struct nft_expr_ops { | |||
| 267 | void (*destroy)(const struct nft_expr *expr); | 288 | void (*destroy)(const struct nft_expr *expr); |
| 268 | int (*dump)(struct sk_buff *skb, | 289 | int (*dump)(struct sk_buff *skb, |
| 269 | const struct nft_expr *expr); | 290 | const struct nft_expr *expr); |
| 270 | const struct nft_data * (*get_verdict)(const struct nft_expr *expr); | 291 | int (*validate)(const struct nft_ctx *ctx, |
| 292 | const struct nft_expr *expr, | ||
| 293 | const struct nft_data **data); | ||
| 271 | const struct nft_expr_type *type; | 294 | const struct nft_expr_type *type; |
| 295 | void *data; | ||
| 272 | }; | 296 | }; |
| 273 | 297 | ||
| 274 | #define NFT_EXPR_MAXATTR 16 | 298 | #define NFT_EXPR_MAXATTR 16 |
| @@ -368,16 +392,25 @@ enum nft_chain_type { | |||
| 368 | NFT_CHAIN_T_MAX | 392 | NFT_CHAIN_T_MAX |
| 369 | }; | 393 | }; |
| 370 | 394 | ||
| 395 | struct nft_stats { | ||
| 396 | u64 bytes; | ||
| 397 | u64 pkts; | ||
| 398 | }; | ||
| 399 | |||
| 371 | /** | 400 | /** |
| 372 | * struct nft_base_chain - nf_tables base chain | 401 | * struct nft_base_chain - nf_tables base chain |
| 373 | * | 402 | * |
| 374 | * @ops: netfilter hook ops | 403 | * @ops: netfilter hook ops |
| 375 | * @type: chain type | 404 | * @type: chain type |
| 405 | * @policy: default policy | ||
| 406 | * @stats: per-cpu chain stats | ||
| 376 | * @chain: the chain | 407 | * @chain: the chain |
| 377 | */ | 408 | */ |
| 378 | struct nft_base_chain { | 409 | struct nft_base_chain { |
| 379 | struct nf_hook_ops ops; | 410 | struct nf_hook_ops ops; |
| 380 | enum nft_chain_type type; | 411 | enum nft_chain_type type; |
| 412 | u8 policy; | ||
| 413 | struct nft_stats __percpu *stats; | ||
| 381 | struct nft_chain chain; | 414 | struct nft_chain chain; |
| 382 | }; | 415 | }; |
| 383 | 416 | ||
| @@ -386,11 +419,8 @@ static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chai | |||
| 386 | return container_of(chain, struct nft_base_chain, chain); | 419 | return container_of(chain, struct nft_base_chain, chain); |
| 387 | } | 420 | } |
| 388 | 421 | ||
| 389 | extern unsigned int nft_do_chain(const struct nf_hook_ops *ops, | 422 | extern unsigned int nft_do_chain_pktinfo(struct nft_pktinfo *pkt, |
| 390 | struct sk_buff *skb, | 423 | const struct nf_hook_ops *ops); |
| 391 | const struct net_device *in, | ||
| 392 | const struct net_device *out, | ||
| 393 | int (*okfn)(struct sk_buff *)); | ||
| 394 | 424 | ||
| 395 | /** | 425 | /** |
| 396 | * struct nft_table - nf_tables table | 426 | * struct nft_table - nf_tables table |
diff --git a/include/net/netfilter/nf_tables_ipv4.h b/include/net/netfilter/nf_tables_ipv4.h new file mode 100644 index 000000000000..1be1c2c197ee --- /dev/null +++ b/include/net/netfilter/nf_tables_ipv4.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #ifndef _NF_TABLES_IPV4_H_ | ||
| 2 | #define _NF_TABLES_IPV4_H_ | ||
| 3 | |||
| 4 | #include <net/netfilter/nf_tables.h> | ||
| 5 | #include <net/ip.h> | ||
| 6 | |||
| 7 | static inline void | ||
| 8 | nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, | ||
| 9 | const struct nf_hook_ops *ops, | ||
| 10 | struct sk_buff *skb, | ||
| 11 | const struct net_device *in, | ||
| 12 | const struct net_device *out) | ||
| 13 | { | ||
| 14 | struct iphdr *ip; | ||
| 15 | |||
| 16 | nft_set_pktinfo(pkt, ops, skb, in, out); | ||
| 17 | |||
| 18 | pkt->xt.thoff = ip_hdrlen(pkt->skb); | ||
| 19 | ip = ip_hdr(pkt->skb); | ||
| 20 | pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET; | ||
| 21 | } | ||
| 22 | |||
| 23 | #endif | ||
diff --git a/include/net/netfilter/nf_tables_ipv6.h b/include/net/netfilter/nf_tables_ipv6.h new file mode 100644 index 000000000000..4a9b88a65963 --- /dev/null +++ b/include/net/netfilter/nf_tables_ipv6.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #ifndef _NF_TABLES_IPV6_H_ | ||
| 2 | #define _NF_TABLES_IPV6_H_ | ||
| 3 | |||
| 4 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
| 5 | #include <net/ipv6.h> | ||
| 6 | |||
| 7 | static inline int | ||
| 8 | nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, | ||
| 9 | const struct nf_hook_ops *ops, | ||
| 10 | struct sk_buff *skb, | ||
| 11 | const struct net_device *in, | ||
| 12 | const struct net_device *out) | ||
| 13 | { | ||
| 14 | int protohdr, thoff = 0; | ||
| 15 | unsigned short frag_off; | ||
| 16 | |||
| 17 | nft_set_pktinfo(pkt, ops, skb, in, out); | ||
| 18 | |||
| 19 | protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL); | ||
| 20 | /* If malformed, drop it */ | ||
| 21 | if (protohdr < 0) | ||
| 22 | return -1; | ||
| 23 | |||
| 24 | pkt->xt.thoff = thoff; | ||
| 25 | pkt->xt.fragoff = frag_off; | ||
| 26 | |||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | |||
| 30 | #endif | ||
