Commit 4c38cd61aef20fce34c669caa901634ca5f88bf8

Authored by David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter/IPVS updates for net-next

The following patchset contains Netfilter updates for your net-next tree,
they are:

1) Remove useless debug message when deleting IPVS service, from
   Yannick Brosseau.

2) Get rid of compilation warning when CONFIG_PROC_FS is unset in
   several spots of the IPVS code, from Arnd Bergmann.

3) Add prandom_u32 support to nft_meta, from Florian Westphal.

4) Remove unused variable in xt_osf, from Sudip Mukherjee.

5) Don't calculate IP checksum twice from netfilter ipv4 defrag hook
   since fixing af_packet defragmentation issues, from Joe Stringer.

6) On-demand hook registration for iptables from netns. Instead of
   registering the hooks for every available netns whenever we need
   one of the support tables, we register this on the specific netns
   that needs it, patchset from Florian Westphal.

7) Add missing port range selection to nf_tables masquerading support.

BTW, just for the record, there is a typo in the description of
5f6c253ebe93b0 ("netfilter: bridge: register hooks only when bridge
interface is added") that refers to the cluster match as deprecated, but
it is actually the CLUSTERIP target (which registers hooks
inconditionally) the one that is scheduled for removal.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 32 changed files Side-by-side Diff

include/linux/netfilter.h
... ... @@ -141,22 +141,6 @@
141 141  
142 142 #ifdef HAVE_JUMP_LABEL
143 143 extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
144   -
145   -static inline bool nf_hook_list_active(struct list_head *hook_list,
146   - u_int8_t pf, unsigned int hook)
147   -{
148   - if (__builtin_constant_p(pf) &&
149   - __builtin_constant_p(hook))
150   - return static_key_false(&nf_hooks_needed[pf][hook]);
151   -
152   - return !list_empty(hook_list);
153   -}
154   -#else
155   -static inline bool nf_hook_list_active(struct list_head *hook_list,
156   - u_int8_t pf, unsigned int hook)
157   -{
158   - return !list_empty(hook_list);
159   -}
160 144 #endif
161 145  
162 146 int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state);
163 147  
... ... @@ -177,9 +161,18 @@
177 161 int (*okfn)(struct net *, struct sock *, struct sk_buff *),
178 162 int thresh)
179 163 {
180   - struct list_head *hook_list = &net->nf.hooks[pf][hook];
  164 + struct list_head *hook_list;
181 165  
182   - if (nf_hook_list_active(hook_list, pf, hook)) {
  166 +#ifdef HAVE_JUMP_LABEL
  167 + if (__builtin_constant_p(pf) &&
  168 + __builtin_constant_p(hook) &&
  169 + !static_key_false(&nf_hooks_needed[pf][hook]))
  170 + return 1;
  171 +#endif
  172 +
  173 + hook_list = &net->nf.hooks[pf][hook];
  174 +
  175 + if (!list_empty(hook_list)) {
183 176 struct nf_hook_state state;
184 177  
185 178 nf_hook_state_init(&state, hook_list, hook, thresh,
include/linux/netfilter/x_tables.h
... ... @@ -200,6 +200,9 @@
200 200 u_int8_t af; /* address/protocol family */
201 201 int priority; /* hook order */
202 202  
  203 + /* called when table is needed in the given netns */
  204 + int (*table_init)(struct net *net);
  205 +
203 206 /* A unique name... */
204 207 const char name[XT_TABLE_MAXNAMELEN];
205 208 };
... ... @@ -408,8 +411,7 @@
408 411 return cnt;
409 412 }
410 413  
411   -struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *);
412   -void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *);
  414 +struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, nf_hookfn *);
413 415  
414 416 #ifdef CONFIG_COMPAT
415 417 #include <net/compat.h>
include/linux/netfilter_arp/arp_tables.h
... ... @@ -48,10 +48,11 @@
48 48 }
49 49  
50 50 extern void *arpt_alloc_initial_table(const struct xt_table *);
51   -extern struct xt_table *arpt_register_table(struct net *net,
52   - const struct xt_table *table,
53   - const struct arpt_replace *repl);
54   -extern void arpt_unregister_table(struct xt_table *table);
  51 +int arpt_register_table(struct net *net, const struct xt_table *table,
  52 + const struct arpt_replace *repl,
  53 + const struct nf_hook_ops *ops, struct xt_table **res);
  54 +void arpt_unregister_table(struct net *net, struct xt_table *table,
  55 + const struct nf_hook_ops *ops);
55 56 extern unsigned int arpt_do_table(struct sk_buff *skb,
56 57 const struct nf_hook_state *state,
57 58 struct xt_table *table);
include/linux/netfilter_ipv4/ip_tables.h
... ... @@ -24,10 +24,11 @@
24 24  
25 25 extern void ipt_init(void) __init;
26 26  
27   -extern struct xt_table *ipt_register_table(struct net *net,
28   - const struct xt_table *table,
29   - const struct ipt_replace *repl);
30   -extern void ipt_unregister_table(struct net *net, struct xt_table *table);
  27 +int ipt_register_table(struct net *net, const struct xt_table *table,
  28 + const struct ipt_replace *repl,
  29 + const struct nf_hook_ops *ops, struct xt_table **res);
  30 +void ipt_unregister_table(struct net *net, struct xt_table *table,
  31 + const struct nf_hook_ops *ops);
31 32  
32 33 /* Standard entry. */
33 34 struct ipt_standard {
include/linux/netfilter_ipv6/ip6_tables.h
... ... @@ -25,10 +25,11 @@
25 25 extern void ip6t_init(void) __init;
26 26  
27 27 extern void *ip6t_alloc_initial_table(const struct xt_table *);
28   -extern struct xt_table *ip6t_register_table(struct net *net,
29   - const struct xt_table *table,
30   - const struct ip6t_replace *repl);
31   -extern void ip6t_unregister_table(struct net *net, struct xt_table *table);
  28 +int ip6t_register_table(struct net *net, const struct xt_table *table,
  29 + const struct ip6t_replace *repl,
  30 + const struct nf_hook_ops *ops, struct xt_table **res);
  31 +void ip6t_unregister_table(struct net *net, struct xt_table *table,
  32 + const struct nf_hook_ops *ops);
32 33 extern unsigned int ip6t_do_table(struct sk_buff *skb,
33 34 const struct nf_hook_state *state,
34 35 struct xt_table *table);
include/net/netfilter/nft_masq.h
... ... @@ -2,7 +2,9 @@
2 2 #define _NFT_MASQ_H_
3 3  
4 4 struct nft_masq {
5   - u32 flags;
  5 + u32 flags;
  6 + enum nft_registers sreg_proto_min:8;
  7 + enum nft_registers sreg_proto_max:8;
6 8 };
7 9  
8 10 extern const struct nla_policy nft_masq_policy[];
include/uapi/linux/netfilter/nf_tables.h
... ... @@ -681,6 +681,7 @@
681 681 * @NFT_META_IIFGROUP: packet input interface group
682 682 * @NFT_META_OIFGROUP: packet output interface group
683 683 * @NFT_META_CGROUP: socket control group (skb->sk->sk_classid)
  684 + * @NFT_META_PRANDOM: a 32bit pseudo-random number
684 685 */
685 686 enum nft_meta_keys {
686 687 NFT_META_LEN,
... ... @@ -707,6 +708,7 @@
707 708 NFT_META_IIFGROUP,
708 709 NFT_META_OIFGROUP,
709 710 NFT_META_CGROUP,
  711 + NFT_META_PRANDOM,
710 712 };
711 713  
712 714 /**
713 715  
... ... @@ -949,10 +951,14 @@
949 951 * enum nft_masq_attributes - nf_tables masquerade expression attributes
950 952 *
951 953 * @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
  954 + * @NFTA_MASQ_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
  955 + * @NFTA_MASQ_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
952 956 */
953 957 enum nft_masq_attributes {
954 958 NFTA_MASQ_UNSPEC,
955 959 NFTA_MASQ_FLAGS,
  960 + NFTA_MASQ_REG_PROTO_MIN,
  961 + NFTA_MASQ_REG_PROTO_MAX,
956 962 __NFTA_MASQ_MAX
957 963 };
958 964 #define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
... ... @@ -255,6 +255,7 @@
255 255 prandom_warmup(state);
256 256 }
257 257 }
  258 +EXPORT_SYMBOL(prandom_seed_full_state);
258 259  
259 260 /*
260 261 * Generate better values after random number generator
net/bridge/br_netfilter_hooks.c
... ... @@ -37,6 +37,7 @@
37 37 #include <net/addrconf.h>
38 38 #include <net/route.h>
39 39 #include <net/netfilter/br_netfilter.h>
  40 +#include <net/netns/generic.h>
40 41  
41 42 #include <asm/uaccess.h>
42 43 #include "br_private.h"
... ... @@ -44,6 +45,12 @@
44 45 #include <linux/sysctl.h>
45 46 #endif
46 47  
  48 +static int brnf_net_id __read_mostly;
  49 +
  50 +struct brnf_net {
  51 + bool enabled;
  52 +};
  53 +
47 54 #ifdef CONFIG_SYSCTL
48 55 static struct ctl_table_header *brnf_sysctl_header;
49 56 static int brnf_call_iptables __read_mostly = 1;
... ... @@ -938,6 +945,53 @@
938 945 },
939 946 };
940 947  
  948 +static int brnf_device_event(struct notifier_block *unused, unsigned long event,
  949 + void *ptr)
  950 +{
  951 + struct net_device *dev = netdev_notifier_info_to_dev(ptr);
  952 + struct brnf_net *brnet;
  953 + struct net *net;
  954 + int ret;
  955 +
  956 + if (event != NETDEV_REGISTER || !(dev->priv_flags & IFF_EBRIDGE))
  957 + return NOTIFY_DONE;
  958 +
  959 + ASSERT_RTNL();
  960 +
  961 + net = dev_net(dev);
  962 + brnet = net_generic(net, brnf_net_id);
  963 + if (brnet->enabled)
  964 + return NOTIFY_OK;
  965 +
  966 + ret = nf_register_net_hooks(net, br_nf_ops, ARRAY_SIZE(br_nf_ops));
  967 + if (ret)
  968 + return NOTIFY_BAD;
  969 +
  970 + brnet->enabled = true;
  971 + return NOTIFY_OK;
  972 +}
  973 +
  974 +static void __net_exit brnf_exit_net(struct net *net)
  975 +{
  976 + struct brnf_net *brnet = net_generic(net, brnf_net_id);
  977 +
  978 + if (!brnet->enabled)
  979 + return;
  980 +
  981 + nf_unregister_net_hooks(net, br_nf_ops, ARRAY_SIZE(br_nf_ops));
  982 + brnet->enabled = false;
  983 +}
  984 +
  985 +static struct pernet_operations brnf_net_ops __read_mostly = {
  986 + .exit = brnf_exit_net,
  987 + .id = &brnf_net_id,
  988 + .size = sizeof(struct brnf_net),
  989 +};
  990 +
  991 +static struct notifier_block brnf_notifier __read_mostly = {
  992 + .notifier_call = brnf_device_event,
  993 +};
  994 +
941 995 #ifdef CONFIG_SYSCTL
942 996 static
943 997 int brnf_sysctl_call_tables(struct ctl_table *ctl, int write,
944 998  
945 999  
... ... @@ -1003,16 +1057,23 @@
1003 1057 {
1004 1058 int ret;
1005 1059  
1006   - ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
  1060 + ret = register_pernet_subsys(&brnf_net_ops);
1007 1061 if (ret < 0)
1008 1062 return ret;
1009 1063  
  1064 + ret = register_netdevice_notifier(&brnf_notifier);
  1065 + if (ret < 0) {
  1066 + unregister_pernet_subsys(&brnf_net_ops);
  1067 + return ret;
  1068 + }
  1069 +
1010 1070 #ifdef CONFIG_SYSCTL
1011 1071 brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table);
1012 1072 if (brnf_sysctl_header == NULL) {
1013 1073 printk(KERN_WARNING
1014 1074 "br_netfilter: can't register to sysctl.\n");
1015   - nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
  1075 + unregister_netdevice_notifier(&brnf_notifier);
  1076 + unregister_pernet_subsys(&brnf_net_ops);
1016 1077 return -ENOMEM;
1017 1078 }
1018 1079 #endif
... ... @@ -1024,7 +1085,8 @@
1024 1085 static void __exit br_netfilter_fini(void)
1025 1086 {
1026 1087 RCU_INIT_POINTER(nf_br_ops, NULL);
1027   - nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
  1088 + unregister_netdevice_notifier(&brnf_notifier);
  1089 + unregister_pernet_subsys(&brnf_net_ops);
1028 1090 #ifdef CONFIG_SYSCTL
1029 1091 unregister_net_sysctl_table(brnf_sysctl_header);
1030 1092 #endif
net/ipv4/netfilter/arp_tables.c
... ... @@ -1780,10 +1780,30 @@
1780 1780 return ret;
1781 1781 }
1782 1782  
1783   -struct xt_table *arpt_register_table(struct net *net,
1784   - const struct xt_table *table,
1785   - const struct arpt_replace *repl)
  1783 +static void __arpt_unregister_table(struct xt_table *table)
1786 1784 {
  1785 + struct xt_table_info *private;
  1786 + void *loc_cpu_entry;
  1787 + struct module *table_owner = table->me;
  1788 + struct arpt_entry *iter;
  1789 +
  1790 + private = xt_unregister_table(table);
  1791 +
  1792 + /* Decrease module usage counts and free resources */
  1793 + loc_cpu_entry = private->entries;
  1794 + xt_entry_foreach(iter, loc_cpu_entry, private->size)
  1795 + cleanup_entry(iter);
  1796 + if (private->number > private->initial_entries)
  1797 + module_put(table_owner);
  1798 + xt_free_table_info(private);
  1799 +}
  1800 +
  1801 +int arpt_register_table(struct net *net,
  1802 + const struct xt_table *table,
  1803 + const struct arpt_replace *repl,
  1804 + const struct nf_hook_ops *ops,
  1805 + struct xt_table **res)
  1806 +{
1787 1807 int ret;
1788 1808 struct xt_table_info *newinfo;
1789 1809 struct xt_table_info bootstrap = {0};
... ... @@ -1791,10 +1811,8 @@
1791 1811 struct xt_table *new_table;
1792 1812  
1793 1813 newinfo = xt_alloc_table_info(repl->size);
1794   - if (!newinfo) {
1795   - ret = -ENOMEM;
1796   - goto out;
1797   - }
  1814 + if (!newinfo)
  1815 + return -ENOMEM;
1798 1816  
1799 1817 loc_cpu_entry = newinfo->entries;
1800 1818 memcpy(loc_cpu_entry, repl->entries, repl->size);
1801 1819  
1802 1820  
1803 1821  
1804 1822  
... ... @@ -1809,30 +1827,28 @@
1809 1827 ret = PTR_ERR(new_table);
1810 1828 goto out_free;
1811 1829 }
1812   - return new_table;
1813 1830  
  1831 + /* set res now, will see skbs right after nf_register_net_hooks */
  1832 + WRITE_ONCE(*res, new_table);
  1833 +
  1834 + ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks));
  1835 + if (ret != 0) {
  1836 + __arpt_unregister_table(new_table);
  1837 + *res = NULL;
  1838 + }
  1839 +
  1840 + return ret;
  1841 +
1814 1842 out_free:
1815 1843 xt_free_table_info(newinfo);
1816   -out:
1817   - return ERR_PTR(ret);
  1844 + return ret;
1818 1845 }
1819 1846  
1820   -void arpt_unregister_table(struct xt_table *table)
  1847 +void arpt_unregister_table(struct net *net, struct xt_table *table,
  1848 + const struct nf_hook_ops *ops)
1821 1849 {
1822   - struct xt_table_info *private;
1823   - void *loc_cpu_entry;
1824   - struct module *table_owner = table->me;
1825   - struct arpt_entry *iter;
1826   -
1827   - private = xt_unregister_table(table);
1828   -
1829   - /* Decrease module usage counts and free resources */
1830   - loc_cpu_entry = private->entries;
1831   - xt_entry_foreach(iter, loc_cpu_entry, private->size)
1832   - cleanup_entry(iter);
1833   - if (private->number > private->initial_entries)
1834   - module_put(table_owner);
1835   - xt_free_table_info(private);
  1850 + nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks));
  1851 + __arpt_unregister_table(table);
1836 1852 }
1837 1853  
1838 1854 /* The built-in targets: standard (NULL) and error. */
net/ipv4/netfilter/arptable_filter.c
... ... @@ -17,12 +17,15 @@
17 17 #define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
18 18 (1 << NF_ARP_FORWARD))
19 19  
  20 +static int __net_init arptable_filter_table_init(struct net *net);
  21 +
20 22 static const struct xt_table packet_filter = {
21 23 .name = "filter",
22 24 .valid_hooks = FILTER_VALID_HOOKS,
23 25 .me = THIS_MODULE,
24 26 .af = NFPROTO_ARP,
25 27 .priority = NF_IP_PRI_FILTER,
  28 + .table_init = arptable_filter_table_init,
26 29 };
27 30  
28 31 /* The work comes in here from netfilter.c */
29 32  
30 33  
31 34  
32 35  
33 36  
... ... @@ -35,26 +38,32 @@
35 38  
36 39 static struct nf_hook_ops *arpfilter_ops __read_mostly;
37 40  
38   -static int __net_init arptable_filter_net_init(struct net *net)
  41 +static int __net_init arptable_filter_table_init(struct net *net)
39 42 {
40 43 struct arpt_replace *repl;
41   -
  44 + int err;
  45 +
  46 + if (net->ipv4.arptable_filter)
  47 + return 0;
  48 +
42 49 repl = arpt_alloc_initial_table(&packet_filter);
43 50 if (repl == NULL)
44 51 return -ENOMEM;
45   - net->ipv4.arptable_filter =
46   - arpt_register_table(net, &packet_filter, repl);
  52 + err = arpt_register_table(net, &packet_filter, repl, arpfilter_ops,
  53 + &net->ipv4.arptable_filter);
47 54 kfree(repl);
48   - return PTR_ERR_OR_ZERO(net->ipv4.arptable_filter);
  55 + return err;
49 56 }
50 57  
51 58 static void __net_exit arptable_filter_net_exit(struct net *net)
52 59 {
53   - arpt_unregister_table(net->ipv4.arptable_filter);
  60 + if (!net->ipv4.arptable_filter)
  61 + return;
  62 + arpt_unregister_table(net, net->ipv4.arptable_filter, arpfilter_ops);
  63 + net->ipv4.arptable_filter = NULL;
54 64 }
55 65  
56 66 static struct pernet_operations arptable_filter_net_ops = {
57   - .init = arptable_filter_net_init,
58 67 .exit = arptable_filter_net_exit,
59 68 };
60 69  
61 70  
62 71  
63 72  
64 73  
65 74  
66 75  
... ... @@ -62,26 +71,23 @@
62 71 {
63 72 int ret;
64 73  
  74 + arpfilter_ops = xt_hook_ops_alloc(&packet_filter, arptable_filter_hook);
  75 + if (IS_ERR(arpfilter_ops))
  76 + return PTR_ERR(arpfilter_ops);
  77 +
65 78 ret = register_pernet_subsys(&arptable_filter_net_ops);
66   - if (ret < 0)
  79 + if (ret < 0) {
  80 + kfree(arpfilter_ops);
67 81 return ret;
68   -
69   - arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook);
70   - if (IS_ERR(arpfilter_ops)) {
71   - ret = PTR_ERR(arpfilter_ops);
72   - goto cleanup_table;
73 82 }
74   - return ret;
75 83  
76   -cleanup_table:
77   - unregister_pernet_subsys(&arptable_filter_net_ops);
78 84 return ret;
79 85 }
80 86  
81 87 static void __exit arptable_filter_fini(void)
82 88 {
83   - xt_hook_unlink(&packet_filter, arpfilter_ops);
84 89 unregister_pernet_subsys(&arptable_filter_net_ops);
  90 + kfree(arpfilter_ops);
85 91 }
86 92  
87 93 module_init(arptable_filter_init);
net/ipv4/netfilter/ip_tables.c
... ... @@ -2062,10 +2062,28 @@
2062 2062 return ret;
2063 2063 }
2064 2064  
2065   -struct xt_table *ipt_register_table(struct net *net,
2066   - const struct xt_table *table,
2067   - const struct ipt_replace *repl)
  2065 +static void __ipt_unregister_table(struct net *net, struct xt_table *table)
2068 2066 {
  2067 + struct xt_table_info *private;
  2068 + void *loc_cpu_entry;
  2069 + struct module *table_owner = table->me;
  2070 + struct ipt_entry *iter;
  2071 +
  2072 + private = xt_unregister_table(table);
  2073 +
  2074 + /* Decrease module usage counts and free resources */
  2075 + loc_cpu_entry = private->entries;
  2076 + xt_entry_foreach(iter, loc_cpu_entry, private->size)
  2077 + cleanup_entry(iter, net);
  2078 + if (private->number > private->initial_entries)
  2079 + module_put(table_owner);
  2080 + xt_free_table_info(private);
  2081 +}
  2082 +
  2083 +int ipt_register_table(struct net *net, const struct xt_table *table,
  2084 + const struct ipt_replace *repl,
  2085 + const struct nf_hook_ops *ops, struct xt_table **res)
  2086 +{
2069 2087 int ret;
2070 2088 struct xt_table_info *newinfo;
2071 2089 struct xt_table_info bootstrap = {0};
... ... @@ -2073,10 +2091,8 @@
2073 2091 struct xt_table *new_table;
2074 2092  
2075 2093 newinfo = xt_alloc_table_info(repl->size);
2076   - if (!newinfo) {
2077   - ret = -ENOMEM;
2078   - goto out;
2079   - }
  2094 + if (!newinfo)
  2095 + return -ENOMEM;
2080 2096  
2081 2097 loc_cpu_entry = newinfo->entries;
2082 2098 memcpy(loc_cpu_entry, repl->entries, repl->size);
2083 2099  
2084 2100  
2085 2101  
2086 2102  
... ... @@ -2091,30 +2107,27 @@
2091 2107 goto out_free;
2092 2108 }
2093 2109  
2094   - return new_table;
  2110 + /* set res now, will see skbs right after nf_register_net_hooks */
  2111 + WRITE_ONCE(*res, new_table);
2095 2112  
  2113 + ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks));
  2114 + if (ret != 0) {
  2115 + __ipt_unregister_table(net, new_table);
  2116 + *res = NULL;
  2117 + }
  2118 +
  2119 + return ret;
  2120 +
2096 2121 out_free:
2097 2122 xt_free_table_info(newinfo);
2098   -out:
2099   - return ERR_PTR(ret);
  2123 + return ret;
2100 2124 }
2101 2125  
2102   -void ipt_unregister_table(struct net *net, struct xt_table *table)
  2126 +void ipt_unregister_table(struct net *net, struct xt_table *table,
  2127 + const struct nf_hook_ops *ops)
2103 2128 {
2104   - struct xt_table_info *private;
2105   - void *loc_cpu_entry;
2106   - struct module *table_owner = table->me;
2107   - struct ipt_entry *iter;
2108   -
2109   - private = xt_unregister_table(table);
2110   -
2111   - /* Decrease module usage counts and free resources */
2112   - loc_cpu_entry = private->entries;
2113   - xt_entry_foreach(iter, loc_cpu_entry, private->size)
2114   - cleanup_entry(iter, net);
2115   - if (private->number > private->initial_entries)
2116   - module_put(table_owner);
2117   - xt_free_table_info(private);
  2129 + nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks));
  2130 + __ipt_unregister_table(net, table);
2118 2131 }
2119 2132  
2120 2133 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
net/ipv4/netfilter/iptable_filter.c
... ... @@ -23,6 +23,7 @@
23 23 #define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \
24 24 (1 << NF_INET_FORWARD) | \
25 25 (1 << NF_INET_LOCAL_OUT))
  26 +static int __net_init iptable_filter_table_init(struct net *net);
26 27  
27 28 static const struct xt_table packet_filter = {
28 29 .name = "filter",
... ... @@ -30,6 +31,7 @@
30 31 .me = THIS_MODULE,
31 32 .af = NFPROTO_IPV4,
32 33 .priority = NF_IP_PRI_FILTER,
  34 + .table_init = iptable_filter_table_init,
33 35 };
34 36  
35 37 static unsigned int
36 38  
37 39  
38 40  
... ... @@ -48,13 +50,17 @@
48 50 static struct nf_hook_ops *filter_ops __read_mostly;
49 51  
50 52 /* Default to forward because I got too much mail already. */
51   -static bool forward = true;
  53 +static bool forward __read_mostly = true;
52 54 module_param(forward, bool, 0000);
53 55  
54   -static int __net_init iptable_filter_net_init(struct net *net)
  56 +static int __net_init iptable_filter_table_init(struct net *net)
55 57 {
56 58 struct ipt_replace *repl;
  59 + int err;
57 60  
  61 + if (net->ipv4.iptable_filter)
  62 + return 0;
  63 +
58 64 repl = ipt_alloc_initial_table(&packet_filter);
59 65 if (repl == NULL)
60 66 return -ENOMEM;
61 67  
62 68  
63 69  
... ... @@ -62,15 +68,26 @@
62 68 ((struct ipt_standard *)repl->entries)[1].target.verdict =
63 69 forward ? -NF_ACCEPT - 1 : -NF_DROP - 1;
64 70  
65   - net->ipv4.iptable_filter =
66   - ipt_register_table(net, &packet_filter, repl);
  71 + err = ipt_register_table(net, &packet_filter, repl, filter_ops,
  72 + &net->ipv4.iptable_filter);
67 73 kfree(repl);
68   - return PTR_ERR_OR_ZERO(net->ipv4.iptable_filter);
  74 + return err;
69 75 }
70 76  
  77 +static int __net_init iptable_filter_net_init(struct net *net)
  78 +{
  79 + if (net == &init_net || !forward)
  80 + return iptable_filter_table_init(net);
  81 +
  82 + return 0;
  83 +}
  84 +
71 85 static void __net_exit iptable_filter_net_exit(struct net *net)
72 86 {
73   - ipt_unregister_table(net, net->ipv4.iptable_filter);
  87 + if (!net->ipv4.iptable_filter)
  88 + return;
  89 + ipt_unregister_table(net, net->ipv4.iptable_filter, filter_ops);
  90 + net->ipv4.iptable_filter = NULL;
74 91 }
75 92  
76 93 static struct pernet_operations iptable_filter_net_ops = {
77 94  
78 95  
79 96  
80 97  
... ... @@ -82,24 +99,21 @@
82 99 {
83 100 int ret;
84 101  
  102 + filter_ops = xt_hook_ops_alloc(&packet_filter, iptable_filter_hook);
  103 + if (IS_ERR(filter_ops))
  104 + return PTR_ERR(filter_ops);
  105 +
85 106 ret = register_pernet_subsys(&iptable_filter_net_ops);
86 107 if (ret < 0)
87   - return ret;
  108 + kfree(filter_ops);
88 109  
89   - /* Register hooks */
90   - filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook);
91   - if (IS_ERR(filter_ops)) {
92   - ret = PTR_ERR(filter_ops);
93   - unregister_pernet_subsys(&iptable_filter_net_ops);
94   - }
95   -
96 110 return ret;
97 111 }
98 112  
99 113 static void __exit iptable_filter_fini(void)
100 114 {
101   - xt_hook_unlink(&packet_filter, filter_ops);
102 115 unregister_pernet_subsys(&iptable_filter_net_ops);
  116 + kfree(filter_ops);
103 117 }
104 118  
105 119 module_init(iptable_filter_init);
net/ipv4/netfilter/iptable_mangle.c
... ... @@ -28,12 +28,15 @@
28 28 (1 << NF_INET_LOCAL_OUT) | \
29 29 (1 << NF_INET_POST_ROUTING))
30 30  
  31 +static int __net_init iptable_mangle_table_init(struct net *net);
  32 +
31 33 static const struct xt_table packet_mangler = {
32 34 .name = "mangle",
33 35 .valid_hooks = MANGLE_VALID_HOOKS,
34 36 .me = THIS_MODULE,
35 37 .af = NFPROTO_IPV4,
36 38 .priority = NF_IP_PRI_MANGLE,
  39 + .table_init = iptable_mangle_table_init,
37 40 };
38 41  
39 42 static unsigned int
40 43  
41 44  
42 45  
43 46  
44 47  
45 48  
... ... @@ -92,27 +95,32 @@
92 95 }
93 96  
94 97 static struct nf_hook_ops *mangle_ops __read_mostly;
95   -
96   -static int __net_init iptable_mangle_net_init(struct net *net)
  98 +static int __net_init iptable_mangle_table_init(struct net *net)
97 99 {
98 100 struct ipt_replace *repl;
  101 + int ret;
99 102  
  103 + if (net->ipv4.iptable_mangle)
  104 + return 0;
  105 +
100 106 repl = ipt_alloc_initial_table(&packet_mangler);
101 107 if (repl == NULL)
102 108 return -ENOMEM;
103   - net->ipv4.iptable_mangle =
104   - ipt_register_table(net, &packet_mangler, repl);
  109 + ret = ipt_register_table(net, &packet_mangler, repl, mangle_ops,
  110 + &net->ipv4.iptable_mangle);
105 111 kfree(repl);
106   - return PTR_ERR_OR_ZERO(net->ipv4.iptable_mangle);
  112 + return ret;
107 113 }
108 114  
109 115 static void __net_exit iptable_mangle_net_exit(struct net *net)
110 116 {
111   - ipt_unregister_table(net, net->ipv4.iptable_mangle);
  117 + if (!net->ipv4.iptable_mangle)
  118 + return;
  119 + ipt_unregister_table(net, net->ipv4.iptable_mangle, mangle_ops);
  120 + net->ipv4.iptable_mangle = NULL;
112 121 }
113 122  
114 123 static struct pernet_operations iptable_mangle_net_ops = {
115   - .init = iptable_mangle_net_init,
116 124 .exit = iptable_mangle_net_exit,
117 125 };
118 126  
119 127  
120 128  
121 129  
122 130  
... ... @@ -120,15 +128,22 @@
120 128 {
121 129 int ret;
122 130  
  131 + mangle_ops = xt_hook_ops_alloc(&packet_mangler, iptable_mangle_hook);
  132 + if (IS_ERR(mangle_ops)) {
  133 + ret = PTR_ERR(mangle_ops);
  134 + return ret;
  135 + }
  136 +
123 137 ret = register_pernet_subsys(&iptable_mangle_net_ops);
124   - if (ret < 0)
  138 + if (ret < 0) {
  139 + kfree(mangle_ops);
125 140 return ret;
  141 + }
126 142  
127   - /* Register hooks */
128   - mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook);
129   - if (IS_ERR(mangle_ops)) {
130   - ret = PTR_ERR(mangle_ops);
  143 + ret = iptable_mangle_table_init(&init_net);
  144 + if (ret) {
131 145 unregister_pernet_subsys(&iptable_mangle_net_ops);
  146 + kfree(mangle_ops);
132 147 }
133 148  
134 149 return ret;
135 150  
... ... @@ -136,8 +151,8 @@
136 151  
137 152 static void __exit iptable_mangle_fini(void)
138 153 {
139   - xt_hook_unlink(&packet_mangler, mangle_ops);
140 154 unregister_pernet_subsys(&iptable_mangle_net_ops);
  155 + kfree(mangle_ops);
141 156 }
142 157  
143 158 module_init(iptable_mangle_init);
net/ipv4/netfilter/iptable_nat.c
... ... @@ -18,6 +18,8 @@
18 18 #include <net/netfilter/nf_nat_core.h>
19 19 #include <net/netfilter/nf_nat_l3proto.h>
20 20  
  21 +static int __net_init iptable_nat_table_init(struct net *net);
  22 +
21 23 static const struct xt_table nf_nat_ipv4_table = {
22 24 .name = "nat",
23 25 .valid_hooks = (1 << NF_INET_PRE_ROUTING) |
... ... @@ -26,6 +28,7 @@
26 28 (1 << NF_INET_LOCAL_IN),
27 29 .me = THIS_MODULE,
28 30 .af = NFPROTO_IPV4,
  31 + .table_init = iptable_nat_table_init,
29 32 };
30 33  
31 34 static unsigned int iptable_nat_do_chain(void *priv,
32 35  
33 36  
34 37  
35 38  
36 39  
37 40  
38 41  
39 42  
40 43  
41 44  
... ... @@ -95,50 +98,50 @@
95 98 },
96 99 };
97 100  
98   -static int __net_init iptable_nat_net_init(struct net *net)
  101 +static int __net_init iptable_nat_table_init(struct net *net)
99 102 {
100 103 struct ipt_replace *repl;
  104 + int ret;
101 105  
  106 + if (net->ipv4.nat_table)
  107 + return 0;
  108 +
102 109 repl = ipt_alloc_initial_table(&nf_nat_ipv4_table);
103 110 if (repl == NULL)
104 111 return -ENOMEM;
105   - net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
  112 + ret = ipt_register_table(net, &nf_nat_ipv4_table, repl,
  113 + nf_nat_ipv4_ops, &net->ipv4.nat_table);
106 114 kfree(repl);
107   - return PTR_ERR_OR_ZERO(net->ipv4.nat_table);
  115 + return ret;
108 116 }
109 117  
110 118 static void __net_exit iptable_nat_net_exit(struct net *net)
111 119 {
112   - ipt_unregister_table(net, net->ipv4.nat_table);
  120 + if (!net->ipv4.nat_table)
  121 + return;
  122 + ipt_unregister_table(net, net->ipv4.nat_table, nf_nat_ipv4_ops);
  123 + net->ipv4.nat_table = NULL;
113 124 }
114 125  
115 126 static struct pernet_operations iptable_nat_net_ops = {
116   - .init = iptable_nat_net_init,
117 127 .exit = iptable_nat_net_exit,
118 128 };
119 129  
120 130 static int __init iptable_nat_init(void)
121 131 {
122   - int err;
  132 + int ret = register_pernet_subsys(&iptable_nat_net_ops);
123 133  
124   - err = register_pernet_subsys(&iptable_nat_net_ops);
125   - if (err < 0)
126   - goto err1;
  134 + if (ret)
  135 + return ret;
127 136  
128   - err = nf_register_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
129   - if (err < 0)
130   - goto err2;
131   - return 0;
132   -
133   -err2:
134   - unregister_pernet_subsys(&iptable_nat_net_ops);
135   -err1:
136   - return err;
  137 + ret = iptable_nat_table_init(&init_net);
  138 + if (ret)
  139 + unregister_pernet_subsys(&iptable_nat_net_ops);
  140 + return ret;
137 141 }
138 142  
139 143 static void __exit iptable_nat_exit(void)
140 144 {
141   - nf_unregister_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
142 145 unregister_pernet_subsys(&iptable_nat_net_ops);
143 146 }
144 147  
net/ipv4/netfilter/iptable_raw.c
... ... @@ -10,12 +10,15 @@
10 10  
11 11 #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
12 12  
  13 +static int __net_init iptable_raw_table_init(struct net *net);
  14 +
13 15 static const struct xt_table packet_raw = {
14 16 .name = "raw",
15 17 .valid_hooks = RAW_VALID_HOOKS,
16 18 .me = THIS_MODULE,
17 19 .af = NFPROTO_IPV4,
18 20 .priority = NF_IP_PRI_RAW,
  21 + .table_init = iptable_raw_table_init,
19 22 };
20 23  
21 24 /* The work comes in here from netfilter.c. */
22 25  
23 26  
24 27  
25 28  
26 29  
27 30  
... ... @@ -34,26 +37,32 @@
34 37  
35 38 static struct nf_hook_ops *rawtable_ops __read_mostly;
36 39  
37   -static int __net_init iptable_raw_net_init(struct net *net)
  40 +static int __net_init iptable_raw_table_init(struct net *net)
38 41 {
39 42 struct ipt_replace *repl;
  43 + int ret;
40 44  
  45 + if (net->ipv4.iptable_raw)
  46 + return 0;
  47 +
41 48 repl = ipt_alloc_initial_table(&packet_raw);
42 49 if (repl == NULL)
43 50 return -ENOMEM;
44   - net->ipv4.iptable_raw =
45   - ipt_register_table(net, &packet_raw, repl);
  51 + ret = ipt_register_table(net, &packet_raw, repl, rawtable_ops,
  52 + &net->ipv4.iptable_raw);
46 53 kfree(repl);
47   - return PTR_ERR_OR_ZERO(net->ipv4.iptable_raw);
  54 + return ret;
48 55 }
49 56  
50 57 static void __net_exit iptable_raw_net_exit(struct net *net)
51 58 {
52   - ipt_unregister_table(net, net->ipv4.iptable_raw);
  59 + if (!net->ipv4.iptable_raw)
  60 + return;
  61 + ipt_unregister_table(net, net->ipv4.iptable_raw, rawtable_ops);
  62 + net->ipv4.iptable_raw = NULL;
53 63 }
54 64  
55 65 static struct pernet_operations iptable_raw_net_ops = {
56   - .init = iptable_raw_net_init,
57 66 .exit = iptable_raw_net_exit,
58 67 };
59 68  
60 69  
61 70  
62 71  
63 72  
... ... @@ -61,15 +70,20 @@
61 70 {
62 71 int ret;
63 72  
  73 + rawtable_ops = xt_hook_ops_alloc(&packet_raw, iptable_raw_hook);
  74 + if (IS_ERR(rawtable_ops))
  75 + return PTR_ERR(rawtable_ops);
  76 +
64 77 ret = register_pernet_subsys(&iptable_raw_net_ops);
65   - if (ret < 0)
  78 + if (ret < 0) {
  79 + kfree(rawtable_ops);
66 80 return ret;
  81 + }
67 82  
68   - /* Register hooks */
69   - rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook);
70   - if (IS_ERR(rawtable_ops)) {
71   - ret = PTR_ERR(rawtable_ops);
  83 + ret = iptable_raw_table_init(&init_net);
  84 + if (ret) {
72 85 unregister_pernet_subsys(&iptable_raw_net_ops);
  86 + kfree(rawtable_ops);
73 87 }
74 88  
75 89 return ret;
76 90  
... ... @@ -77,8 +91,8 @@
77 91  
78 92 static void __exit iptable_raw_fini(void)
79 93 {
80   - xt_hook_unlink(&packet_raw, rawtable_ops);
81 94 unregister_pernet_subsys(&iptable_raw_net_ops);
  95 + kfree(rawtable_ops);
82 96 }
83 97  
84 98 module_init(iptable_raw_init);
net/ipv4/netfilter/iptable_security.c
... ... @@ -28,12 +28,15 @@
28 28 (1 << NF_INET_FORWARD) | \
29 29 (1 << NF_INET_LOCAL_OUT)
30 30  
  31 +static int __net_init iptable_security_table_init(struct net *net);
  32 +
31 33 static const struct xt_table security_table = {
32 34 .name = "security",
33 35 .valid_hooks = SECURITY_VALID_HOOKS,
34 36 .me = THIS_MODULE,
35 37 .af = NFPROTO_IPV4,
36 38 .priority = NF_IP_PRI_SECURITY,
  39 + .table_init = iptable_security_table_init,
37 40 };
38 41  
39 42 static unsigned int
40 43  
41 44  
42 45  
43 46  
44 47  
45 48  
... ... @@ -51,26 +54,33 @@
51 54  
52 55 static struct nf_hook_ops *sectbl_ops __read_mostly;
53 56  
54   -static int __net_init iptable_security_net_init(struct net *net)
  57 +static int __net_init iptable_security_table_init(struct net *net)
55 58 {
56 59 struct ipt_replace *repl;
  60 + int ret;
57 61  
  62 + if (net->ipv4.iptable_security)
  63 + return 0;
  64 +
58 65 repl = ipt_alloc_initial_table(&security_table);
59 66 if (repl == NULL)
60 67 return -ENOMEM;
61   - net->ipv4.iptable_security =
62   - ipt_register_table(net, &security_table, repl);
  68 + ret = ipt_register_table(net, &security_table, repl, sectbl_ops,
  69 + &net->ipv4.iptable_security);
63 70 kfree(repl);
64   - return PTR_ERR_OR_ZERO(net->ipv4.iptable_security);
  71 + return ret;
65 72 }
66 73  
67 74 static void __net_exit iptable_security_net_exit(struct net *net)
68 75 {
69   - ipt_unregister_table(net, net->ipv4.iptable_security);
  76 + if (!net->ipv4.iptable_security)
  77 + return;
  78 +
  79 + ipt_unregister_table(net, net->ipv4.iptable_security, sectbl_ops);
  80 + net->ipv4.iptable_security = NULL;
70 81 }
71 82  
72 83 static struct pernet_operations iptable_security_net_ops = {
73   - .init = iptable_security_net_init,
74 84 .exit = iptable_security_net_exit,
75 85 };
76 86  
77 87  
78 88  
79 89  
80 90  
81 91  
82 92  
... ... @@ -78,27 +88,29 @@
78 88 {
79 89 int ret;
80 90  
  91 + sectbl_ops = xt_hook_ops_alloc(&security_table, iptable_security_hook);
  92 + if (IS_ERR(sectbl_ops))
  93 + return PTR_ERR(sectbl_ops);
  94 +
81 95 ret = register_pernet_subsys(&iptable_security_net_ops);
82   - if (ret < 0)
  96 + if (ret < 0) {
  97 + kfree(sectbl_ops);
83 98 return ret;
  99 + }
84 100  
85   - sectbl_ops = xt_hook_link(&security_table, iptable_security_hook);
86   - if (IS_ERR(sectbl_ops)) {
87   - ret = PTR_ERR(sectbl_ops);
88   - goto cleanup_table;
  101 + ret = iptable_security_table_init(&init_net);
  102 + if (ret) {
  103 + unregister_pernet_subsys(&iptable_security_net_ops);
  104 + kfree(sectbl_ops);
89 105 }
90 106  
91 107 return ret;
92   -
93   -cleanup_table:
94   - unregister_pernet_subsys(&iptable_security_net_ops);
95   - return ret;
96 108 }
97 109  
98 110 static void __exit iptable_security_fini(void)
99 111 {
100   - xt_hook_unlink(&security_table, sectbl_ops);
101 112 unregister_pernet_subsys(&iptable_security_net_ops);
  113 + kfree(sectbl_ops);
102 114 }
103 115  
104 116 module_init(iptable_security_init);
net/ipv4/netfilter/nf_defrag_ipv4.c
... ... @@ -31,10 +31,8 @@
31 31 err = ip_defrag(net, skb, user);
32 32 local_bh_enable();
33 33  
34   - if (!err) {
35   - ip_send_check(ip_hdr(skb));
  34 + if (!err)
36 35 skb->ignore_df = 1;
37   - }
38 36  
39 37 return err;
40 38 }
net/ipv4/netfilter/nft_masq_ipv4.c
... ... @@ -25,7 +25,12 @@
25 25  
26 26 memset(&range, 0, sizeof(range));
27 27 range.flags = priv->flags;
28   -
  28 + if (priv->sreg_proto_min) {
  29 + range.min_proto.all =
  30 + *(__be16 *)&regs->data[priv->sreg_proto_min];
  31 + range.max_proto.all =
  32 + *(__be16 *)&regs->data[priv->sreg_proto_max];
  33 + }
29 34 regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->hook,
30 35 &range, pkt->out);
31 36 }
net/ipv6/netfilter/ip6_tables.c
... ... @@ -2071,10 +2071,29 @@
2071 2071 return ret;
2072 2072 }
2073 2073  
2074   -struct xt_table *ip6t_register_table(struct net *net,
2075   - const struct xt_table *table,
2076   - const struct ip6t_replace *repl)
  2074 +static void __ip6t_unregister_table(struct net *net, struct xt_table *table)
2077 2075 {
  2076 + struct xt_table_info *private;
  2077 + void *loc_cpu_entry;
  2078 + struct module *table_owner = table->me;
  2079 + struct ip6t_entry *iter;
  2080 +
  2081 + private = xt_unregister_table(table);
  2082 +
  2083 + /* Decrease module usage counts and free resources */
  2084 + loc_cpu_entry = private->entries;
  2085 + xt_entry_foreach(iter, loc_cpu_entry, private->size)
  2086 + cleanup_entry(iter, net);
  2087 + if (private->number > private->initial_entries)
  2088 + module_put(table_owner);
  2089 + xt_free_table_info(private);
  2090 +}
  2091 +
  2092 +int ip6t_register_table(struct net *net, const struct xt_table *table,
  2093 + const struct ip6t_replace *repl,
  2094 + const struct nf_hook_ops *ops,
  2095 + struct xt_table **res)
  2096 +{
2078 2097 int ret;
2079 2098 struct xt_table_info *newinfo;
2080 2099 struct xt_table_info bootstrap = {0};
... ... @@ -2082,10 +2101,8 @@
2082 2101 struct xt_table *new_table;
2083 2102  
2084 2103 newinfo = xt_alloc_table_info(repl->size);
2085   - if (!newinfo) {
2086   - ret = -ENOMEM;
2087   - goto out;
2088   - }
  2104 + if (!newinfo)
  2105 + return -ENOMEM;
2089 2106  
2090 2107 loc_cpu_entry = newinfo->entries;
2091 2108 memcpy(loc_cpu_entry, repl->entries, repl->size);
2092 2109  
2093 2110  
2094 2111  
2095 2112  
... ... @@ -2099,30 +2116,28 @@
2099 2116 ret = PTR_ERR(new_table);
2100 2117 goto out_free;
2101 2118 }
2102   - return new_table;
2103 2119  
  2120 + /* set res now, will see skbs right after nf_register_net_hooks */
  2121 + WRITE_ONCE(*res, new_table);
  2122 +
  2123 + ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks));
  2124 + if (ret != 0) {
  2125 + __ip6t_unregister_table(net, new_table);
  2126 + *res = NULL;
  2127 + }
  2128 +
  2129 + return ret;
  2130 +
2104 2131 out_free:
2105 2132 xt_free_table_info(newinfo);
2106   -out:
2107   - return ERR_PTR(ret);
  2133 + return ret;
2108 2134 }
2109 2135  
2110   -void ip6t_unregister_table(struct net *net, struct xt_table *table)
  2136 +void ip6t_unregister_table(struct net *net, struct xt_table *table,
  2137 + const struct nf_hook_ops *ops)
2111 2138 {
2112   - struct xt_table_info *private;
2113   - void *loc_cpu_entry;
2114   - struct module *table_owner = table->me;
2115   - struct ip6t_entry *iter;
2116   -
2117   - private = xt_unregister_table(table);
2118   -
2119   - /* Decrease module usage counts and free resources */
2120   - loc_cpu_entry = private->entries;
2121   - xt_entry_foreach(iter, loc_cpu_entry, private->size)
2122   - cleanup_entry(iter, net);
2123   - if (private->number > private->initial_entries)
2124   - module_put(table_owner);
2125   - xt_free_table_info(private);
  2139 + nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks));
  2140 + __ip6t_unregister_table(net, table);
2126 2141 }
2127 2142  
2128 2143 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
net/ipv6/netfilter/ip6table_filter.c
... ... @@ -22,12 +22,15 @@
22 22 (1 << NF_INET_FORWARD) | \
23 23 (1 << NF_INET_LOCAL_OUT))
24 24  
  25 +static int __net_init ip6table_filter_table_init(struct net *net);
  26 +
25 27 static const struct xt_table packet_filter = {
26 28 .name = "filter",
27 29 .valid_hooks = FILTER_VALID_HOOKS,
28 30 .me = THIS_MODULE,
29 31 .af = NFPROTO_IPV6,
30 32 .priority = NF_IP6_PRI_FILTER,
  33 + .table_init = ip6table_filter_table_init,
31 34 };
32 35  
33 36 /* The work comes in here from netfilter.c. */
34 37  
35 38  
... ... @@ -44,10 +47,14 @@
44 47 static bool forward = true;
45 48 module_param(forward, bool, 0000);
46 49  
47   -static int __net_init ip6table_filter_net_init(struct net *net)
  50 +static int __net_init ip6table_filter_table_init(struct net *net)
48 51 {
49 52 struct ip6t_replace *repl;
  53 + int err;
50 54  
  55 + if (net->ipv6.ip6table_filter)
  56 + return 0;
  57 +
51 58 repl = ip6t_alloc_initial_table(&packet_filter);
52 59 if (repl == NULL)
53 60 return -ENOMEM;
54 61  
55 62  
56 63  
... ... @@ -55,15 +62,26 @@
55 62 ((struct ip6t_standard *)repl->entries)[1].target.verdict =
56 63 forward ? -NF_ACCEPT - 1 : -NF_DROP - 1;
57 64  
58   - net->ipv6.ip6table_filter =
59   - ip6t_register_table(net, &packet_filter, repl);
  65 + err = ip6t_register_table(net, &packet_filter, repl, filter_ops,
  66 + &net->ipv6.ip6table_filter);
60 67 kfree(repl);
61   - return PTR_ERR_OR_ZERO(net->ipv6.ip6table_filter);
  68 + return err;
62 69 }
63 70  
  71 +static int __net_init ip6table_filter_net_init(struct net *net)
  72 +{
  73 + if (net == &init_net || !forward)
  74 + return ip6table_filter_table_init(net);
  75 +
  76 + return 0;
  77 +}
  78 +
64 79 static void __net_exit ip6table_filter_net_exit(struct net *net)
65 80 {
66   - ip6t_unregister_table(net, net->ipv6.ip6table_filter);
  81 + if (!net->ipv6.ip6table_filter)
  82 + return;
  83 + ip6t_unregister_table(net, net->ipv6.ip6table_filter, filter_ops);
  84 + net->ipv6.ip6table_filter = NULL;
67 85 }
68 86  
69 87 static struct pernet_operations ip6table_filter_net_ops = {
70 88  
71 89  
72 90  
73 91  
74 92  
... ... @@ -75,28 +93,21 @@
75 93 {
76 94 int ret;
77 95  
  96 + filter_ops = xt_hook_ops_alloc(&packet_filter, ip6table_filter_hook);
  97 + if (IS_ERR(filter_ops))
  98 + return PTR_ERR(filter_ops);
  99 +
78 100 ret = register_pernet_subsys(&ip6table_filter_net_ops);
79 101 if (ret < 0)
80   - return ret;
  102 + kfree(filter_ops);
81 103  
82   - /* Register hooks */
83   - filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook);
84   - if (IS_ERR(filter_ops)) {
85   - ret = PTR_ERR(filter_ops);
86   - goto cleanup_table;
87   - }
88   -
89 104 return ret;
90   -
91   - cleanup_table:
92   - unregister_pernet_subsys(&ip6table_filter_net_ops);
93   - return ret;
94 105 }
95 106  
96 107 static void __exit ip6table_filter_fini(void)
97 108 {
98   - xt_hook_unlink(&packet_filter, filter_ops);
99 109 unregister_pernet_subsys(&ip6table_filter_net_ops);
  110 + kfree(filter_ops);
100 111 }
101 112  
102 113 module_init(ip6table_filter_init);
net/ipv6/netfilter/ip6table_mangle.c
... ... @@ -23,12 +23,15 @@
23 23 (1 << NF_INET_LOCAL_OUT) | \
24 24 (1 << NF_INET_POST_ROUTING))
25 25  
  26 +static int __net_init ip6table_mangle_table_init(struct net *net);
  27 +
26 28 static const struct xt_table packet_mangler = {
27 29 .name = "mangle",
28 30 .valid_hooks = MANGLE_VALID_HOOKS,
29 31 .me = THIS_MODULE,
30 32 .af = NFPROTO_IPV6,
31 33 .priority = NF_IP6_PRI_MANGLE,
  34 + .table_init = ip6table_mangle_table_init,
32 35 };
33 36  
34 37 static unsigned int
35 38  
36 39  
37 40  
38 41  
39 42  
40 43  
... ... @@ -88,26 +91,33 @@
88 91 }
89 92  
90 93 static struct nf_hook_ops *mangle_ops __read_mostly;
91   -static int __net_init ip6table_mangle_net_init(struct net *net)
  94 +static int __net_init ip6table_mangle_table_init(struct net *net)
92 95 {
93 96 struct ip6t_replace *repl;
  97 + int ret;
94 98  
  99 + if (net->ipv6.ip6table_mangle)
  100 + return 0;
  101 +
95 102 repl = ip6t_alloc_initial_table(&packet_mangler);
96 103 if (repl == NULL)
97 104 return -ENOMEM;
98   - net->ipv6.ip6table_mangle =
99   - ip6t_register_table(net, &packet_mangler, repl);
  105 + ret = ip6t_register_table(net, &packet_mangler, repl, mangle_ops,
  106 + &net->ipv6.ip6table_mangle);
100 107 kfree(repl);
101   - return PTR_ERR_OR_ZERO(net->ipv6.ip6table_mangle);
  108 + return ret;
102 109 }
103 110  
104 111 static void __net_exit ip6table_mangle_net_exit(struct net *net)
105 112 {
106   - ip6t_unregister_table(net, net->ipv6.ip6table_mangle);
  113 + if (!net->ipv6.ip6table_mangle)
  114 + return;
  115 +
  116 + ip6t_unregister_table(net, net->ipv6.ip6table_mangle, mangle_ops);
  117 + net->ipv6.ip6table_mangle = NULL;
107 118 }
108 119  
109 120 static struct pernet_operations ip6table_mangle_net_ops = {
110   - .init = ip6table_mangle_net_init,
111 121 .exit = ip6table_mangle_net_exit,
112 122 };
113 123  
114 124  
115 125  
116 126  
117 127  
118 128  
119 129  
... ... @@ -115,28 +125,28 @@
115 125 {
116 126 int ret;
117 127  
  128 + mangle_ops = xt_hook_ops_alloc(&packet_mangler, ip6table_mangle_hook);
  129 + if (IS_ERR(mangle_ops))
  130 + return PTR_ERR(mangle_ops);
  131 +
118 132 ret = register_pernet_subsys(&ip6table_mangle_net_ops);
119   - if (ret < 0)
  133 + if (ret < 0) {
  134 + kfree(mangle_ops);
120 135 return ret;
121   -
122   - /* Register hooks */
123   - mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook);
124   - if (IS_ERR(mangle_ops)) {
125   - ret = PTR_ERR(mangle_ops);
126   - goto cleanup_table;
127 136 }
128 137  
  138 + ret = ip6table_mangle_table_init(&init_net);
  139 + if (ret) {
  140 + unregister_pernet_subsys(&ip6table_mangle_net_ops);
  141 + kfree(mangle_ops);
  142 + }
129 143 return ret;
130   -
131   - cleanup_table:
132   - unregister_pernet_subsys(&ip6table_mangle_net_ops);
133   - return ret;
134 144 }
135 145  
136 146 static void __exit ip6table_mangle_fini(void)
137 147 {
138   - xt_hook_unlink(&packet_mangler, mangle_ops);
139 148 unregister_pernet_subsys(&ip6table_mangle_net_ops);
  149 + kfree(mangle_ops);
140 150 }
141 151  
142 152 module_init(ip6table_mangle_init);
net/ipv6/netfilter/ip6table_nat.c
... ... @@ -20,6 +20,8 @@
20 20 #include <net/netfilter/nf_nat_core.h>
21 21 #include <net/netfilter/nf_nat_l3proto.h>
22 22  
  23 +static int __net_init ip6table_nat_table_init(struct net *net);
  24 +
23 25 static const struct xt_table nf_nat_ipv6_table = {
24 26 .name = "nat",
25 27 .valid_hooks = (1 << NF_INET_PRE_ROUTING) |
... ... @@ -28,6 +30,7 @@
28 30 (1 << NF_INET_LOCAL_IN),
29 31 .me = THIS_MODULE,
30 32 .af = NFPROTO_IPV6,
  33 + .table_init = ip6table_nat_table_init,
31 34 };
32 35  
33 36 static unsigned int ip6table_nat_do_chain(void *priv,
34 37  
35 38  
36 39  
37 40  
38 41  
39 42  
40 43  
41 44  
42 45  
43 46  
... ... @@ -97,50 +100,50 @@
97 100 },
98 101 };
99 102  
100   -static int __net_init ip6table_nat_net_init(struct net *net)
  103 +static int __net_init ip6table_nat_table_init(struct net *net)
101 104 {
102 105 struct ip6t_replace *repl;
  106 + int ret;
103 107  
  108 + if (net->ipv6.ip6table_nat)
  109 + return 0;
  110 +
104 111 repl = ip6t_alloc_initial_table(&nf_nat_ipv6_table);
105 112 if (repl == NULL)
106 113 return -ENOMEM;
107   - net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl);
  114 + ret = ip6t_register_table(net, &nf_nat_ipv6_table, repl,
  115 + nf_nat_ipv6_ops, &net->ipv6.ip6table_nat);
108 116 kfree(repl);
109   - return PTR_ERR_OR_ZERO(net->ipv6.ip6table_nat);
  117 + return ret;
110 118 }
111 119  
112 120 static void __net_exit ip6table_nat_net_exit(struct net *net)
113 121 {
114   - ip6t_unregister_table(net, net->ipv6.ip6table_nat);
  122 + if (!net->ipv6.ip6table_nat)
  123 + return;
  124 + ip6t_unregister_table(net, net->ipv6.ip6table_nat, nf_nat_ipv6_ops);
  125 + net->ipv6.ip6table_nat = NULL;
115 126 }
116 127  
117 128 static struct pernet_operations ip6table_nat_net_ops = {
118   - .init = ip6table_nat_net_init,
119 129 .exit = ip6table_nat_net_exit,
120 130 };
121 131  
122 132 static int __init ip6table_nat_init(void)
123 133 {
124   - int err;
  134 + int ret = register_pernet_subsys(&ip6table_nat_net_ops);
125 135  
126   - err = register_pernet_subsys(&ip6table_nat_net_ops);
127   - if (err < 0)
128   - goto err1;
  136 + if (ret)
  137 + return ret;
129 138  
130   - err = nf_register_hooks(nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops));
131   - if (err < 0)
132   - goto err2;
133   - return 0;
134   -
135   -err2:
136   - unregister_pernet_subsys(&ip6table_nat_net_ops);
137   -err1:
138   - return err;
  139 + ret = ip6table_nat_table_init(&init_net);
  140 + if (ret)
  141 + unregister_pernet_subsys(&ip6table_nat_net_ops);
  142 + return ret;
139 143 }
140 144  
141 145 static void __exit ip6table_nat_exit(void)
142 146 {
143   - nf_unregister_hooks(nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops));
144 147 unregister_pernet_subsys(&ip6table_nat_net_ops);
145 148 }
146 149  
net/ipv6/netfilter/ip6table_raw.c
... ... @@ -9,12 +9,15 @@
9 9  
10 10 #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
11 11  
  12 +static int __net_init ip6table_raw_table_init(struct net *net);
  13 +
12 14 static const struct xt_table packet_raw = {
13 15 .name = "raw",
14 16 .valid_hooks = RAW_VALID_HOOKS,
15 17 .me = THIS_MODULE,
16 18 .af = NFPROTO_IPV6,
17 19 .priority = NF_IP6_PRI_RAW,
  20 + .table_init = ip6table_raw_table_init,
18 21 };
19 22  
20 23 /* The work comes in here from netfilter.c. */
21 24  
22 25  
23 26  
24 27  
25 28  
26 29  
... ... @@ -27,26 +30,32 @@
27 30  
28 31 static struct nf_hook_ops *rawtable_ops __read_mostly;
29 32  
30   -static int __net_init ip6table_raw_net_init(struct net *net)
  33 +static int __net_init ip6table_raw_table_init(struct net *net)
31 34 {
32 35 struct ip6t_replace *repl;
  36 + int ret;
33 37  
  38 + if (net->ipv6.ip6table_raw)
  39 + return 0;
  40 +
34 41 repl = ip6t_alloc_initial_table(&packet_raw);
35 42 if (repl == NULL)
36 43 return -ENOMEM;
37   - net->ipv6.ip6table_raw =
38   - ip6t_register_table(net, &packet_raw, repl);
  44 + ret = ip6t_register_table(net, &packet_raw, repl, rawtable_ops,
  45 + &net->ipv6.ip6table_raw);
39 46 kfree(repl);
40   - return PTR_ERR_OR_ZERO(net->ipv6.ip6table_raw);
  47 + return ret;
41 48 }
42 49  
43 50 static void __net_exit ip6table_raw_net_exit(struct net *net)
44 51 {
45   - ip6t_unregister_table(net, net->ipv6.ip6table_raw);
  52 + if (!net->ipv6.ip6table_raw)
  53 + return;
  54 + ip6t_unregister_table(net, net->ipv6.ip6table_raw, rawtable_ops);
  55 + net->ipv6.ip6table_raw = NULL;
46 56 }
47 57  
48 58 static struct pernet_operations ip6table_raw_net_ops = {
49   - .init = ip6table_raw_net_init,
50 59 .exit = ip6table_raw_net_exit,
51 60 };
52 61  
53 62  
54 63  
55 64  
56 65  
57 66  
58 67  
... ... @@ -54,28 +63,29 @@
54 63 {
55 64 int ret;
56 65  
  66 + /* Register hooks */
  67 + rawtable_ops = xt_hook_ops_alloc(&packet_raw, ip6table_raw_hook);
  68 + if (IS_ERR(rawtable_ops))
  69 + return PTR_ERR(rawtable_ops);
  70 +
57 71 ret = register_pernet_subsys(&ip6table_raw_net_ops);
58   - if (ret < 0)
  72 + if (ret < 0) {
  73 + kfree(rawtable_ops);
59 74 return ret;
60   -
61   - /* Register hooks */
62   - rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook);
63   - if (IS_ERR(rawtable_ops)) {
64   - ret = PTR_ERR(rawtable_ops);
65   - goto cleanup_table;
66 75 }
67 76  
  77 + ret = ip6table_raw_table_init(&init_net);
  78 + if (ret) {
  79 + unregister_pernet_subsys(&ip6table_raw_net_ops);
  80 + kfree(rawtable_ops);
  81 + }
68 82 return ret;
69   -
70   - cleanup_table:
71   - unregister_pernet_subsys(&ip6table_raw_net_ops);
72   - return ret;
73 83 }
74 84  
75 85 static void __exit ip6table_raw_fini(void)
76 86 {
77   - xt_hook_unlink(&packet_raw, rawtable_ops);
78 87 unregister_pernet_subsys(&ip6table_raw_net_ops);
  88 + kfree(rawtable_ops);
79 89 }
80 90  
81 91 module_init(ip6table_raw_init);
net/ipv6/netfilter/ip6table_security.c
... ... @@ -27,12 +27,15 @@
27 27 (1 << NF_INET_FORWARD) | \
28 28 (1 << NF_INET_LOCAL_OUT)
29 29  
  30 +static int __net_init ip6table_security_table_init(struct net *net);
  31 +
30 32 static const struct xt_table security_table = {
31 33 .name = "security",
32 34 .valid_hooks = SECURITY_VALID_HOOKS,
33 35 .me = THIS_MODULE,
34 36 .af = NFPROTO_IPV6,
35 37 .priority = NF_IP6_PRI_SECURITY,
  38 + .table_init = ip6table_security_table_init,
36 39 };
37 40  
38 41 static unsigned int
39 42  
40 43  
41 44  
42 45  
43 46  
44 47  
... ... @@ -44,26 +47,32 @@
44 47  
45 48 static struct nf_hook_ops *sectbl_ops __read_mostly;
46 49  
47   -static int __net_init ip6table_security_net_init(struct net *net)
  50 +static int __net_init ip6table_security_table_init(struct net *net)
48 51 {
49 52 struct ip6t_replace *repl;
  53 + int ret;
50 54  
  55 + if (net->ipv6.ip6table_security)
  56 + return 0;
  57 +
51 58 repl = ip6t_alloc_initial_table(&security_table);
52 59 if (repl == NULL)
53 60 return -ENOMEM;
54   - net->ipv6.ip6table_security =
55   - ip6t_register_table(net, &security_table, repl);
  61 + ret = ip6t_register_table(net, &security_table, repl, sectbl_ops,
  62 + &net->ipv6.ip6table_security);
56 63 kfree(repl);
57   - return PTR_ERR_OR_ZERO(net->ipv6.ip6table_security);
  64 + return ret;
58 65 }
59 66  
60 67 static void __net_exit ip6table_security_net_exit(struct net *net)
61 68 {
62   - ip6t_unregister_table(net, net->ipv6.ip6table_security);
  69 + if (!net->ipv6.ip6table_security)
  70 + return;
  71 + ip6t_unregister_table(net, net->ipv6.ip6table_security, sectbl_ops);
  72 + net->ipv6.ip6table_security = NULL;
63 73 }
64 74  
65 75 static struct pernet_operations ip6table_security_net_ops = {
66   - .init = ip6table_security_net_init,
67 76 .exit = ip6table_security_net_exit,
68 77 };
69 78  
70 79  
71 80  
72 81  
73 82  
74 83  
75 84  
... ... @@ -71,27 +80,28 @@
71 80 {
72 81 int ret;
73 82  
  83 + sectbl_ops = xt_hook_ops_alloc(&security_table, ip6table_security_hook);
  84 + if (IS_ERR(sectbl_ops))
  85 + return PTR_ERR(sectbl_ops);
  86 +
74 87 ret = register_pernet_subsys(&ip6table_security_net_ops);
75   - if (ret < 0)
  88 + if (ret < 0) {
  89 + kfree(sectbl_ops);
76 90 return ret;
77   -
78   - sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook);
79   - if (IS_ERR(sectbl_ops)) {
80   - ret = PTR_ERR(sectbl_ops);
81   - goto cleanup_table;
82 91 }
83 92  
  93 + ret = ip6table_security_table_init(&init_net);
  94 + if (ret) {
  95 + unregister_pernet_subsys(&ip6table_security_net_ops);
  96 + kfree(sectbl_ops);
  97 + }
84 98 return ret;
85   -
86   -cleanup_table:
87   - unregister_pernet_subsys(&ip6table_security_net_ops);
88   - return ret;
89 99 }
90 100  
91 101 static void __exit ip6table_security_fini(void)
92 102 {
93   - xt_hook_unlink(&security_table, sectbl_ops);
94 103 unregister_pernet_subsys(&ip6table_security_net_ops);
  104 + kfree(sectbl_ops);
95 105 }
96 106  
97 107 module_init(ip6table_security_init);
net/ipv6/netfilter/nft_masq_ipv6.c
... ... @@ -26,7 +26,12 @@
26 26  
27 27 memset(&range, 0, sizeof(range));
28 28 range.flags = priv->flags;
29   -
  29 + if (priv->sreg_proto_min) {
  30 + range.min_proto.all =
  31 + *(__be16 *)&regs->data[priv->sreg_proto_min];
  32 + range.max_proto.all =
  33 + *(__be16 *)&regs->data[priv->sreg_proto_max];
  34 + }
30 35 regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out);
31 36 }
32 37  
net/netfilter/ipvs/ip_vs_app.c
... ... @@ -605,18 +605,14 @@
605 605  
606 606 int __net_init ip_vs_app_net_init(struct netns_ipvs *ipvs)
607 607 {
608   - struct net *net = ipvs->net;
609   -
610 608 INIT_LIST_HEAD(&ipvs->app_list);
611   - proc_create("ip_vs_app", 0, net->proc_net, &ip_vs_app_fops);
  609 + proc_create("ip_vs_app", 0, ipvs->net->proc_net, &ip_vs_app_fops);
612 610 return 0;
613 611 }
614 612  
615 613 void __net_exit ip_vs_app_net_cleanup(struct netns_ipvs *ipvs)
616 614 {
617   - struct net *net = ipvs->net;
618   -
619 615 unregister_ip_vs_app(ipvs, NULL /* all */);
620   - remove_proc_entry("ip_vs_app", net->proc_net);
  616 + remove_proc_entry("ip_vs_app", ipvs->net->proc_net);
621 617 }
net/netfilter/ipvs/ip_vs_ctl.c
... ... @@ -1376,8 +1376,6 @@
1376 1376 struct ip_vs_pe *old_pe;
1377 1377 struct netns_ipvs *ipvs = svc->ipvs;
1378 1378  
1379   - pr_info("%s: enter\n", __func__);
1380   -
1381 1379 /* Count only IPv4 services for old get/setsockopt interface */
1382 1380 if (svc->af == AF_INET)
1383 1381 ipvs->num_services--;
... ... @@ -3947,7 +3945,6 @@
3947 3945  
3948 3946 int __net_init ip_vs_control_net_init(struct netns_ipvs *ipvs)
3949 3947 {
3950   - struct net *net = ipvs->net;
3951 3948 int i, idx;
3952 3949  
3953 3950 /* Initialize rs_table */
... ... @@ -3974,9 +3971,9 @@
3974 3971  
3975 3972 spin_lock_init(&ipvs->tot_stats.lock);
3976 3973  
3977   - proc_create("ip_vs", 0, net->proc_net, &ip_vs_info_fops);
3978   - proc_create("ip_vs_stats", 0, net->proc_net, &ip_vs_stats_fops);
3979   - proc_create("ip_vs_stats_percpu", 0, net->proc_net,
  3974 + proc_create("ip_vs", 0, ipvs->net->proc_net, &ip_vs_info_fops);
  3975 + proc_create("ip_vs_stats", 0, ipvs->net->proc_net, &ip_vs_stats_fops);
  3976 + proc_create("ip_vs_stats_percpu", 0, ipvs->net->proc_net,
3980 3977 &ip_vs_stats_percpu_fops);
3981 3978  
3982 3979 if (ip_vs_control_net_init_sysctl(ipvs))
3983 3980  
... ... @@ -3991,13 +3988,11 @@
3991 3988  
3992 3989 void __net_exit ip_vs_control_net_cleanup(struct netns_ipvs *ipvs)
3993 3990 {
3994   - struct net *net = ipvs->net;
3995   -
3996 3991 ip_vs_trash_cleanup(ipvs);
3997 3992 ip_vs_control_net_cleanup_sysctl(ipvs);
3998   - remove_proc_entry("ip_vs_stats_percpu", net->proc_net);
3999   - remove_proc_entry("ip_vs_stats", net->proc_net);
4000   - remove_proc_entry("ip_vs", net->proc_net);
  3993 + remove_proc_entry("ip_vs_stats_percpu", ipvs->net->proc_net);
  3994 + remove_proc_entry("ip_vs_stats", ipvs->net->proc_net);
  3995 + remove_proc_entry("ip_vs", ipvs->net->proc_net);
4001 3996 free_percpu(ipvs->tot_stats.cpustats);
4002 3997 }
4003 3998  
net/netfilter/nft_masq.c
... ... @@ -17,7 +17,9 @@
17 17 #include <net/netfilter/nft_masq.h>
18 18  
19 19 const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
20   - [NFTA_MASQ_FLAGS] = { .type = NLA_U32 },
  20 + [NFTA_MASQ_FLAGS] = { .type = NLA_U32 },
  21 + [NFTA_MASQ_REG_PROTO_MIN] = { .type = NLA_U32 },
  22 + [NFTA_MASQ_REG_PROTO_MAX] = { .type = NLA_U32 },
21 23 };
22 24 EXPORT_SYMBOL_GPL(nft_masq_policy);
23 25  
... ... @@ -40,6 +42,7 @@
40 42 const struct nft_expr *expr,
41 43 const struct nlattr * const tb[])
42 44 {
  45 + u32 plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
43 46 struct nft_masq *priv = nft_expr_priv(expr);
44 47 int err;
45 48  
46 49  
47 50  
... ... @@ -47,13 +50,33 @@
47 50 if (err)
48 51 return err;
49 52  
50   - if (tb[NFTA_MASQ_FLAGS] == NULL)
51   - return 0;
  53 + if (tb[NFTA_MASQ_FLAGS]) {
  54 + priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
  55 + if (priv->flags & ~NF_NAT_RANGE_MASK)
  56 + return -EINVAL;
  57 + }
52 58  
53   - priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
54   - if (priv->flags & ~NF_NAT_RANGE_MASK)
55   - return -EINVAL;
  59 + if (tb[NFTA_MASQ_REG_PROTO_MIN]) {
  60 + priv->sreg_proto_min =
  61 + nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MIN]);
56 62  
  63 + err = nft_validate_register_load(priv->sreg_proto_min, plen);
  64 + if (err < 0)
  65 + return err;
  66 +
  67 + if (tb[NFTA_MASQ_REG_PROTO_MAX]) {
  68 + priv->sreg_proto_max =
  69 + nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MAX]);
  70 +
  71 + err = nft_validate_register_load(priv->sreg_proto_max,
  72 + plen);
  73 + if (err < 0)
  74 + return err;
  75 + } else {
  76 + priv->sreg_proto_max = priv->sreg_proto_min;
  77 + }
  78 + }
  79 +
57 80 return 0;
58 81 }
59 82 EXPORT_SYMBOL_GPL(nft_masq_init);
60 83  
... ... @@ -62,11 +85,17 @@
62 85 {
63 86 const struct nft_masq *priv = nft_expr_priv(expr);
64 87  
65   - if (priv->flags == 0)
66   - return 0;
67   -
68   - if (nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags)))
  88 + if (priv->flags != 0 &&
  89 + nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags)))
69 90 goto nla_put_failure;
  91 +
  92 + if (priv->sreg_proto_min) {
  93 + if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN,
  94 + priv->sreg_proto_min) ||
  95 + nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MAX,
  96 + priv->sreg_proto_max))
  97 + goto nla_put_failure;
  98 + }
70 99  
71 100 return 0;
72 101  
net/netfilter/nft_meta.c
... ... @@ -28,6 +28,8 @@
28 28  
29 29 #include <uapi/linux/netfilter_bridge.h> /* NF_BR_PRE_ROUTING */
30 30  
  31 +static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state);
  32 +
31 33 void nft_meta_get_eval(const struct nft_expr *expr,
32 34 struct nft_regs *regs,
33 35 const struct nft_pktinfo *pkt)
... ... @@ -181,6 +183,11 @@
181 183 *dest = sock_cgroup_classid(&sk->sk_cgrp_data);
182 184 break;
183 185 #endif
  186 + case NFT_META_PRANDOM: {
  187 + struct rnd_state *state = this_cpu_ptr(&nft_prandom_state);
  188 + *dest = prandom_u32_state(state);
  189 + break;
  190 + }
184 191 default:
185 192 WARN_ON(1);
186 193 goto err;
... ... @@ -276,6 +283,10 @@
276 283 case NFT_META_IIFNAME:
277 284 case NFT_META_OIFNAME:
278 285 len = IFNAMSIZ;
  286 + break;
  287 + case NFT_META_PRANDOM:
  288 + prandom_init_once(&nft_prandom_state);
  289 + len = sizeof(u32);
279 290 break;
280 291 default:
281 292 return -EOPNOTSUPP;
net/netfilter/x_tables.c
... ... @@ -694,12 +694,45 @@
694 694 struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
695 695 const char *name)
696 696 {
697   - struct xt_table *t;
  697 + struct xt_table *t, *found = NULL;
698 698  
699 699 mutex_lock(&xt[af].mutex);
700 700 list_for_each_entry(t, &net->xt.tables[af], list)
701 701 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
702 702 return t;
  703 +
  704 + if (net == &init_net)
  705 + goto out;
  706 +
  707 + /* Table doesn't exist in this netns, re-try init */
  708 + list_for_each_entry(t, &init_net.xt.tables[af], list) {
  709 + if (strcmp(t->name, name))
  710 + continue;
  711 + if (!try_module_get(t->me))
  712 + return NULL;
  713 +
  714 + mutex_unlock(&xt[af].mutex);
  715 + if (t->table_init(net) != 0) {
  716 + module_put(t->me);
  717 + return NULL;
  718 + }
  719 +
  720 + found = t;
  721 +
  722 + mutex_lock(&xt[af].mutex);
  723 + break;
  724 + }
  725 +
  726 + if (!found)
  727 + goto out;
  728 +
  729 + /* and once again: */
  730 + list_for_each_entry(t, &net->xt.tables[af], list)
  731 + if (strcmp(t->name, name) == 0)
  732 + return t;
  733 +
  734 + module_put(found->me);
  735 + out:
703 736 mutex_unlock(&xt[af].mutex);
704 737 return NULL;
705 738 }
706 739  
707 740  
708 741  
... ... @@ -1170,20 +1203,20 @@
1170 1203 #endif /* CONFIG_PROC_FS */
1171 1204  
1172 1205 /**
1173   - * xt_hook_link - set up hooks for a new table
  1206 + * xt_hook_ops_alloc - set up hooks for a new table
1174 1207 * @table: table with metadata needed to set up hooks
1175 1208 * @fn: Hook function
1176 1209 *
1177   - * This function will take care of creating and registering the necessary
1178   - * Netfilter hooks for XT tables.
  1210 + * This function will create the nf_hook_ops that the x_table needs
  1211 + * to hand to xt_hook_link_net().
1179 1212 */
1180   -struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
  1213 +struct nf_hook_ops *
  1214 +xt_hook_ops_alloc(const struct xt_table *table, nf_hookfn *fn)
1181 1215 {
1182 1216 unsigned int hook_mask = table->valid_hooks;
1183 1217 uint8_t i, num_hooks = hweight32(hook_mask);
1184 1218 uint8_t hooknum;
1185 1219 struct nf_hook_ops *ops;
1186   - int ret;
1187 1220  
1188 1221 ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL);
1189 1222 if (ops == NULL)
1190 1223  
... ... @@ -1200,27 +1233,9 @@
1200 1233 ++i;
1201 1234 }
1202 1235  
1203   - ret = nf_register_hooks(ops, num_hooks);
1204   - if (ret < 0) {
1205   - kfree(ops);
1206   - return ERR_PTR(ret);
1207   - }
1208   -
1209 1236 return ops;
1210 1237 }
1211   -EXPORT_SYMBOL_GPL(xt_hook_link);
1212   -
1213   -/**
1214   - * xt_hook_unlink - remove hooks for a table
1215   - * @ops: nf_hook_ops array as returned by nf_hook_link
1216   - * @hook_mask: the very same mask that was passed to nf_hook_link
1217   - */
1218   -void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops)
1219   -{
1220   - nf_unregister_hooks(ops, hweight32(table->valid_hooks));
1221   - kfree(ops);
1222   -}
1223   -EXPORT_SYMBOL_GPL(xt_hook_unlink);
  1238 +EXPORT_SYMBOL_GPL(xt_hook_ops_alloc);
1224 1239  
1225 1240 int xt_proto_init(struct net *net, u_int8_t af)
1226 1241 {
net/netfilter/xt_osf.c
... ... @@ -262,7 +262,6 @@
262 262 if (f->opt[optnum].kind == (*optp)) {
263 263 __u32 len = f->opt[optnum].length;
264 264 const __u8 *optend = optp + len;
265   - int loop_cont = 0;
266 265  
267 266 fmatch = FMATCH_OK;
268 267  
... ... @@ -275,7 +274,6 @@
275 274 mss = ntohs((__force __be16)mss);
276 275 break;
277 276 case OSFOPT_TS:
278   - loop_cont = 1;
279 277 break;
280 278 }
281 279