From 9370761c56b66aa5c65e069a7b010111a025018d Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 10 Oct 2013 23:21:26 +0200 Subject: netfilter: nf_tables: convert built-in tables/chains to chain types This patch converts built-in tables/chains to chain types that allows you to deploy customized table and chain configurations from userspace. After this patch, you have to specify the chain type when creating a new chain: add chain ip filter output { type filter hook input priority 0; } ^^^^ ------ The existing chain types after this patch are: filter, route and nat. Note that tables are just containers of chains with no specific semantics, which is a significant change with regards to iptables. Signed-off-by: Pablo Neira Ayuso --- net/ipv6/netfilter/Kconfig | 4 +- net/ipv6/netfilter/Makefile | 2 +- net/ipv6/netfilter/nf_table_route_ipv6.c | 93 ------------------------------- net/ipv6/netfilter/nf_tables_ipv6.c | 22 +++++++- net/ipv6/netfilter/nft_chain_route_ipv6.c | 82 +++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 97 deletions(-) delete mode 100644 net/ipv6/netfilter/nf_table_route_ipv6.c create mode 100644 net/ipv6/netfilter/nft_chain_route_ipv6.c (limited to 'net/ipv6') diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 5677e38eeca3..23833064b7b5 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -29,9 +29,9 @@ config NF_TABLES_IPV6 depends on NF_TABLES tristate "IPv6 nf_tables support" -config NF_TABLE_ROUTE_IPV6 +config NFT_CHAIN_ROUTE_IPV6 depends on NF_TABLES_IPV6 - tristate "IPv6 nf_tables route table support" + tristate "IPv6 nf_tables route chain support" config IP6_NF_IPTABLES tristate "IP6 tables support (required for filtering)" diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 956af4492d10..be4913aa524d 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile @@ -25,7 +25,7 @@ obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o # nf_tables obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o -obj-$(CONFIG_NF_TABLE_ROUTE_IPV6) += nf_table_route_ipv6.o +obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o # matches obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o diff --git a/net/ipv6/netfilter/nf_table_route_ipv6.c b/net/ipv6/netfilter/nf_table_route_ipv6.c deleted file mode 100644 index 48ac65c7b398..000000000000 --- a/net/ipv6/netfilter/nf_table_route_ipv6.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2008 Patrick McHardy - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Development of this code funded by Astaro AG (http://www.astaro.com/) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - unsigned int ret; - struct in6_addr saddr, daddr; - u_int8_t hop_limit; - u32 mark, flowlabel; - - /* save source/dest address, mark, hoplimit, flowlabel, priority */ - memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr)); - memcpy(&daddr, &ipv6_hdr(skb)->daddr, sizeof(daddr)); - mark = skb->mark; - hop_limit = ipv6_hdr(skb)->hop_limit; - - /* flowlabel and prio (includes version, which shouldn't change either */ - flowlabel = *((u32 *)ipv6_hdr(skb)); - - ret = nft_do_chain(ops, skb, in, out, okfn); - if (ret != NF_DROP && ret != NF_QUEUE && - (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) || - memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) || - skb->mark != mark || - ipv6_hdr(skb)->hop_limit != hop_limit || - flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) - return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP; - - return ret; -} - -static struct nft_base_chain nf_chain_route_output __read_mostly = { - .chain = { - .name = "OUTPUT", - .rules = LIST_HEAD_INIT(nf_chain_route_output.chain.rules), - .flags = NFT_BASE_CHAIN | NFT_CHAIN_BUILTIN, - }, - .ops = { - .hook = nf_route_table_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_LOCAL_OUT, - .priority = NF_IP6_PRI_MANGLE, - .priv = &nf_chain_route_output.chain, - }, -}; - -static struct nft_table nf_table_route_ipv6 __read_mostly = { - .name = "route", - .chains = LIST_HEAD_INIT(nf_table_route_ipv6.chains), -}; - -static int __init nf_table_route_init(void) -{ - list_add_tail(&nf_chain_route_output.chain.list, - &nf_table_route_ipv6.chains); - return nft_register_table(&nf_table_route_ipv6, NFPROTO_IPV6); -} - -static void __exit nf_table_route_exit(void) -{ - nft_unregister_table(&nf_table_route_ipv6, NFPROTO_IPV6); -} - -module_init(nf_table_route_init); -module_exit(nf_table_route_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Patrick McHardy "); -MODULE_ALIAS_NFT_TABLE(AF_INET6, "route"); diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c index e0717cea4913..3631d6238e6f 100644 --- a/net/ipv6/netfilter/nf_tables_ipv6.c +++ b/net/ipv6/netfilter/nf_tables_ipv6.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2008 Patrick McHardy + * Copyright (c) 2012-2013 Pablo Neira Ayuso * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -39,14 +40,33 @@ static struct nft_af_info nft_af_ipv6 __read_mostly = { }, }; +static struct nf_chain_type filter_ipv6 = { + .family = NFPROTO_IPV6, + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, + .hook_mask = (1 << NF_INET_LOCAL_IN) | + (1 << NF_INET_LOCAL_OUT) | + (1 << NF_INET_FORWARD) | + (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_POST_ROUTING), + .fn = { + [NF_INET_LOCAL_IN] = nft_do_chain, + [NF_INET_LOCAL_OUT] = nft_do_chain, + [NF_INET_FORWARD] = nft_do_chain, + [NF_INET_PRE_ROUTING] = nft_do_chain, + [NF_INET_POST_ROUTING] = nft_do_chain, + }, +}; + static int __init nf_tables_ipv6_init(void) { + nft_register_chain_type(&filter_ipv6); return nft_register_afinfo(&nft_af_ipv6); } - static void __exit nf_tables_ipv6_exit(void) { nft_unregister_afinfo(&nft_af_ipv6); + nft_unregister_chain_type(&filter_ipv6); } module_init(nf_tables_ipv6_init); diff --git a/net/ipv6/netfilter/nft_chain_route_ipv6.c b/net/ipv6/netfilter/nft_chain_route_ipv6.c new file mode 100644 index 000000000000..4cdc992fa067 --- /dev/null +++ b/net/ipv6/netfilter/nft_chain_route_ipv6.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2008 Patrick McHardy + * Copyright (c) 2012 Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, + struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + unsigned int ret; + struct in6_addr saddr, daddr; + u_int8_t hop_limit; + u32 mark, flowlabel; + + /* save source/dest address, mark, hoplimit, flowlabel, priority */ + memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr)); + memcpy(&daddr, &ipv6_hdr(skb)->daddr, sizeof(daddr)); + mark = skb->mark; + hop_limit = ipv6_hdr(skb)->hop_limit; + + /* flowlabel and prio (includes version, which shouldn't change either */ + flowlabel = *((u32 *)ipv6_hdr(skb)); + + ret = nft_do_chain(ops, skb, in, out, okfn); + if (ret != NF_DROP && ret != NF_QUEUE && + (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) || + memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) || + skb->mark != mark || + ipv6_hdr(skb)->hop_limit != hop_limit || + flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) + return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP; + + return ret; +} + +static struct nf_chain_type nft_chain_route_ipv6 = { + .family = NFPROTO_IPV6, + .name = "route", + .type = NFT_CHAIN_T_ROUTE, + .hook_mask = (1 << NF_INET_LOCAL_OUT), + .fn = { + [NF_INET_LOCAL_OUT] = nf_route_table_hook, + }, + .me = THIS_MODULE, +}; + +static int __init nft_chain_route_init(void) +{ + return nft_register_chain_type(&nft_chain_route_ipv6); +} + +static void __exit nft_chain_route_exit(void) +{ + nft_unregister_chain_type(&nft_chain_route_ipv6); +} + +module_init(nft_chain_route_init); +module_exit(nft_chain_route_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick McHardy "); +MODULE_ALIAS_NFT_CHAIN(AF_INET6, "route"); -- cgit v1.2.3