diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 170 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 17 |
3 files changed, 90 insertions, 99 deletions
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index b693f841aeb4..1cf3f0c6a959 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -598,7 +598,7 @@ static int __init ip6_queue_init(void) | |||
598 | #ifdef CONFIG_SYSCTL | 598 | #ifdef CONFIG_SYSCTL |
599 | ipq_sysctl_header = register_sysctl_paths(net_ipv6_ctl_path, ipq_table); | 599 | ipq_sysctl_header = register_sysctl_paths(net_ipv6_ctl_path, ipq_table); |
600 | #endif | 600 | #endif |
601 | status = nf_register_queue_handler(PF_INET6, &nfqh); | 601 | status = nf_register_queue_handler(NFPROTO_IPV6, &nfqh); |
602 | if (status < 0) { | 602 | if (status < 0) { |
603 | printk(KERN_ERR "ip6_queue: failed to register queue handler\n"); | 603 | printk(KERN_ERR "ip6_queue: failed to register queue handler\n"); |
604 | goto cleanup_sysctl; | 604 | goto cleanup_sysctl; |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 219e165aea10..ced1f2c0cb65 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -270,8 +270,8 @@ static struct nf_loginfo trace_loginfo = { | |||
270 | /* Mildly perf critical (only if packet tracing is on) */ | 270 | /* Mildly perf critical (only if packet tracing is on) */ |
271 | static inline int | 271 | static inline int |
272 | get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, | 272 | get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, |
273 | char *hookname, char **chainname, | 273 | const char *hookname, const char **chainname, |
274 | char **comment, unsigned int *rulenum) | 274 | const char **comment, unsigned int *rulenum) |
275 | { | 275 | { |
276 | struct ip6t_standard_target *t = (void *)ip6t_get_target(s); | 276 | struct ip6t_standard_target *t = (void *)ip6t_get_target(s); |
277 | 277 | ||
@@ -289,8 +289,8 @@ get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, | |||
289 | && unconditional(&s->ipv6)) { | 289 | && unconditional(&s->ipv6)) { |
290 | /* Tail of chains: STANDARD target (return/policy) */ | 290 | /* Tail of chains: STANDARD target (return/policy) */ |
291 | *comment = *chainname == hookname | 291 | *comment = *chainname == hookname |
292 | ? (char *)comments[NF_IP6_TRACE_COMMENT_POLICY] | 292 | ? comments[NF_IP6_TRACE_COMMENT_POLICY] |
293 | : (char *)comments[NF_IP6_TRACE_COMMENT_RETURN]; | 293 | : comments[NF_IP6_TRACE_COMMENT_RETURN]; |
294 | } | 294 | } |
295 | return 1; | 295 | return 1; |
296 | } else | 296 | } else |
@@ -309,14 +309,14 @@ static void trace_packet(struct sk_buff *skb, | |||
309 | { | 309 | { |
310 | void *table_base; | 310 | void *table_base; |
311 | const struct ip6t_entry *root; | 311 | const struct ip6t_entry *root; |
312 | char *hookname, *chainname, *comment; | 312 | const char *hookname, *chainname, *comment; |
313 | unsigned int rulenum = 0; | 313 | unsigned int rulenum = 0; |
314 | 314 | ||
315 | table_base = (void *)private->entries[smp_processor_id()]; | 315 | table_base = private->entries[smp_processor_id()]; |
316 | root = get_entry(table_base, private->hook_entry[hook]); | 316 | root = get_entry(table_base, private->hook_entry[hook]); |
317 | 317 | ||
318 | hookname = chainname = (char *)hooknames[hook]; | 318 | hookname = chainname = hooknames[hook]; |
319 | comment = (char *)comments[NF_IP6_TRACE_COMMENT_RULE]; | 319 | comment = comments[NF_IP6_TRACE_COMMENT_RULE]; |
320 | 320 | ||
321 | IP6T_ENTRY_ITERATE(root, | 321 | IP6T_ENTRY_ITERATE(root, |
322 | private->size - private->hook_entry[hook], | 322 | private->size - private->hook_entry[hook], |
@@ -329,6 +329,12 @@ static void trace_packet(struct sk_buff *skb, | |||
329 | } | 329 | } |
330 | #endif | 330 | #endif |
331 | 331 | ||
332 | static inline __pure struct ip6t_entry * | ||
333 | ip6t_next_entry(const struct ip6t_entry *entry) | ||
334 | { | ||
335 | return (void *)entry + entry->next_offset; | ||
336 | } | ||
337 | |||
332 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ | 338 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ |
333 | unsigned int | 339 | unsigned int |
334 | ip6t_do_table(struct sk_buff *skb, | 340 | ip6t_do_table(struct sk_buff *skb, |
@@ -337,6 +343,8 @@ ip6t_do_table(struct sk_buff *skb, | |||
337 | const struct net_device *out, | 343 | const struct net_device *out, |
338 | struct xt_table *table) | 344 | struct xt_table *table) |
339 | { | 345 | { |
346 | #define tb_comefrom ((struct ip6t_entry *)table_base)->comefrom | ||
347 | |||
340 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); | 348 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); |
341 | bool hotdrop = false; | 349 | bool hotdrop = false; |
342 | /* Initializing verdict to NF_DROP keeps gcc happy. */ | 350 | /* Initializing verdict to NF_DROP keeps gcc happy. */ |
@@ -361,7 +369,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
361 | mtpar.in = tgpar.in = in; | 369 | mtpar.in = tgpar.in = in; |
362 | mtpar.out = tgpar.out = out; | 370 | mtpar.out = tgpar.out = out; |
363 | mtpar.family = tgpar.family = NFPROTO_IPV6; | 371 | mtpar.family = tgpar.family = NFPROTO_IPV6; |
364 | tgpar.hooknum = hook; | 372 | mtpar.hooknum = tgpar.hooknum = hook; |
365 | 373 | ||
366 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 374 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
367 | 375 | ||
@@ -375,96 +383,86 @@ ip6t_do_table(struct sk_buff *skb, | |||
375 | back = get_entry(table_base, private->underflow[hook]); | 383 | back = get_entry(table_base, private->underflow[hook]); |
376 | 384 | ||
377 | do { | 385 | do { |
386 | struct ip6t_entry_target *t; | ||
387 | |||
378 | IP_NF_ASSERT(e); | 388 | IP_NF_ASSERT(e); |
379 | IP_NF_ASSERT(back); | 389 | IP_NF_ASSERT(back); |
380 | if (ip6_packet_match(skb, indev, outdev, &e->ipv6, | 390 | if (!ip6_packet_match(skb, indev, outdev, &e->ipv6, |
381 | &mtpar.thoff, &mtpar.fragoff, &hotdrop)) { | 391 | &mtpar.thoff, &mtpar.fragoff, &hotdrop) || |
382 | struct ip6t_entry_target *t; | 392 | IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) { |
383 | 393 | e = ip6t_next_entry(e); | |
384 | if (IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) | 394 | continue; |
385 | goto no_match; | 395 | } |
386 | 396 | ||
387 | ADD_COUNTER(e->counters, | 397 | ADD_COUNTER(e->counters, |
388 | ntohs(ipv6_hdr(skb)->payload_len) + | 398 | ntohs(ipv6_hdr(skb)->payload_len) + |
389 | sizeof(struct ipv6hdr), 1); | 399 | sizeof(struct ipv6hdr), 1); |
390 | 400 | ||
391 | t = ip6t_get_target(e); | 401 | t = ip6t_get_target(e); |
392 | IP_NF_ASSERT(t->u.kernel.target); | 402 | IP_NF_ASSERT(t->u.kernel.target); |
393 | 403 | ||
394 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | 404 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ |
395 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | 405 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) |
396 | /* The packet is traced: log it */ | 406 | /* The packet is traced: log it */ |
397 | if (unlikely(skb->nf_trace)) | 407 | if (unlikely(skb->nf_trace)) |
398 | trace_packet(skb, hook, in, out, | 408 | trace_packet(skb, hook, in, out, |
399 | table->name, private, e); | 409 | table->name, private, e); |
400 | #endif | 410 | #endif |
401 | /* Standard target? */ | 411 | /* Standard target? */ |
402 | if (!t->u.kernel.target->target) { | 412 | if (!t->u.kernel.target->target) { |
403 | int v; | 413 | int v; |
404 | 414 | ||
405 | v = ((struct ip6t_standard_target *)t)->verdict; | 415 | v = ((struct ip6t_standard_target *)t)->verdict; |
406 | if (v < 0) { | 416 | if (v < 0) { |
407 | /* Pop from stack? */ | 417 | /* Pop from stack? */ |
408 | if (v != IP6T_RETURN) { | 418 | if (v != IP6T_RETURN) { |
409 | verdict = (unsigned)(-v) - 1; | 419 | verdict = (unsigned)(-v) - 1; |
410 | break; | 420 | break; |
411 | } | ||
412 | e = back; | ||
413 | back = get_entry(table_base, | ||
414 | back->comefrom); | ||
415 | continue; | ||
416 | } | ||
417 | if (table_base + v != (void *)e + e->next_offset | ||
418 | && !(e->ipv6.flags & IP6T_F_GOTO)) { | ||
419 | /* Save old back ptr in next entry */ | ||
420 | struct ip6t_entry *next | ||
421 | = (void *)e + e->next_offset; | ||
422 | next->comefrom | ||
423 | = (void *)back - table_base; | ||
424 | /* set back pointer to next entry */ | ||
425 | back = next; | ||
426 | } | 421 | } |
422 | e = back; | ||
423 | back = get_entry(table_base, back->comefrom); | ||
424 | continue; | ||
425 | } | ||
426 | if (table_base + v != ip6t_next_entry(e) | ||
427 | && !(e->ipv6.flags & IP6T_F_GOTO)) { | ||
428 | /* Save old back ptr in next entry */ | ||
429 | struct ip6t_entry *next = ip6t_next_entry(e); | ||
430 | next->comefrom = (void *)back - table_base; | ||
431 | /* set back pointer to next entry */ | ||
432 | back = next; | ||
433 | } | ||
427 | 434 | ||
428 | e = get_entry(table_base, v); | 435 | e = get_entry(table_base, v); |
429 | } else { | 436 | continue; |
430 | /* Targets which reenter must return | 437 | } |
431 | abs. verdicts */ | ||
432 | tgpar.target = t->u.kernel.target; | ||
433 | tgpar.targinfo = t->data; | ||
434 | 438 | ||
435 | #ifdef CONFIG_NETFILTER_DEBUG | 439 | /* Targets which reenter must return |
436 | ((struct ip6t_entry *)table_base)->comefrom | 440 | abs. verdicts */ |
437 | = 0xeeeeeeec; | 441 | tgpar.target = t->u.kernel.target; |
438 | #endif | 442 | tgpar.targinfo = t->data; |
439 | verdict = t->u.kernel.target->target(skb, | ||
440 | &tgpar); | ||
441 | 443 | ||
442 | #ifdef CONFIG_NETFILTER_DEBUG | 444 | #ifdef CONFIG_NETFILTER_DEBUG |
443 | if (((struct ip6t_entry *)table_base)->comefrom | 445 | tb_comefrom = 0xeeeeeeec; |
444 | != 0xeeeeeeec | ||
445 | && verdict == IP6T_CONTINUE) { | ||
446 | printk("Target %s reentered!\n", | ||
447 | t->u.kernel.target->name); | ||
448 | verdict = NF_DROP; | ||
449 | } | ||
450 | ((struct ip6t_entry *)table_base)->comefrom | ||
451 | = 0x57acc001; | ||
452 | #endif | 446 | #endif |
453 | if (verdict == IP6T_CONTINUE) | 447 | verdict = t->u.kernel.target->target(skb, &tgpar); |
454 | e = (void *)e + e->next_offset; | ||
455 | else | ||
456 | /* Verdict */ | ||
457 | break; | ||
458 | } | ||
459 | } else { | ||
460 | 448 | ||
461 | no_match: | 449 | #ifdef CONFIG_NETFILTER_DEBUG |
462 | e = (void *)e + e->next_offset; | 450 | if (tb_comefrom != 0xeeeeeeec && verdict == IP6T_CONTINUE) { |
451 | printk("Target %s reentered!\n", | ||
452 | t->u.kernel.target->name); | ||
453 | verdict = NF_DROP; | ||
463 | } | 454 | } |
455 | tb_comefrom = 0x57acc001; | ||
456 | #endif | ||
457 | if (verdict == IP6T_CONTINUE) | ||
458 | e = ip6t_next_entry(e); | ||
459 | else | ||
460 | /* Verdict */ | ||
461 | break; | ||
464 | } while (!hotdrop); | 462 | } while (!hotdrop); |
465 | 463 | ||
466 | #ifdef CONFIG_NETFILTER_DEBUG | 464 | #ifdef CONFIG_NETFILTER_DEBUG |
467 | ((struct ip6t_entry *)table_base)->comefrom = NETFILTER_LINK_POISON; | 465 | tb_comefrom = NETFILTER_LINK_POISON; |
468 | #endif | 466 | #endif |
469 | xt_info_rdunlock_bh(); | 467 | xt_info_rdunlock_bh(); |
470 | 468 | ||
@@ -475,6 +473,8 @@ ip6t_do_table(struct sk_buff *skb, | |||
475 | return NF_DROP; | 473 | return NF_DROP; |
476 | else return verdict; | 474 | else return verdict; |
477 | #endif | 475 | #endif |
476 | |||
477 | #undef tb_comefrom | ||
478 | } | 478 | } |
479 | 479 | ||
480 | /* Figures out from what hook each rule can be called: returns 0 if | 480 | /* Figures out from what hook each rule can be called: returns 0 if |
@@ -2191,7 +2191,7 @@ static bool icmp6_checkentry(const struct xt_mtchk_param *par) | |||
2191 | static struct xt_target ip6t_standard_target __read_mostly = { | 2191 | static struct xt_target ip6t_standard_target __read_mostly = { |
2192 | .name = IP6T_STANDARD_TARGET, | 2192 | .name = IP6T_STANDARD_TARGET, |
2193 | .targetsize = sizeof(int), | 2193 | .targetsize = sizeof(int), |
2194 | .family = AF_INET6, | 2194 | .family = NFPROTO_IPV6, |
2195 | #ifdef CONFIG_COMPAT | 2195 | #ifdef CONFIG_COMPAT |
2196 | .compatsize = sizeof(compat_int_t), | 2196 | .compatsize = sizeof(compat_int_t), |
2197 | .compat_from_user = compat_standard_from_user, | 2197 | .compat_from_user = compat_standard_from_user, |
@@ -2203,7 +2203,7 @@ static struct xt_target ip6t_error_target __read_mostly = { | |||
2203 | .name = IP6T_ERROR_TARGET, | 2203 | .name = IP6T_ERROR_TARGET, |
2204 | .target = ip6t_error, | 2204 | .target = ip6t_error, |
2205 | .targetsize = IP6T_FUNCTION_MAXNAMELEN, | 2205 | .targetsize = IP6T_FUNCTION_MAXNAMELEN, |
2206 | .family = AF_INET6, | 2206 | .family = NFPROTO_IPV6, |
2207 | }; | 2207 | }; |
2208 | 2208 | ||
2209 | static struct nf_sockopt_ops ip6t_sockopts = { | 2209 | static struct nf_sockopt_ops ip6t_sockopts = { |
@@ -2229,17 +2229,17 @@ static struct xt_match icmp6_matchstruct __read_mostly = { | |||
2229 | .matchsize = sizeof(struct ip6t_icmp), | 2229 | .matchsize = sizeof(struct ip6t_icmp), |
2230 | .checkentry = icmp6_checkentry, | 2230 | .checkentry = icmp6_checkentry, |
2231 | .proto = IPPROTO_ICMPV6, | 2231 | .proto = IPPROTO_ICMPV6, |
2232 | .family = AF_INET6, | 2232 | .family = NFPROTO_IPV6, |
2233 | }; | 2233 | }; |
2234 | 2234 | ||
2235 | static int __net_init ip6_tables_net_init(struct net *net) | 2235 | static int __net_init ip6_tables_net_init(struct net *net) |
2236 | { | 2236 | { |
2237 | return xt_proto_init(net, AF_INET6); | 2237 | return xt_proto_init(net, NFPROTO_IPV6); |
2238 | } | 2238 | } |
2239 | 2239 | ||
2240 | static void __net_exit ip6_tables_net_exit(struct net *net) | 2240 | static void __net_exit ip6_tables_net_exit(struct net *net) |
2241 | { | 2241 | { |
2242 | xt_proto_fini(net, AF_INET6); | 2242 | xt_proto_fini(net, NFPROTO_IPV6); |
2243 | } | 2243 | } |
2244 | 2244 | ||
2245 | static struct pernet_operations ip6_tables_net_ops = { | 2245 | static struct pernet_operations ip6_tables_net_ops = { |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 9903227bf37c..642dcb127bab 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -95,18 +95,10 @@ static int icmpv6_packet(struct nf_conn *ct, | |||
95 | u_int8_t pf, | 95 | u_int8_t pf, |
96 | unsigned int hooknum) | 96 | unsigned int hooknum) |
97 | { | 97 | { |
98 | /* Try to delete connection immediately after all replies: | 98 | /* Do not immediately delete the connection after the first |
99 | won't actually vanish as we still have skb, and del_timer | 99 | successful reply to avoid excessive conntrackd traffic |
100 | means this will only run once even if count hits zero twice | 100 | and also to handle correctly ICMP echo reply duplicates. */ |
101 | (theoretically possible with SMP) */ | 101 | nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmpv6_timeout); |
102 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { | ||
103 | if (atomic_dec_and_test(&ct->proto.icmp.count)) | ||
104 | nf_ct_kill_acct(ct, ctinfo, skb); | ||
105 | } else { | ||
106 | atomic_inc(&ct->proto.icmp.count); | ||
107 | nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct); | ||
108 | nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmpv6_timeout); | ||
109 | } | ||
110 | 102 | ||
111 | return NF_ACCEPT; | 103 | return NF_ACCEPT; |
112 | } | 104 | } |
@@ -132,7 +124,6 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
132 | type + 128); | 124 | type + 128); |
133 | return false; | 125 | return false; |
134 | } | 126 | } |
135 | atomic_set(&ct->proto.icmp.count, 0); | ||
136 | return true; | 127 | return true; |
137 | } | 128 | } |
138 | 129 | ||