Commit 2b95efe7f6bb750256a702cc32d33b0cb2cd8223

Authored by Jan Engelhardt
1 parent 2b21e05147

netfilter: xtables: use xt_table for hook instantiation

The respective xt_table structures already have most of the metadata
needed for hook setup. Add a 'priority' field to struct xt_table so
that xt_hook_link() can be called with a reduced number of arguments.

So should we be having more tables in the future, it comes at no
static cost (only runtime, as before) - space saved:
6807373->6806555.

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>

Showing 11 changed files with 121 additions and 250 deletions Side-by-side Diff

include/linux/netfilter/x_tables.h
... ... @@ -361,6 +361,7 @@
361 361 struct module *me;
362 362  
363 363 u_int8_t af; /* address/protocol family */
  364 + int priority; /* hook order */
364 365  
365 366 /* A unique name... */
366 367 const char name[XT_TABLE_MAXNAMELEN];
... ... @@ -521,6 +522,9 @@
521 522 BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
522 523 return ret;
523 524 }
  525 +
  526 +extern struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *);
  527 +extern void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *);
524 528  
525 529 #ifdef CONFIG_COMPAT
526 530 #include <net/compat.h>
net/ipv4/netfilter/arptable_filter.c
... ... @@ -50,6 +50,7 @@
50 50 .valid_hooks = FILTER_VALID_HOOKS,
51 51 .me = THIS_MODULE,
52 52 .af = NFPROTO_ARP,
  53 + .priority = NF_IP_PRI_FILTER,
53 54 };
54 55  
55 56 /* The work comes in here from netfilter.c */
... ... @@ -63,29 +64,7 @@
63 64 return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter);
64 65 }
65 66  
66   -static struct nf_hook_ops arpt_ops[] __read_mostly = {
67   - {
68   - .hook = arptable_filter_hook,
69   - .owner = THIS_MODULE,
70   - .pf = NFPROTO_ARP,
71   - .hooknum = NF_ARP_IN,
72   - .priority = NF_IP_PRI_FILTER,
73   - },
74   - {
75   - .hook = arptable_filter_hook,
76   - .owner = THIS_MODULE,
77   - .pf = NFPROTO_ARP,
78   - .hooknum = NF_ARP_OUT,
79   - .priority = NF_IP_PRI_FILTER,
80   - },
81   - {
82   - .hook = arptable_filter_hook,
83   - .owner = THIS_MODULE,
84   - .pf = NFPROTO_ARP,
85   - .hooknum = NF_ARP_FORWARD,
86   - .priority = NF_IP_PRI_FILTER,
87   - },
88   -};
  67 +static struct nf_hook_ops *arpfilter_ops __read_mostly;
89 68  
90 69 static int __net_init arptable_filter_net_init(struct net *net)
91 70 {
92 71  
... ... @@ -115,9 +94,11 @@
115 94 if (ret < 0)
116 95 return ret;
117 96  
118   - ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
119   - if (ret < 0)
  97 + arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook);
  98 + if (IS_ERR(arpfilter_ops)) {
  99 + ret = PTR_ERR(arpfilter_ops);
120 100 goto cleanup_table;
  101 + }
121 102 return ret;
122 103  
123 104 cleanup_table:
... ... @@ -127,7 +108,7 @@
127 108  
128 109 static void __exit arptable_filter_fini(void)
129 110 {
130   - nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
  111 + xt_hook_unlink(&packet_filter, arpfilter_ops);
131 112 unregister_pernet_subsys(&arptable_filter_net_ops);
132 113 }
133 114  
net/ipv4/netfilter/iptable_filter.c
... ... @@ -58,6 +58,7 @@
58 58 .valid_hooks = FILTER_VALID_HOOKS,
59 59 .me = THIS_MODULE,
60 60 .af = NFPROTO_IPV4,
  61 + .priority = NF_IP_PRI_FILTER,
61 62 };
62 63  
63 64 static unsigned int
... ... @@ -77,29 +78,7 @@
77 78 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter);
78 79 }
79 80  
80   -static struct nf_hook_ops ipt_ops[] __read_mostly = {
81   - {
82   - .hook = iptable_filter_hook,
83   - .owner = THIS_MODULE,
84   - .pf = NFPROTO_IPV4,
85   - .hooknum = NF_INET_LOCAL_IN,
86   - .priority = NF_IP_PRI_FILTER,
87   - },
88   - {
89   - .hook = iptable_filter_hook,
90   - .owner = THIS_MODULE,
91   - .pf = NFPROTO_IPV4,
92   - .hooknum = NF_INET_FORWARD,
93   - .priority = NF_IP_PRI_FILTER,
94   - },
95   - {
96   - .hook = iptable_filter_hook,
97   - .owner = THIS_MODULE,
98   - .pf = NFPROTO_IPV4,
99   - .hooknum = NF_INET_LOCAL_OUT,
100   - .priority = NF_IP_PRI_FILTER,
101   - },
102   -};
  81 +static struct nf_hook_ops *filter_ops __read_mostly;
103 82  
104 83 /* Default to forward because I got too much mail already. */
105 84 static int forward = NF_ACCEPT;
106 85  
... ... @@ -142,9 +121,11 @@
142 121 return ret;
143 122  
144 123 /* Register hooks */
145   - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
146   - if (ret < 0)
  124 + filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook);
  125 + if (IS_ERR(filter_ops)) {
  126 + ret = PTR_ERR(filter_ops);
147 127 goto cleanup_table;
  128 + }
148 129  
149 130 return ret;
150 131  
... ... @@ -155,7 +136,7 @@
155 136  
156 137 static void __exit iptable_filter_fini(void)
157 138 {
158   - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
  139 + xt_hook_unlink(&packet_filter, filter_ops);
159 140 unregister_pernet_subsys(&iptable_filter_net_ops);
160 141 }
161 142  
net/ipv4/netfilter/iptable_mangle.c
... ... @@ -69,6 +69,7 @@
69 69 .valid_hooks = MANGLE_VALID_HOOKS,
70 70 .me = THIS_MODULE,
71 71 .af = NFPROTO_IPV4,
  72 + .priority = NF_IP_PRI_MANGLE,
72 73 };
73 74  
74 75 static unsigned int
... ... @@ -129,43 +130,7 @@
129 130 dev_net(in)->ipv4.iptable_mangle);
130 131 }
131 132  
132   -static struct nf_hook_ops ipt_ops[] __read_mostly = {
133   - {
134   - .hook = iptable_mangle_hook,
135   - .owner = THIS_MODULE,
136   - .pf = NFPROTO_IPV4,
137   - .hooknum = NF_INET_PRE_ROUTING,
138   - .priority = NF_IP_PRI_MANGLE,
139   - },
140   - {
141   - .hook = iptable_mangle_hook,
142   - .owner = THIS_MODULE,
143   - .pf = NFPROTO_IPV4,
144   - .hooknum = NF_INET_LOCAL_IN,
145   - .priority = NF_IP_PRI_MANGLE,
146   - },
147   - {
148   - .hook = iptable_mangle_hook,
149   - .owner = THIS_MODULE,
150   - .pf = NFPROTO_IPV4,
151   - .hooknum = NF_INET_FORWARD,
152   - .priority = NF_IP_PRI_MANGLE,
153   - },
154   - {
155   - .hook = iptable_mangle_hook,
156   - .owner = THIS_MODULE,
157   - .pf = NFPROTO_IPV4,
158   - .hooknum = NF_INET_LOCAL_OUT,
159   - .priority = NF_IP_PRI_MANGLE,
160   - },
161   - {
162   - .hook = iptable_mangle_hook,
163   - .owner = THIS_MODULE,
164   - .pf = NFPROTO_IPV4,
165   - .hooknum = NF_INET_POST_ROUTING,
166   - .priority = NF_IP_PRI_MANGLE,
167   - },
168   -};
  133 +static struct nf_hook_ops *mangle_ops __read_mostly;
169 134  
170 135 static int __net_init iptable_mangle_net_init(struct net *net)
171 136 {
172 137  
... ... @@ -196,9 +161,11 @@
196 161 return ret;
197 162  
198 163 /* Register hooks */
199   - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
200   - if (ret < 0)
  164 + mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook);
  165 + if (IS_ERR(mangle_ops)) {
  166 + ret = PTR_ERR(mangle_ops);
201 167 goto cleanup_table;
  168 + }
202 169  
203 170 return ret;
204 171  
... ... @@ -209,7 +176,7 @@
209 176  
210 177 static void __exit iptable_mangle_fini(void)
211 178 {
212   - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
  179 + xt_hook_unlink(&packet_mangler, mangle_ops);
213 180 unregister_pernet_subsys(&iptable_mangle_net_ops);
214 181 }
215 182  
net/ipv4/netfilter/iptable_raw.c
... ... @@ -41,6 +41,7 @@
41 41 .valid_hooks = RAW_VALID_HOOKS,
42 42 .me = THIS_MODULE,
43 43 .af = NFPROTO_IPV4,
  44 + .priority = NF_IP_PRI_RAW,
44 45 };
45 46  
46 47 /* The work comes in here from netfilter.c. */
... ... @@ -61,23 +62,7 @@
61 62 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw);
62 63 }
63 64  
64   -/* 'raw' is the very first table. */
65   -static struct nf_hook_ops ipt_ops[] __read_mostly = {
66   - {
67   - .hook = iptable_raw_hook,
68   - .pf = NFPROTO_IPV4,
69   - .hooknum = NF_INET_PRE_ROUTING,
70   - .priority = NF_IP_PRI_RAW,
71   - .owner = THIS_MODULE,
72   - },
73   - {
74   - .hook = iptable_raw_hook,
75   - .pf = NFPROTO_IPV4,
76   - .hooknum = NF_INET_LOCAL_OUT,
77   - .priority = NF_IP_PRI_RAW,
78   - .owner = THIS_MODULE,
79   - },
80   -};
  65 +static struct nf_hook_ops *rawtable_ops __read_mostly;
81 66  
82 67 static int __net_init iptable_raw_net_init(struct net *net)
83 68 {
84 69  
... ... @@ -108,9 +93,11 @@
108 93 return ret;
109 94  
110 95 /* Register hooks */
111   - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
112   - if (ret < 0)
  96 + rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook);
  97 + if (IS_ERR(rawtable_ops)) {
  98 + ret = PTR_ERR(rawtable_ops);
113 99 goto cleanup_table;
  100 + }
114 101  
115 102 return ret;
116 103  
... ... @@ -121,7 +108,7 @@
121 108  
122 109 static void __exit iptable_raw_fini(void)
123 110 {
124   - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
  111 + xt_hook_unlink(&packet_raw, rawtable_ops);
125 112 unregister_pernet_subsys(&iptable_raw_net_ops);
126 113 }
127 114  
net/ipv4/netfilter/iptable_security.c
... ... @@ -62,6 +62,7 @@
62 62 .valid_hooks = SECURITY_VALID_HOOKS,
63 63 .me = THIS_MODULE,
64 64 .af = NFPROTO_IPV4,
  65 + .priority = NF_IP_PRI_SECURITY,
65 66 };
66 67  
67 68 static unsigned int
... ... @@ -82,29 +83,7 @@
82 83 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security);
83 84 }
84 85  
85   -static struct nf_hook_ops ipt_ops[] __read_mostly = {
86   - {
87   - .hook = iptable_security_hook,
88   - .owner = THIS_MODULE,
89   - .pf = NFPROTO_IPV4,
90   - .hooknum = NF_INET_LOCAL_IN,
91   - .priority = NF_IP_PRI_SECURITY,
92   - },
93   - {
94   - .hook = iptable_security_hook,
95   - .owner = THIS_MODULE,
96   - .pf = NFPROTO_IPV4,
97   - .hooknum = NF_INET_FORWARD,
98   - .priority = NF_IP_PRI_SECURITY,
99   - },
100   - {
101   - .hook = iptable_security_hook,
102   - .owner = THIS_MODULE,
103   - .pf = NFPROTO_IPV4,
104   - .hooknum = NF_INET_LOCAL_OUT,
105   - .priority = NF_IP_PRI_SECURITY,
106   - },
107   -};
  86 +static struct nf_hook_ops *sectbl_ops __read_mostly;
108 87  
109 88 static int __net_init iptable_security_net_init(struct net *net)
110 89 {
111 90  
... ... @@ -135,9 +114,11 @@
135 114 if (ret < 0)
136 115 return ret;
137 116  
138   - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
139   - if (ret < 0)
  117 + sectbl_ops = xt_hook_link(&security_table, iptable_security_hook);
  118 + if (IS_ERR(sectbl_ops)) {
  119 + ret = PTR_ERR(sectbl_ops);
140 120 goto cleanup_table;
  121 + }
141 122  
142 123 return ret;
143 124  
... ... @@ -148,7 +129,7 @@
148 129  
149 130 static void __exit iptable_security_fini(void)
150 131 {
151   - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
  132 + xt_hook_unlink(&security_table, sectbl_ops);
152 133 unregister_pernet_subsys(&iptable_security_net_ops);
153 134 }
154 135  
net/ipv6/netfilter/ip6table_filter.c
... ... @@ -56,6 +56,7 @@
56 56 .valid_hooks = FILTER_VALID_HOOKS,
57 57 .me = THIS_MODULE,
58 58 .af = NFPROTO_IPV6,
  59 + .priority = NF_IP6_PRI_FILTER,
59 60 };
60 61  
61 62 /* The work comes in here from netfilter.c. */
... ... @@ -69,29 +70,7 @@
69 70 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter);
70 71 }
71 72  
72   -static struct nf_hook_ops ip6t_ops[] __read_mostly = {
73   - {
74   - .hook = ip6table_filter_hook,
75   - .owner = THIS_MODULE,
76   - .pf = NFPROTO_IPV6,
77   - .hooknum = NF_INET_LOCAL_IN,
78   - .priority = NF_IP6_PRI_FILTER,
79   - },
80   - {
81   - .hook = ip6table_filter_hook,
82   - .owner = THIS_MODULE,
83   - .pf = NFPROTO_IPV6,
84   - .hooknum = NF_INET_FORWARD,
85   - .priority = NF_IP6_PRI_FILTER,
86   - },
87   - {
88   - .hook = ip6table_filter_hook,
89   - .owner = THIS_MODULE,
90   - .pf = NFPROTO_IPV6,
91   - .hooknum = NF_INET_LOCAL_OUT,
92   - .priority = NF_IP6_PRI_FILTER,
93   - },
94   -};
  73 +static struct nf_hook_ops *filter_ops __read_mostly;
95 74  
96 75 /* Default to forward because I got too much mail already. */
97 76 static int forward = NF_ACCEPT;
98 77  
... ... @@ -134,9 +113,11 @@
134 113 return ret;
135 114  
136 115 /* Register hooks */
137   - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
138   - if (ret < 0)
  116 + filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook);
  117 + if (IS_ERR(filter_ops)) {
  118 + ret = PTR_ERR(filter_ops);
139 119 goto cleanup_table;
  120 + }
140 121  
141 122 return ret;
142 123  
... ... @@ -147,7 +128,7 @@
147 128  
148 129 static void __exit ip6table_filter_fini(void)
149 130 {
150   - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
  131 + xt_hook_unlink(&packet_filter, filter_ops);
151 132 unregister_pernet_subsys(&ip6table_filter_net_ops);
152 133 }
153 134  
net/ipv6/netfilter/ip6table_mangle.c
... ... @@ -62,6 +62,7 @@
62 62 .valid_hooks = MANGLE_VALID_HOOKS,
63 63 .me = THIS_MODULE,
64 64 .af = NFPROTO_IPV6,
  65 + .priority = NF_IP6_PRI_MANGLE,
65 66 };
66 67  
67 68 static unsigned int
... ... @@ -122,44 +123,7 @@
122 123 dev_net(in)->ipv6.ip6table_mangle);
123 124 }
124 125  
125   -static struct nf_hook_ops ip6t_ops[] __read_mostly = {
126   - {
127   - .hook = ip6table_mangle_hook,
128   - .owner = THIS_MODULE,
129   - .pf = NFPROTO_IPV6,
130   - .hooknum = NF_INET_PRE_ROUTING,
131   - .priority = NF_IP6_PRI_MANGLE,
132   - },
133   - {
134   - .hook = ip6table_mangle_hook,
135   - .owner = THIS_MODULE,
136   - .pf = NFPROTO_IPV6,
137   - .hooknum = NF_INET_LOCAL_IN,
138   - .priority = NF_IP6_PRI_MANGLE,
139   - },
140   - {
141   - .hook = ip6table_mangle_hook,
142   - .owner = THIS_MODULE,
143   - .pf = NFPROTO_IPV6,
144   - .hooknum = NF_INET_FORWARD,
145   - .priority = NF_IP6_PRI_MANGLE,
146   - },
147   - {
148   - .hook = ip6table_mangle_hook,
149   - .owner = THIS_MODULE,
150   - .pf = NFPROTO_IPV6,
151   - .hooknum = NF_INET_LOCAL_OUT,
152   - .priority = NF_IP6_PRI_MANGLE,
153   - },
154   - {
155   - .hook = ip6table_mangle_hook,
156   - .owner = THIS_MODULE,
157   - .pf = NFPROTO_IPV6,
158   - .hooknum = NF_INET_POST_ROUTING,
159   - .priority = NF_IP6_PRI_MANGLE,
160   - },
161   -};
162   -
  126 +static struct nf_hook_ops *mangle_ops __read_mostly;
163 127 static int __net_init ip6table_mangle_net_init(struct net *net)
164 128 {
165 129 /* Register table */
166 130  
... ... @@ -189,9 +153,11 @@
189 153 return ret;
190 154  
191 155 /* Register hooks */
192   - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
193   - if (ret < 0)
  156 + mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook);
  157 + if (IS_ERR(mangle_ops)) {
  158 + ret = PTR_ERR(mangle_ops);
194 159 goto cleanup_table;
  160 + }
195 161  
196 162 return ret;
197 163  
... ... @@ -202,7 +168,7 @@
202 168  
203 169 static void __exit ip6table_mangle_fini(void)
204 170 {
205   - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
  171 + xt_hook_unlink(&packet_mangler, mangle_ops);
206 172 unregister_pernet_subsys(&ip6table_mangle_net_ops);
207 173 }
208 174  
net/ipv6/netfilter/ip6table_raw.c
... ... @@ -40,6 +40,7 @@
40 40 .valid_hooks = RAW_VALID_HOOKS,
41 41 .me = THIS_MODULE,
42 42 .af = NFPROTO_IPV6,
  43 + .priority = NF_IP6_PRI_FIRST,
43 44 };
44 45  
45 46 /* The work comes in here from netfilter.c. */
... ... @@ -53,22 +54,7 @@
53 54 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw);
54 55 }
55 56  
56   -static struct nf_hook_ops ip6t_ops[] __read_mostly = {
57   - {
58   - .hook = ip6table_raw_hook,
59   - .pf = NFPROTO_IPV6,
60   - .hooknum = NF_INET_PRE_ROUTING,
61   - .priority = NF_IP6_PRI_FIRST,
62   - .owner = THIS_MODULE,
63   - },
64   - {
65   - .hook = ip6table_raw_hook,
66   - .pf = NFPROTO_IPV6,
67   - .hooknum = NF_INET_LOCAL_OUT,
68   - .priority = NF_IP6_PRI_FIRST,
69   - .owner = THIS_MODULE,
70   - },
71   -};
  57 +static struct nf_hook_ops *rawtable_ops __read_mostly;
72 58  
73 59 static int __net_init ip6table_raw_net_init(struct net *net)
74 60 {
75 61  
... ... @@ -99,9 +85,11 @@
99 85 return ret;
100 86  
101 87 /* Register hooks */
102   - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
103   - if (ret < 0)
  88 + rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook);
  89 + if (IS_ERR(rawtable_ops)) {
  90 + ret = PTR_ERR(rawtable_ops);
104 91 goto cleanup_table;
  92 + }
105 93  
106 94 return ret;
107 95  
... ... @@ -112,7 +100,7 @@
112 100  
113 101 static void __exit ip6table_raw_fini(void)
114 102 {
115   - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
  103 + xt_hook_unlink(&packet_raw, rawtable_ops);
116 104 unregister_pernet_subsys(&ip6table_raw_net_ops);
117 105 }
118 106  
net/ipv6/netfilter/ip6table_security.c
... ... @@ -61,6 +61,7 @@
61 61 .valid_hooks = SECURITY_VALID_HOOKS,
62 62 .me = THIS_MODULE,
63 63 .af = NFPROTO_IPV6,
  64 + .priority = NF_IP6_PRI_SECURITY,
64 65 };
65 66  
66 67 static unsigned int
... ... @@ -74,29 +75,7 @@
74 75 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security);
75 76 }
76 77  
77   -static struct nf_hook_ops ip6t_ops[] __read_mostly = {
78   - {
79   - .hook = ip6table_security_hook,
80   - .owner = THIS_MODULE,
81   - .pf = NFPROTO_IPV6,
82   - .hooknum = NF_INET_LOCAL_IN,
83   - .priority = NF_IP6_PRI_SECURITY,
84   - },
85   - {
86   - .hook = ip6table_security_hook,
87   - .owner = THIS_MODULE,
88   - .pf = NFPROTO_IPV6,
89   - .hooknum = NF_INET_FORWARD,
90   - .priority = NF_IP6_PRI_SECURITY,
91   - },
92   - {
93   - .hook = ip6table_security_hook,
94   - .owner = THIS_MODULE,
95   - .pf = NFPROTO_IPV6,
96   - .hooknum = NF_INET_LOCAL_OUT,
97   - .priority = NF_IP6_PRI_SECURITY,
98   - },
99   -};
  78 +static struct nf_hook_ops *sectbl_ops __read_mostly;
100 79  
101 80 static int __net_init ip6table_security_net_init(struct net *net)
102 81 {
103 82  
... ... @@ -127,9 +106,11 @@
127 106 if (ret < 0)
128 107 return ret;
129 108  
130   - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
131   - if (ret < 0)
  109 + sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook);
  110 + if (IS_ERR(sectbl_ops)) {
  111 + ret = PTR_ERR(sectbl_ops);
132 112 goto cleanup_table;
  113 + }
133 114  
134 115 return ret;
135 116  
... ... @@ -140,7 +121,7 @@
140 121  
141 122 static void __exit ip6table_security_fini(void)
142 123 {
143   - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
  124 + xt_hook_unlink(&security_table, sectbl_ops);
144 125 unregister_pernet_subsys(&ip6table_security_net_ops);
145 126 }
146 127  
net/netfilter/x_tables.c
... ... @@ -1091,6 +1091,60 @@
1091 1091  
1092 1092 #endif /* CONFIG_PROC_FS */
1093 1093  
  1094 +/**
  1095 + * xt_hook_link - set up hooks for a new table
  1096 + * @table: table with metadata needed to set up hooks
  1097 + * @fn: Hook function
  1098 + *
  1099 + * This function will take care of creating and registering the necessary
  1100 + * Netfilter hooks for XT tables.
  1101 + */
  1102 +struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
  1103 +{
  1104 + unsigned int hook_mask = table->valid_hooks;
  1105 + uint8_t i, num_hooks = hweight32(hook_mask);
  1106 + uint8_t hooknum;
  1107 + struct nf_hook_ops *ops;
  1108 + int ret;
  1109 +
  1110 + ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL);
  1111 + if (ops == NULL)
  1112 + return ERR_PTR(-ENOMEM);
  1113 +
  1114 + for (i = 0, hooknum = 0; i < num_hooks && hook_mask != 0;
  1115 + hook_mask >>= 1, ++hooknum) {
  1116 + if (!(hook_mask & 1))
  1117 + continue;
  1118 + ops[i].hook = fn;
  1119 + ops[i].owner = table->me;
  1120 + ops[i].pf = table->af;
  1121 + ops[i].hooknum = hooknum;
  1122 + ops[i].priority = table->priority;
  1123 + ++i;
  1124 + }
  1125 +
  1126 + ret = nf_register_hooks(ops, num_hooks);
  1127 + if (ret < 0) {
  1128 + kfree(ops);
  1129 + return ERR_PTR(ret);
  1130 + }
  1131 +
  1132 + return ops;
  1133 +}
  1134 +EXPORT_SYMBOL_GPL(xt_hook_link);
  1135 +
  1136 +/**
  1137 + * xt_hook_unlink - remove hooks for a table
  1138 + * @ops: nf_hook_ops array as returned by nf_hook_link
  1139 + * @hook_mask: the very same mask that was passed to nf_hook_link
  1140 + */
  1141 +void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops)
  1142 +{
  1143 + nf_unregister_hooks(ops, hweight32(table->valid_hooks));
  1144 + kfree(ops);
  1145 +}
  1146 +EXPORT_SYMBOL_GPL(xt_hook_unlink);
  1147 +
1094 1148 int xt_proto_init(struct net *net, u_int8_t af)
1095 1149 {
1096 1150 #ifdef CONFIG_PROC_FS