aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/netfilter/ip6_queue.c2
-rw-r--r--net/ipv6/netfilter/ip6_tables.c170
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c17
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) */
271static inline int 271static inline int
272get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, 272get_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
332static inline __pure struct ip6t_entry *
333ip6t_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. */
333unsigned int 339unsigned int
334ip6t_do_table(struct sk_buff *skb, 340ip6t_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)
2191static struct xt_target ip6t_standard_target __read_mostly = { 2191static 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
2209static struct nf_sockopt_ops ip6t_sockopts = { 2209static 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
2235static int __net_init ip6_tables_net_init(struct net *net) 2235static 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
2240static void __net_exit ip6_tables_net_exit(struct net *net) 2240static 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
2245static struct pernet_operations ip6_tables_net_ops = { 2245static 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