diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 109 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_queue.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 172 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_MASQUERADE.c | 12 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 17 |
5 files changed, 149 insertions, 163 deletions
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 831fe1879dc0..7505dff4ffdf 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -231,6 +231,12 @@ static inline struct arpt_entry *get_entry(void *base, unsigned int offset) | |||
231 | return (struct arpt_entry *)(base + offset); | 231 | return (struct arpt_entry *)(base + offset); |
232 | } | 232 | } |
233 | 233 | ||
234 | static inline __pure | ||
235 | struct arpt_entry *arpt_next_entry(const struct arpt_entry *entry) | ||
236 | { | ||
237 | return (void *)entry + entry->next_offset; | ||
238 | } | ||
239 | |||
234 | unsigned int arpt_do_table(struct sk_buff *skb, | 240 | unsigned int arpt_do_table(struct sk_buff *skb, |
235 | unsigned int hook, | 241 | unsigned int hook, |
236 | const struct net_device *in, | 242 | const struct net_device *in, |
@@ -267,67 +273,64 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
267 | 273 | ||
268 | arp = arp_hdr(skb); | 274 | arp = arp_hdr(skb); |
269 | do { | 275 | do { |
270 | if (arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { | 276 | struct arpt_entry_target *t; |
271 | struct arpt_entry_target *t; | 277 | int hdr_len; |
272 | int hdr_len; | ||
273 | |||
274 | hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + | ||
275 | (2 * skb->dev->addr_len); | ||
276 | 278 | ||
277 | ADD_COUNTER(e->counters, hdr_len, 1); | 279 | if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { |
280 | e = arpt_next_entry(e); | ||
281 | continue; | ||
282 | } | ||
278 | 283 | ||
279 | t = arpt_get_target(e); | 284 | hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + |
285 | (2 * skb->dev->addr_len); | ||
286 | ADD_COUNTER(e->counters, hdr_len, 1); | ||
280 | 287 | ||
281 | /* Standard target? */ | 288 | t = arpt_get_target(e); |
282 | if (!t->u.kernel.target->target) { | ||
283 | int v; | ||
284 | 289 | ||
285 | v = ((struct arpt_standard_target *)t)->verdict; | 290 | /* Standard target? */ |
286 | if (v < 0) { | 291 | if (!t->u.kernel.target->target) { |
287 | /* Pop from stack? */ | 292 | int v; |
288 | if (v != ARPT_RETURN) { | ||
289 | verdict = (unsigned)(-v) - 1; | ||
290 | break; | ||
291 | } | ||
292 | e = back; | ||
293 | back = get_entry(table_base, | ||
294 | back->comefrom); | ||
295 | continue; | ||
296 | } | ||
297 | if (table_base + v | ||
298 | != (void *)e + e->next_offset) { | ||
299 | /* Save old back ptr in next entry */ | ||
300 | struct arpt_entry *next | ||
301 | = (void *)e + e->next_offset; | ||
302 | next->comefrom = | ||
303 | (void *)back - table_base; | ||
304 | |||
305 | /* set back pointer to next entry */ | ||
306 | back = next; | ||
307 | } | ||
308 | 293 | ||
309 | e = get_entry(table_base, v); | 294 | v = ((struct arpt_standard_target *)t)->verdict; |
310 | } else { | 295 | if (v < 0) { |
311 | /* Targets which reenter must return | 296 | /* Pop from stack? */ |
312 | * abs. verdicts | 297 | if (v != ARPT_RETURN) { |
313 | */ | 298 | verdict = (unsigned)(-v) - 1; |
314 | tgpar.target = t->u.kernel.target; | ||
315 | tgpar.targinfo = t->data; | ||
316 | verdict = t->u.kernel.target->target(skb, | ||
317 | &tgpar); | ||
318 | |||
319 | /* Target might have changed stuff. */ | ||
320 | arp = arp_hdr(skb); | ||
321 | |||
322 | if (verdict == ARPT_CONTINUE) | ||
323 | e = (void *)e + e->next_offset; | ||
324 | else | ||
325 | /* Verdict */ | ||
326 | break; | 299 | break; |
300 | } | ||
301 | e = back; | ||
302 | back = get_entry(table_base, back->comefrom); | ||
303 | continue; | ||
327 | } | 304 | } |
328 | } else { | 305 | if (table_base + v |
329 | e = (void *)e + e->next_offset; | 306 | != arpt_next_entry(e)) { |
307 | /* Save old back ptr in next entry */ | ||
308 | struct arpt_entry *next = arpt_next_entry(e); | ||
309 | next->comefrom = (void *)back - table_base; | ||
310 | |||
311 | /* set back pointer to next entry */ | ||
312 | back = next; | ||
313 | } | ||
314 | |||
315 | e = get_entry(table_base, v); | ||
316 | continue; | ||
330 | } | 317 | } |
318 | |||
319 | /* Targets which reenter must return | ||
320 | * abs. verdicts | ||
321 | */ | ||
322 | tgpar.target = t->u.kernel.target; | ||
323 | tgpar.targinfo = t->data; | ||
324 | verdict = t->u.kernel.target->target(skb, &tgpar); | ||
325 | |||
326 | /* Target might have changed stuff. */ | ||
327 | arp = arp_hdr(skb); | ||
328 | |||
329 | if (verdict == ARPT_CONTINUE) | ||
330 | e = arpt_next_entry(e); | ||
331 | else | ||
332 | /* Verdict */ | ||
333 | break; | ||
331 | } while (!hotdrop); | 334 | } while (!hotdrop); |
332 | xt_info_rdunlock_bh(); | 335 | xt_info_rdunlock_bh(); |
333 | 336 | ||
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 5f22c91c6e15..c156db215987 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -596,7 +596,7 @@ static int __init ip_queue_init(void) | |||
596 | #ifdef CONFIG_SYSCTL | 596 | #ifdef CONFIG_SYSCTL |
597 | ipq_sysctl_header = register_sysctl_paths(net_ipv4_ctl_path, ipq_table); | 597 | ipq_sysctl_header = register_sysctl_paths(net_ipv4_ctl_path, ipq_table); |
598 | #endif | 598 | #endif |
599 | status = nf_register_queue_handler(PF_INET, &nfqh); | 599 | status = nf_register_queue_handler(NFPROTO_IPV4, &nfqh); |
600 | if (status < 0) { | 600 | if (status < 0) { |
601 | printk(KERN_ERR "ip_queue: failed to register queue handler\n"); | 601 | printk(KERN_ERR "ip_queue: failed to register queue handler\n"); |
602 | goto cleanup_sysctl; | 602 | goto cleanup_sysctl; |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2ec8d7290c40..5bf7c3f185da 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -238,8 +238,8 @@ static struct nf_loginfo trace_loginfo = { | |||
238 | /* Mildly perf critical (only if packet tracing is on) */ | 238 | /* Mildly perf critical (only if packet tracing is on) */ |
239 | static inline int | 239 | static inline int |
240 | get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, | 240 | get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, |
241 | char *hookname, char **chainname, | 241 | const char *hookname, const char **chainname, |
242 | char **comment, unsigned int *rulenum) | 242 | const char **comment, unsigned int *rulenum) |
243 | { | 243 | { |
244 | struct ipt_standard_target *t = (void *)ipt_get_target(s); | 244 | struct ipt_standard_target *t = (void *)ipt_get_target(s); |
245 | 245 | ||
@@ -257,8 +257,8 @@ get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, | |||
257 | && unconditional(&s->ip)) { | 257 | && unconditional(&s->ip)) { |
258 | /* Tail of chains: STANDARD target (return/policy) */ | 258 | /* Tail of chains: STANDARD target (return/policy) */ |
259 | *comment = *chainname == hookname | 259 | *comment = *chainname == hookname |
260 | ? (char *)comments[NF_IP_TRACE_COMMENT_POLICY] | 260 | ? comments[NF_IP_TRACE_COMMENT_POLICY] |
261 | : (char *)comments[NF_IP_TRACE_COMMENT_RETURN]; | 261 | : comments[NF_IP_TRACE_COMMENT_RETURN]; |
262 | } | 262 | } |
263 | return 1; | 263 | return 1; |
264 | } else | 264 | } else |
@@ -277,14 +277,14 @@ static void trace_packet(struct sk_buff *skb, | |||
277 | { | 277 | { |
278 | void *table_base; | 278 | void *table_base; |
279 | const struct ipt_entry *root; | 279 | const struct ipt_entry *root; |
280 | char *hookname, *chainname, *comment; | 280 | const char *hookname, *chainname, *comment; |
281 | unsigned int rulenum = 0; | 281 | unsigned int rulenum = 0; |
282 | 282 | ||
283 | table_base = (void *)private->entries[smp_processor_id()]; | 283 | table_base = private->entries[smp_processor_id()]; |
284 | root = get_entry(table_base, private->hook_entry[hook]); | 284 | root = get_entry(table_base, private->hook_entry[hook]); |
285 | 285 | ||
286 | hookname = chainname = (char *)hooknames[hook]; | 286 | hookname = chainname = hooknames[hook]; |
287 | comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE]; | 287 | comment = comments[NF_IP_TRACE_COMMENT_RULE]; |
288 | 288 | ||
289 | IPT_ENTRY_ITERATE(root, | 289 | IPT_ENTRY_ITERATE(root, |
290 | private->size - private->hook_entry[hook], | 290 | private->size - private->hook_entry[hook], |
@@ -297,6 +297,12 @@ static void trace_packet(struct sk_buff *skb, | |||
297 | } | 297 | } |
298 | #endif | 298 | #endif |
299 | 299 | ||
300 | static inline __pure | ||
301 | struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry) | ||
302 | { | ||
303 | return (void *)entry + entry->next_offset; | ||
304 | } | ||
305 | |||
300 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ | 306 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ |
301 | unsigned int | 307 | unsigned int |
302 | ipt_do_table(struct sk_buff *skb, | 308 | ipt_do_table(struct sk_buff *skb, |
@@ -305,6 +311,8 @@ ipt_do_table(struct sk_buff *skb, | |||
305 | const struct net_device *out, | 311 | const struct net_device *out, |
306 | struct xt_table *table) | 312 | struct xt_table *table) |
307 | { | 313 | { |
314 | #define tb_comefrom ((struct ipt_entry *)table_base)->comefrom | ||
315 | |||
308 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); | 316 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); |
309 | const struct iphdr *ip; | 317 | const struct iphdr *ip; |
310 | u_int16_t datalen; | 318 | u_int16_t datalen; |
@@ -335,7 +343,7 @@ ipt_do_table(struct sk_buff *skb, | |||
335 | mtpar.in = tgpar.in = in; | 343 | mtpar.in = tgpar.in = in; |
336 | mtpar.out = tgpar.out = out; | 344 | mtpar.out = tgpar.out = out; |
337 | mtpar.family = tgpar.family = NFPROTO_IPV4; | 345 | mtpar.family = tgpar.family = NFPROTO_IPV4; |
338 | tgpar.hooknum = hook; | 346 | mtpar.hooknum = tgpar.hooknum = hook; |
339 | 347 | ||
340 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 348 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
341 | xt_info_rdlock_bh(); | 349 | xt_info_rdlock_bh(); |
@@ -348,92 +356,84 @@ ipt_do_table(struct sk_buff *skb, | |||
348 | back = get_entry(table_base, private->underflow[hook]); | 356 | back = get_entry(table_base, private->underflow[hook]); |
349 | 357 | ||
350 | do { | 358 | do { |
359 | struct ipt_entry_target *t; | ||
360 | |||
351 | IP_NF_ASSERT(e); | 361 | IP_NF_ASSERT(e); |
352 | IP_NF_ASSERT(back); | 362 | IP_NF_ASSERT(back); |
353 | if (ip_packet_match(ip, indev, outdev, | 363 | if (!ip_packet_match(ip, indev, outdev, |
354 | &e->ip, mtpar.fragoff)) { | 364 | &e->ip, mtpar.fragoff) || |
355 | struct ipt_entry_target *t; | 365 | IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) { |
356 | 366 | e = ipt_next_entry(e); | |
357 | if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) | 367 | continue; |
358 | goto no_match; | 368 | } |
359 | 369 | ||
360 | ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); | 370 | ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); |
361 | 371 | ||
362 | t = ipt_get_target(e); | 372 | t = ipt_get_target(e); |
363 | IP_NF_ASSERT(t->u.kernel.target); | 373 | IP_NF_ASSERT(t->u.kernel.target); |
364 | 374 | ||
365 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | 375 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ |
366 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | 376 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) |
367 | /* The packet is traced: log it */ | 377 | /* The packet is traced: log it */ |
368 | if (unlikely(skb->nf_trace)) | 378 | if (unlikely(skb->nf_trace)) |
369 | trace_packet(skb, hook, in, out, | 379 | trace_packet(skb, hook, in, out, |
370 | table->name, private, e); | 380 | table->name, private, e); |
371 | #endif | 381 | #endif |
372 | /* Standard target? */ | 382 | /* Standard target? */ |
373 | if (!t->u.kernel.target->target) { | 383 | if (!t->u.kernel.target->target) { |
374 | int v; | 384 | int v; |
375 | 385 | ||
376 | v = ((struct ipt_standard_target *)t)->verdict; | 386 | v = ((struct ipt_standard_target *)t)->verdict; |
377 | if (v < 0) { | 387 | if (v < 0) { |
378 | /* Pop from stack? */ | 388 | /* Pop from stack? */ |
379 | if (v != IPT_RETURN) { | 389 | if (v != IPT_RETURN) { |
380 | verdict = (unsigned)(-v) - 1; | 390 | verdict = (unsigned)(-v) - 1; |
381 | break; | 391 | break; |
382 | } | ||
383 | e = back; | ||
384 | back = get_entry(table_base, | ||
385 | back->comefrom); | ||
386 | continue; | ||
387 | } | ||
388 | if (table_base + v != (void *)e + e->next_offset | ||
389 | && !(e->ip.flags & IPT_F_GOTO)) { | ||
390 | /* Save old back ptr in next entry */ | ||
391 | struct ipt_entry *next | ||
392 | = (void *)e + e->next_offset; | ||
393 | next->comefrom | ||
394 | = (void *)back - table_base; | ||
395 | /* set back pointer to next entry */ | ||
396 | back = next; | ||
397 | } | 392 | } |
393 | e = back; | ||
394 | back = get_entry(table_base, back->comefrom); | ||
395 | continue; | ||
396 | } | ||
397 | if (table_base + v != ipt_next_entry(e) | ||
398 | && !(e->ip.flags & IPT_F_GOTO)) { | ||
399 | /* Save old back ptr in next entry */ | ||
400 | struct ipt_entry *next = ipt_next_entry(e); | ||
401 | next->comefrom = (void *)back - table_base; | ||
402 | /* set back pointer to next entry */ | ||
403 | back = next; | ||
404 | } | ||
405 | |||
406 | e = get_entry(table_base, v); | ||
407 | continue; | ||
408 | } | ||
409 | |||
410 | /* Targets which reenter must return | ||
411 | abs. verdicts */ | ||
412 | tgpar.target = t->u.kernel.target; | ||
413 | tgpar.targinfo = t->data; | ||
414 | |||
398 | 415 | ||
399 | e = get_entry(table_base, v); | ||
400 | } else { | ||
401 | /* Targets which reenter must return | ||
402 | abs. verdicts */ | ||
403 | tgpar.target = t->u.kernel.target; | ||
404 | tgpar.targinfo = t->data; | ||
405 | #ifdef CONFIG_NETFILTER_DEBUG | 416 | #ifdef CONFIG_NETFILTER_DEBUG |
406 | ((struct ipt_entry *)table_base)->comefrom | 417 | tb_comefrom = 0xeeeeeeec; |
407 | = 0xeeeeeeec; | ||
408 | #endif | 418 | #endif |
409 | verdict = t->u.kernel.target->target(skb, | 419 | verdict = t->u.kernel.target->target(skb, &tgpar); |
410 | &tgpar); | ||
411 | #ifdef CONFIG_NETFILTER_DEBUG | 420 | #ifdef CONFIG_NETFILTER_DEBUG |
412 | if (((struct ipt_entry *)table_base)->comefrom | 421 | if (comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) { |
413 | != 0xeeeeeeec | 422 | printk("Target %s reentered!\n", |
414 | && verdict == IPT_CONTINUE) { | 423 | t->u.kernel.target->name); |
415 | printk("Target %s reentered!\n", | 424 | verdict = NF_DROP; |
416 | t->u.kernel.target->name); | 425 | } |
417 | verdict = NF_DROP; | 426 | tb_comefrom = 0x57acc001; |
418 | } | ||
419 | ((struct ipt_entry *)table_base)->comefrom | ||
420 | = 0x57acc001; | ||
421 | #endif | 427 | #endif |
422 | /* Target might have changed stuff. */ | 428 | /* Target might have changed stuff. */ |
423 | ip = ip_hdr(skb); | 429 | ip = ip_hdr(skb); |
424 | datalen = skb->len - ip->ihl * 4; | 430 | datalen = skb->len - ip->ihl * 4; |
425 | |||
426 | if (verdict == IPT_CONTINUE) | ||
427 | e = (void *)e + e->next_offset; | ||
428 | else | ||
429 | /* Verdict */ | ||
430 | break; | ||
431 | } | ||
432 | } else { | ||
433 | 431 | ||
434 | no_match: | 432 | if (verdict == IPT_CONTINUE) |
435 | e = (void *)e + e->next_offset; | 433 | e = ipt_next_entry(e); |
436 | } | 434 | else |
435 | /* Verdict */ | ||
436 | break; | ||
437 | } while (!hotdrop); | 437 | } while (!hotdrop); |
438 | xt_info_rdunlock_bh(); | 438 | xt_info_rdunlock_bh(); |
439 | 439 | ||
@@ -444,6 +444,8 @@ ipt_do_table(struct sk_buff *skb, | |||
444 | return NF_DROP; | 444 | return NF_DROP; |
445 | else return verdict; | 445 | else return verdict; |
446 | #endif | 446 | #endif |
447 | |||
448 | #undef tb_comefrom | ||
447 | } | 449 | } |
448 | 450 | ||
449 | /* Figures out from what hook each rule can be called: returns 0 if | 451 | /* Figures out from what hook each rule can be called: returns 0 if |
@@ -2158,7 +2160,7 @@ static bool icmp_checkentry(const struct xt_mtchk_param *par) | |||
2158 | static struct xt_target ipt_standard_target __read_mostly = { | 2160 | static struct xt_target ipt_standard_target __read_mostly = { |
2159 | .name = IPT_STANDARD_TARGET, | 2161 | .name = IPT_STANDARD_TARGET, |
2160 | .targetsize = sizeof(int), | 2162 | .targetsize = sizeof(int), |
2161 | .family = AF_INET, | 2163 | .family = NFPROTO_IPV4, |
2162 | #ifdef CONFIG_COMPAT | 2164 | #ifdef CONFIG_COMPAT |
2163 | .compatsize = sizeof(compat_int_t), | 2165 | .compatsize = sizeof(compat_int_t), |
2164 | .compat_from_user = compat_standard_from_user, | 2166 | .compat_from_user = compat_standard_from_user, |
@@ -2170,7 +2172,7 @@ static struct xt_target ipt_error_target __read_mostly = { | |||
2170 | .name = IPT_ERROR_TARGET, | 2172 | .name = IPT_ERROR_TARGET, |
2171 | .target = ipt_error, | 2173 | .target = ipt_error, |
2172 | .targetsize = IPT_FUNCTION_MAXNAMELEN, | 2174 | .targetsize = IPT_FUNCTION_MAXNAMELEN, |
2173 | .family = AF_INET, | 2175 | .family = NFPROTO_IPV4, |
2174 | }; | 2176 | }; |
2175 | 2177 | ||
2176 | static struct nf_sockopt_ops ipt_sockopts = { | 2178 | static struct nf_sockopt_ops ipt_sockopts = { |
@@ -2196,17 +2198,17 @@ static struct xt_match icmp_matchstruct __read_mostly = { | |||
2196 | .matchsize = sizeof(struct ipt_icmp), | 2198 | .matchsize = sizeof(struct ipt_icmp), |
2197 | .checkentry = icmp_checkentry, | 2199 | .checkentry = icmp_checkentry, |
2198 | .proto = IPPROTO_ICMP, | 2200 | .proto = IPPROTO_ICMP, |
2199 | .family = AF_INET, | 2201 | .family = NFPROTO_IPV4, |
2200 | }; | 2202 | }; |
2201 | 2203 | ||
2202 | static int __net_init ip_tables_net_init(struct net *net) | 2204 | static int __net_init ip_tables_net_init(struct net *net) |
2203 | { | 2205 | { |
2204 | return xt_proto_init(net, AF_INET); | 2206 | return xt_proto_init(net, NFPROTO_IPV4); |
2205 | } | 2207 | } |
2206 | 2208 | ||
2207 | static void __net_exit ip_tables_net_exit(struct net *net) | 2209 | static void __net_exit ip_tables_net_exit(struct net *net) |
2208 | { | 2210 | { |
2209 | xt_proto_fini(net, AF_INET); | 2211 | xt_proto_fini(net, NFPROTO_IPV4); |
2210 | } | 2212 | } |
2211 | 2213 | ||
2212 | static struct pernet_operations ip_tables_net_ops = { | 2214 | static struct pernet_operations ip_tables_net_ops = { |
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index c0992c75bdac..dada0863946d 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
@@ -27,9 +27,6 @@ MODULE_LICENSE("GPL"); | |||
27 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 27 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
28 | MODULE_DESCRIPTION("Xtables: automatic-address SNAT"); | 28 | MODULE_DESCRIPTION("Xtables: automatic-address SNAT"); |
29 | 29 | ||
30 | /* Lock protects masq region inside conntrack */ | ||
31 | static DEFINE_RWLOCK(masq_lock); | ||
32 | |||
33 | /* FIXME: Multiple targets. --RR */ | 30 | /* FIXME: Multiple targets. --RR */ |
34 | static bool masquerade_tg_check(const struct xt_tgchk_param *par) | 31 | static bool masquerade_tg_check(const struct xt_tgchk_param *par) |
35 | { | 32 | { |
@@ -79,9 +76,7 @@ masquerade_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
79 | return NF_DROP; | 76 | return NF_DROP; |
80 | } | 77 | } |
81 | 78 | ||
82 | write_lock_bh(&masq_lock); | ||
83 | nat->masq_index = par->out->ifindex; | 79 | nat->masq_index = par->out->ifindex; |
84 | write_unlock_bh(&masq_lock); | ||
85 | 80 | ||
86 | /* Transfer from original range. */ | 81 | /* Transfer from original range. */ |
87 | newrange = ((struct nf_nat_range) | 82 | newrange = ((struct nf_nat_range) |
@@ -97,16 +92,11 @@ static int | |||
97 | device_cmp(struct nf_conn *i, void *ifindex) | 92 | device_cmp(struct nf_conn *i, void *ifindex) |
98 | { | 93 | { |
99 | const struct nf_conn_nat *nat = nfct_nat(i); | 94 | const struct nf_conn_nat *nat = nfct_nat(i); |
100 | int ret; | ||
101 | 95 | ||
102 | if (!nat) | 96 | if (!nat) |
103 | return 0; | 97 | return 0; |
104 | 98 | ||
105 | read_lock_bh(&masq_lock); | 99 | return nat->masq_index == (int)(long)ifindex; |
106 | ret = (nat->masq_index == (int)(long)ifindex); | ||
107 | read_unlock_bh(&masq_lock); | ||
108 | |||
109 | return ret; | ||
110 | } | 100 | } |
111 | 101 | ||
112 | static int masq_device_event(struct notifier_block *this, | 102 | static int masq_device_event(struct notifier_block *this, |
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 23b2c2ee869a..d71ba7677344 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -82,18 +82,10 @@ static int icmp_packet(struct nf_conn *ct, | |||
82 | u_int8_t pf, | 82 | u_int8_t pf, |
83 | unsigned int hooknum) | 83 | unsigned int hooknum) |
84 | { | 84 | { |
85 | /* Try to delete connection immediately after all replies: | 85 | /* Do not immediately delete the connection after the first |
86 | won't actually vanish as we still have skb, and del_timer | 86 | successful reply to avoid excessive conntrackd traffic |
87 | means this will only run once even if count hits zero twice | 87 | and also to handle correctly ICMP echo reply duplicates. */ |
88 | (theoretically possible with SMP) */ | 88 | nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout); |
89 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { | ||
90 | if (atomic_dec_and_test(&ct->proto.icmp.count)) | ||
91 | nf_ct_kill_acct(ct, ctinfo, skb); | ||
92 | } else { | ||
93 | atomic_inc(&ct->proto.icmp.count); | ||
94 | nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct); | ||
95 | nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout); | ||
96 | } | ||
97 | 89 | ||
98 | return NF_ACCEPT; | 90 | return NF_ACCEPT; |
99 | } | 91 | } |
@@ -117,7 +109,6 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
117 | nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple); | 109 | nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple); |
118 | return false; | 110 | return false; |
119 | } | 111 | } |
120 | atomic_set(&ct->proto.icmp.count, 0); | ||
121 | return true; | 112 | return true; |
122 | } | 113 | } |
123 | 114 | ||