diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-08-27 20:53:14 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-09-03 07:32:48 -0400 |
commit | 236df005614bea6a2f9afa9867e3bdfc206c6291 (patch) | |
tree | 89bbe58ab9299a508589775f8ad184223889af7c | |
parent | 6703aa74ad1ba2e598bb49a37f7518da1195bacb (diff) |
netfilter: xt_CT: refactorize xt_ct_tg_check
This patch adds xt_ct_set_helper and xt_ct_set_timeout to reduce
the size of xt_ct_tg_check.
This aims to improve code mantainability by splitting xt_ct_tg_check
in smaller chunks.
Suggested by Eric Dumazet.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | net/netfilter/xt_CT.c | 262 |
1 files changed, 126 insertions, 136 deletions
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 116018560c60..16c712563860 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
@@ -72,14 +72,44 @@ static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) | |||
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | 74 | ||
75 | static int | ||
76 | xt_ct_set_helper(struct nf_conn *ct, const char *helper_name, | ||
77 | const struct xt_tgchk_param *par) | ||
78 | { | ||
79 | struct nf_conntrack_helper *helper; | ||
80 | struct nf_conn_help *help; | ||
81 | u8 proto; | ||
82 | |||
83 | proto = xt_ct_find_proto(par); | ||
84 | if (!proto) { | ||
85 | pr_info("You must specify a L4 protocol, and not use " | ||
86 | "inversions on it.\n"); | ||
87 | return -ENOENT; | ||
88 | } | ||
89 | |||
90 | helper = nf_conntrack_helper_try_module_get(helper_name, par->family, | ||
91 | proto); | ||
92 | if (helper == NULL) { | ||
93 | pr_info("No such helper \"%s\"\n", helper_name); | ||
94 | return -ENOENT; | ||
95 | } | ||
96 | |||
97 | help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL); | ||
98 | if (help == NULL) { | ||
99 | module_put(helper->me); | ||
100 | return -ENOMEM; | ||
101 | } | ||
102 | |||
103 | help->helper = helper; | ||
104 | return 0; | ||
105 | } | ||
106 | |||
75 | static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) | 107 | static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) |
76 | { | 108 | { |
77 | struct xt_ct_target_info *info = par->targinfo; | 109 | struct xt_ct_target_info *info = par->targinfo; |
78 | struct nf_conntrack_tuple t; | 110 | struct nf_conntrack_tuple t; |
79 | struct nf_conn_help *help; | ||
80 | struct nf_conn *ct; | 111 | struct nf_conn *ct; |
81 | int ret = 0; | 112 | int ret; |
82 | u8 proto; | ||
83 | 113 | ||
84 | if (info->flags & ~XT_CT_NOTRACK) | 114 | if (info->flags & ~XT_CT_NOTRACK) |
85 | return -EINVAL; | 115 | return -EINVAL; |
@@ -112,31 +142,9 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) | |||
112 | goto err3; | 142 | goto err3; |
113 | 143 | ||
114 | if (info->helper[0]) { | 144 | if (info->helper[0]) { |
115 | struct nf_conntrack_helper *helper; | 145 | ret = xt_ct_set_helper(ct, info->helper, par); |
116 | 146 | if (ret < 0) | |
117 | ret = -ENOENT; | ||
118 | proto = xt_ct_find_proto(par); | ||
119 | if (!proto) { | ||
120 | pr_info("You must specify a L4 protocol, " | ||
121 | "and not use inversions on it.\n"); | ||
122 | goto err3; | ||
123 | } | ||
124 | |||
125 | ret = -ENOENT; | ||
126 | helper = nf_conntrack_helper_try_module_get(info->helper, | ||
127 | par->family, | ||
128 | proto); | ||
129 | if (helper == NULL) { | ||
130 | pr_info("No such helper \"%s\"\n", info->helper); | ||
131 | goto err3; | ||
132 | } | ||
133 | |||
134 | ret = -ENOMEM; | ||
135 | help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL); | ||
136 | if (help == NULL) | ||
137 | goto err3; | 147 | goto err3; |
138 | |||
139 | help->helper = helper; | ||
140 | } | 148 | } |
141 | 149 | ||
142 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); | 150 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); |
@@ -164,17 +172,77 @@ static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout) | |||
164 | } | 172 | } |
165 | #endif | 173 | #endif |
166 | 174 | ||
175 | static int | ||
176 | xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, | ||
177 | const char *timeout_name) | ||
178 | { | ||
179 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | ||
180 | typeof(nf_ct_timeout_find_get_hook) timeout_find_get; | ||
181 | struct ctnl_timeout *timeout; | ||
182 | struct nf_conn_timeout *timeout_ext; | ||
183 | const struct ipt_entry *e = par->entryinfo; | ||
184 | struct nf_conntrack_l4proto *l4proto; | ||
185 | int ret = 0; | ||
186 | |||
187 | rcu_read_lock(); | ||
188 | timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); | ||
189 | if (timeout_find_get == NULL) { | ||
190 | ret = -ENOENT; | ||
191 | pr_info("Timeout policy base is empty\n"); | ||
192 | goto out; | ||
193 | } | ||
194 | |||
195 | if (e->ip.invflags & IPT_INV_PROTO) { | ||
196 | ret = -EINVAL; | ||
197 | pr_info("You cannot use inversion on L4 protocol\n"); | ||
198 | goto out; | ||
199 | } | ||
200 | |||
201 | timeout = timeout_find_get(timeout_name); | ||
202 | if (timeout == NULL) { | ||
203 | ret = -ENOENT; | ||
204 | pr_info("No such timeout policy \"%s\"\n", timeout_name); | ||
205 | goto out; | ||
206 | } | ||
207 | |||
208 | if (timeout->l3num != par->family) { | ||
209 | ret = -EINVAL; | ||
210 | pr_info("Timeout policy `%s' can only be used by L3 protocol " | ||
211 | "number %d\n", timeout_name, timeout->l3num); | ||
212 | goto err_put_timeout; | ||
213 | } | ||
214 | /* Make sure the timeout policy matches any existing protocol tracker, | ||
215 | * otherwise default to generic. | ||
216 | */ | ||
217 | l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto); | ||
218 | if (timeout->l4proto->l4proto != l4proto->l4proto) { | ||
219 | ret = -EINVAL; | ||
220 | pr_info("Timeout policy `%s' can only be used by L4 protocol " | ||
221 | "number %d\n", | ||
222 | timeout_name, timeout->l4proto->l4proto); | ||
223 | goto err_put_timeout; | ||
224 | } | ||
225 | timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); | ||
226 | if (timeout_ext == NULL) | ||
227 | ret = -ENOMEM; | ||
228 | |||
229 | err_put_timeout: | ||
230 | __xt_ct_tg_timeout_put(timeout); | ||
231 | out: | ||
232 | rcu_read_unlock(); | ||
233 | return ret; | ||
234 | #else | ||
235 | return -EOPNOTSUPP; | ||
236 | #endif | ||
237 | } | ||
238 | |||
167 | static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) | 239 | static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) |
168 | { | 240 | { |
169 | struct xt_ct_target_info_v1 *info = par->targinfo; | 241 | struct xt_ct_target_info_v1 *info = par->targinfo; |
170 | struct nf_conntrack_tuple t; | 242 | struct nf_conntrack_tuple t; |
171 | struct nf_conn_help *help; | ||
172 | struct nf_conn *ct; | 243 | struct nf_conn *ct; |
173 | int ret = 0; | 244 | int ret; |
174 | u8 proto; | 245 | |
175 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | ||
176 | struct ctnl_timeout *timeout; | ||
177 | #endif | ||
178 | if (info->flags & ~XT_CT_NOTRACK) | 246 | if (info->flags & ~XT_CT_NOTRACK) |
179 | return -EINVAL; | 247 | return -EINVAL; |
180 | 248 | ||
@@ -206,93 +274,16 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) | |||
206 | goto err3; | 274 | goto err3; |
207 | 275 | ||
208 | if (info->helper[0]) { | 276 | if (info->helper[0]) { |
209 | struct nf_conntrack_helper *helper; | 277 | ret = xt_ct_set_helper(ct, info->helper, par); |
210 | 278 | if (ret < 0) | |
211 | ret = -ENOENT; | ||
212 | proto = xt_ct_find_proto(par); | ||
213 | if (!proto) { | ||
214 | pr_info("You must specify a L4 protocol, " | ||
215 | "and not use inversions on it.\n"); | ||
216 | goto err3; | ||
217 | } | ||
218 | |||
219 | ret = -ENOENT; | ||
220 | helper = nf_conntrack_helper_try_module_get(info->helper, | ||
221 | par->family, | ||
222 | proto); | ||
223 | if (helper == NULL) { | ||
224 | pr_info("No such helper \"%s\"\n", info->helper); | ||
225 | goto err3; | ||
226 | } | ||
227 | |||
228 | ret = -ENOMEM; | ||
229 | help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL); | ||
230 | if (help == NULL) | ||
231 | goto err3; | 279 | goto err3; |
232 | |||
233 | help->helper = helper; | ||
234 | } | 280 | } |
235 | 281 | ||
236 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | ||
237 | if (info->timeout[0]) { | 282 | if (info->timeout[0]) { |
238 | typeof(nf_ct_timeout_find_get_hook) timeout_find_get; | 283 | ret = xt_ct_set_timeout(ct, par, info->timeout); |
239 | struct nf_conn_timeout *timeout_ext; | 284 | if (ret < 0) |
240 | 285 | goto err3; | |
241 | rcu_read_lock(); | ||
242 | timeout_find_get = | ||
243 | rcu_dereference(nf_ct_timeout_find_get_hook); | ||
244 | |||
245 | if (timeout_find_get) { | ||
246 | const struct ipt_entry *e = par->entryinfo; | ||
247 | struct nf_conntrack_l4proto *l4proto; | ||
248 | |||
249 | if (e->ip.invflags & IPT_INV_PROTO) { | ||
250 | ret = -EINVAL; | ||
251 | pr_info("You cannot use inversion on " | ||
252 | "L4 protocol\n"); | ||
253 | goto err4; | ||
254 | } | ||
255 | timeout = timeout_find_get(info->timeout); | ||
256 | if (timeout == NULL) { | ||
257 | ret = -ENOENT; | ||
258 | pr_info("No such timeout policy \"%s\"\n", | ||
259 | info->timeout); | ||
260 | goto err4; | ||
261 | } | ||
262 | if (timeout->l3num != par->family) { | ||
263 | ret = -EINVAL; | ||
264 | pr_info("Timeout policy `%s' can only be " | ||
265 | "used by L3 protocol number %d\n", | ||
266 | info->timeout, timeout->l3num); | ||
267 | goto err5; | ||
268 | } | ||
269 | /* Make sure the timeout policy matches any existing | ||
270 | * protocol tracker, otherwise default to generic. | ||
271 | */ | ||
272 | l4proto = __nf_ct_l4proto_find(par->family, | ||
273 | e->ip.proto); | ||
274 | if (timeout->l4proto->l4proto != l4proto->l4proto) { | ||
275 | ret = -EINVAL; | ||
276 | pr_info("Timeout policy `%s' can only be " | ||
277 | "used by L4 protocol number %d\n", | ||
278 | info->timeout, | ||
279 | timeout->l4proto->l4proto); | ||
280 | goto err5; | ||
281 | } | ||
282 | timeout_ext = nf_ct_timeout_ext_add(ct, timeout, | ||
283 | GFP_ATOMIC); | ||
284 | if (timeout_ext == NULL) { | ||
285 | ret = -ENOMEM; | ||
286 | goto err5; | ||
287 | } | ||
288 | } else { | ||
289 | ret = -ENOENT; | ||
290 | pr_info("Timeout policy base is empty\n"); | ||
291 | goto err4; | ||
292 | } | ||
293 | rcu_read_unlock(); | ||
294 | } | 286 | } |
295 | #endif | ||
296 | 287 | ||
297 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); | 288 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); |
298 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); | 289 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); |
@@ -300,12 +291,6 @@ out: | |||
300 | info->ct = ct; | 291 | info->ct = ct; |
301 | return 0; | 292 | return 0; |
302 | 293 | ||
303 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | ||
304 | err5: | ||
305 | __xt_ct_tg_timeout_put(timeout); | ||
306 | err4: | ||
307 | rcu_read_unlock(); | ||
308 | #endif | ||
309 | err3: | 294 | err3: |
310 | nf_conntrack_free(ct); | 295 | nf_conntrack_free(ct); |
311 | err2: | 296 | err2: |
@@ -330,15 +315,30 @@ static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) | |||
330 | nf_ct_put(info->ct); | 315 | nf_ct_put(info->ct); |
331 | } | 316 | } |
332 | 317 | ||
333 | static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | 318 | static void xt_ct_destroy_timeout(struct nf_conn *ct) |
334 | { | 319 | { |
335 | struct xt_ct_target_info_v1 *info = par->targinfo; | ||
336 | struct nf_conn *ct = info->ct; | ||
337 | struct nf_conn_help *help; | ||
338 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 320 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
339 | struct nf_conn_timeout *timeout_ext; | 321 | struct nf_conn_timeout *timeout_ext; |
340 | typeof(nf_ct_timeout_put_hook) timeout_put; | 322 | typeof(nf_ct_timeout_put_hook) timeout_put; |
323 | |||
324 | rcu_read_lock(); | ||
325 | timeout_put = rcu_dereference(nf_ct_timeout_put_hook); | ||
326 | |||
327 | if (timeout_put) { | ||
328 | timeout_ext = nf_ct_timeout_find(ct); | ||
329 | if (timeout_ext) | ||
330 | timeout_put(timeout_ext->timeout); | ||
331 | } | ||
332 | rcu_read_unlock(); | ||
341 | #endif | 333 | #endif |
334 | } | ||
335 | |||
336 | static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | ||
337 | { | ||
338 | struct xt_ct_target_info_v1 *info = par->targinfo; | ||
339 | struct nf_conn *ct = info->ct; | ||
340 | struct nf_conn_help *help; | ||
341 | |||
342 | if (!nf_ct_is_untracked(ct)) { | 342 | if (!nf_ct_is_untracked(ct)) { |
343 | help = nfct_help(ct); | 343 | help = nfct_help(ct); |
344 | if (help) | 344 | if (help) |
@@ -346,17 +346,7 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | |||
346 | 346 | ||
347 | nf_ct_l3proto_module_put(par->family); | 347 | nf_ct_l3proto_module_put(par->family); |
348 | 348 | ||
349 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 349 | xt_ct_destroy_timeout(ct); |
350 | rcu_read_lock(); | ||
351 | timeout_put = rcu_dereference(nf_ct_timeout_put_hook); | ||
352 | |||
353 | if (timeout_put) { | ||
354 | timeout_ext = nf_ct_timeout_find(ct); | ||
355 | if (timeout_ext) | ||
356 | timeout_put(timeout_ext->timeout); | ||
357 | } | ||
358 | rcu_read_unlock(); | ||
359 | #endif | ||
360 | } | 350 | } |
361 | nf_ct_put(info->ct); | 351 | nf_ct_put(info->ct); |
362 | } | 352 | } |