This patch adds a new table family and a new filter chain that you can use to attach IPv4 and IPv6 rules. This should help to simplify rule-set maintainance in dual-stack setups.
Unified · Split
| @@ -20,4 +20,6 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, · 19 unmodified lines | ||
| 20 | 20 | pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET; |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | +extern struct nft_af_info nft_af_ipv4; | |
| 24 | + | |
| 23 | 25 | #endif |
| @@ -27,4 +27,6 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, · 26 unmodified lines | ||
| 27 | 27 | return 0; |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | +extern struct nft_af_info nft_af_ipv6; | |
| 31 | + | |
| 30 | 32 | #endif |
| @@ -10,6 +10,7 @@ struct netns_nftables { · 9 unmodified lines | ||
| 10 | 10 | struct list_head commit_list; |
| 11 | 11 | struct nft_af_info *ipv4; |
| 12 | 12 | struct nft_af_info *ipv6; |
| 13 | + struct nft_af_info *inet; | |
| 13 | 14 | struct nft_af_info *arp; |
| 14 | 15 | struct nft_af_info *bridge; |
| 15 | 16 | u8 gencursor; |
| @@ -53,6 +53,7 @@ enum nf_inet_hooks { · 52 unmodified lines | ||
| 53 | 53 | |
| 54 | 54 | enum { |
| 55 | 55 | NFPROTO_UNSPEC = 0, |
| 56 | + NFPROTO_INET = 1, | |
| 56 | 57 | NFPROTO_IPV4 = 2, |
| 57 | 58 | NFPROTO_ARP = 3, |
| 58 | 59 | NFPROTO_BRIDGE = 7, |
| @@ -48,7 +48,7 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops, · 47 unmodified lines | ||
| 48 | 48 | return nft_do_chain_ipv4(ops, skb, in, out, okfn); |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | −static struct nft_af_info nft_af_ipv4 __read_mostly = { | |
| 51 | +struct nft_af_info nft_af_ipv4 __read_mostly = { | |
| 52 | 52 | .family = NFPROTO_IPV4, |
| 53 | 53 | .nhooks = NF_INET_NUMHOOKS, |
| 54 | 54 | .owner = THIS_MODULE, |
| @@ -61,6 +61,7 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = { · 6 unmodified lines | ||
| 61 | 61 | [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, |
| 62 | 62 | }, |
| 63 | 63 | }; |
| 64 | +EXPORT_SYMBOL_GPL(nft_af_ipv4); | |
| 64 | 65 | |
| 65 | 66 | static int nf_tables_ipv4_init_net(struct net *net) |
| 66 | 67 | { |
| @@ -47,7 +47,7 @@ static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops, · 46 unmodified lines | ||
| 47 | 47 | return nft_do_chain_ipv6(ops, skb, in, out, okfn); |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | −static struct nft_af_info nft_af_ipv6 __read_mostly = { | |
| 50 | +struct nft_af_info nft_af_ipv6 __read_mostly = { | |
| 51 | 51 | .family = NFPROTO_IPV6, |
| 52 | 52 | .nhooks = NF_INET_NUMHOOKS, |
| 53 | 53 | .owner = THIS_MODULE, |
| @@ -60,6 +60,7 @@ static struct nft_af_info nft_af_ipv6 __read_mostly = { · 6 unmodified lines | ||
| 60 | 60 | [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, |
| 61 | 61 | }, |
| 62 | 62 | }; |
| 63 | +EXPORT_SYMBOL_GPL(nft_af_ipv6); | |
| 63 | 64 | |
| 64 | 65 | static int nf_tables_ipv6_init_net(struct net *net) |
| 65 | 66 | { |
| @@ -428,6 +428,14 @@ config NF_TABLES · 427 unmodified lines | ||
| 428 | 428 | |
| 429 | 429 | To compile it as a module, choose M here. |
| 430 | 430 | |
| 431 | +config NF_TABLES_INET | |
| 432 | + depends on NF_TABLES | |
| 433 | + select NF_TABLES_IPV4 | |
| 434 | + select NF_TABLES_IPV6 | |
| 435 | + tristate "Netfilter nf_tables mixed IPv4/IPv6 tables support" | |
| 436 | + help | |
| 437 | + This option enables support for a mixed IPv4/IPv6 "inet" table. | |
| 438 | + | |
| 431 | 439 | config NFT_EXTHDR |
| 432 | 440 | depends on NF_TABLES |
| 433 | 441 | tristate "Netfilter nf_tables IPv6 exthdr module" |
| @@ -70,6 +70,7 @@ nf_tables-objs += nft_immediate.o nft_cmp.o nft_lookup.o · 69 unmodified lines | ||
| 70 | 70 | nf_tables-objs += nft_bitwise.o nft_byteorder.o nft_payload.o |
| 71 | 71 | |
| 72 | 72 | obj-$(CONFIG_NF_TABLES) += nf_tables.o |
| 73 | +obj-$(CONFIG_NF_TABLES_INET) += nf_tables_inet.o | |
| 73 | 74 | obj-$(CONFIG_NFT_COMPAT) += nft_compat.o |
| 74 | 75 | obj-$(CONFIG_NFT_EXTHDR) += nft_exthdr.o |
| 75 | 76 | obj-$(CONFIG_NFT_META) += nft_meta.o |
| @@ -0,0 +1,97 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2012-2014 Patrick McHardy <kaber@trash.net> | |
| 3 | + * | |
| 4 | + * This program is free software; you can redistribute it and/or modify | |
| 5 | + * it under the terms of the GNU General Public License version 2 as | |
| 6 | + * published by the Free Software Foundation. | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#include <linux/init.h> | |
| 10 | +#include <linux/module.h> | |
| 11 | +#include <linux/ip.h> | |
| 12 | +#include <linux/netfilter_ipv4.h> | |
| 13 | +#include <linux/netfilter_ipv6.h> | |
| 14 | +#include <net/netfilter/nf_tables.h> | |
| 15 | +#include <net/netfilter/nf_tables_ipv4.h> | |
| 16 | +#include <net/netfilter/nf_tables_ipv6.h> | |
| 17 | +#include <net/ip.h> | |
| 18 | + | |
| 19 | +static void nft_inet_hook_ops_init(struct nf_hook_ops *ops, unsigned int n) | |
| 20 | +{ | |
| 21 | + struct nft_af_info *afi; | |
| 22 | + | |
| 23 | + if (n == 1) | |
| 24 | + afi = &nft_af_ipv4; | |
| 25 | + else | |
| 26 | + afi = &nft_af_ipv6; | |
| 27 | + | |
| 28 | + ops->pf = afi->family; | |
| 29 | + if (afi->hooks[ops->hooknum]) | |
| 30 | + ops->hook = afi->hooks[ops->hooknum]; | |
| 31 | +} | |
| 32 | + | |
| 33 | +static struct nft_af_info nft_af_inet __read_mostly = { | |
| 34 | + .family = NFPROTO_INET, | |
| 35 | + .nhooks = NF_INET_NUMHOOKS, | |
| 36 | + .owner = THIS_MODULE, | |
| 37 | + .nops = 2, | |
| 38 | + .hook_ops_init = nft_inet_hook_ops_init, | |
| 39 | +}; | |
| 40 | + | |
| 41 | +static int __net_init nf_tables_inet_init_net(struct net *net) | |
| 42 | +{ | |
| 43 | + net->nft.inet = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); | |
| 44 | + if (net->nft.inet == NULL) | |
| 45 | + return -ENOMEM; | |
| 46 | + memcpy(net->nft.inet, &nft_af_inet, sizeof(nft_af_inet)); | |
| 47 | + | |
| 48 | + if (nft_register_afinfo(net, net->nft.inet) < 0) | |
| 49 | + goto err; | |
| 50 | + | |
| 51 | + return 0; | |
| 52 | + | |
| 53 | +err: | |
| 54 | + kfree(net->nft.inet); | |
| 55 | + return -ENOMEM; | |
| 56 | +} | |
| 57 | + | |
| 58 | +static void __net_exit nf_tables_inet_exit_net(struct net *net) | |
| 59 | +{ | |
| 60 | + nft_unregister_afinfo(net->nft.inet); | |
| 61 | + kfree(net->nft.inet); | |
| 62 | +} | |
| 63 | + | |
| 64 | +static struct pernet_operations nf_tables_inet_net_ops = { | |
| 65 | + .init = nf_tables_inet_init_net, | |
| 66 | + .exit = nf_tables_inet_exit_net, | |
| 67 | +}; | |
| 68 | + | |
| 69 | +static struct nf_chain_type filter_inet = { | |
| 70 | + .family = NFPROTO_INET, | |
| 71 | + .name = "filter", | |
| 72 | + .type = NFT_CHAIN_T_DEFAULT, | |
| 73 | + .hook_mask = (1 << NF_INET_LOCAL_IN) | | |
| 74 | + (1 << NF_INET_LOCAL_OUT) | | |
| 75 | + (1 << NF_INET_FORWARD) | | |
| 76 | + (1 << NF_INET_PRE_ROUTING) | | |
| 77 | + (1 << NF_INET_POST_ROUTING), | |
| 78 | +}; | |
| 79 | + | |
| 80 | +static int __init nf_tables_inet_init(void) | |
| 81 | +{ | |
| 82 | + nft_register_chain_type(&filter_inet); | |
| 83 | + return register_pernet_subsys(&nf_tables_inet_net_ops); | |
| 84 | +} | |
| 85 | + | |
| 86 | +static void __exit nf_tables_inet_exit(void) | |
| 87 | +{ | |
| 88 | + unregister_pernet_subsys(&nf_tables_inet_net_ops); | |
| 89 | + nft_unregister_chain_type(&filter_inet); | |
| 90 | +} | |
| 91 | + | |
| 92 | +module_init(nf_tables_inet_init); | |
| 93 | +module_exit(nf_tables_inet_exit); | |
| 94 | + | |
| 95 | +MODULE_LICENSE("GPL"); | |
| 96 | +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | |
| 97 | +MODULE_ALIAS_NFT_FAMILY(1); | |