diff options
Diffstat (limited to 'net/ipv6/reassembly.c')
-rw-r--r-- | net/ipv6/reassembly.c | 23 |
1 files changed, 8 insertions, 15 deletions
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index da5bd0ed83df..4d98549a6868 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -208,18 +208,17 @@ static void ip6_frag_expire(unsigned long data) | |||
208 | fq_kill(fq); | 208 | fq_kill(fq); |
209 | 209 | ||
210 | net = container_of(fq->q.net, struct net, ipv6.frags); | 210 | net = container_of(fq->q.net, struct net, ipv6.frags); |
211 | dev = dev_get_by_index(net, fq->iif); | 211 | rcu_read_lock(); |
212 | dev = dev_get_by_index_rcu(net, fq->iif); | ||
212 | if (!dev) | 213 | if (!dev) |
213 | goto out; | 214 | goto out_rcu_unlock; |
214 | 215 | ||
215 | rcu_read_lock(); | ||
216 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); | 216 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); |
217 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); | 217 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); |
218 | rcu_read_unlock(); | ||
219 | 218 | ||
220 | /* Don't send error if the first segment did not arrive. */ | 219 | /* Don't send error if the first segment did not arrive. */ |
221 | if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments) | 220 | if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments) |
222 | goto out; | 221 | goto out_rcu_unlock; |
223 | 222 | ||
224 | /* | 223 | /* |
225 | But use as source device on which LAST ARRIVED | 224 | But use as source device on which LAST ARRIVED |
@@ -228,9 +227,9 @@ static void ip6_frag_expire(unsigned long data) | |||
228 | */ | 227 | */ |
229 | fq->q.fragments->dev = dev; | 228 | fq->q.fragments->dev = dev; |
230 | icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); | 229 | icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); |
230 | out_rcu_unlock: | ||
231 | rcu_read_unlock(); | ||
231 | out: | 232 | out: |
232 | if (dev) | ||
233 | dev_put(dev); | ||
234 | spin_unlock(&fq->q.lock); | 233 | spin_unlock(&fq->q.lock); |
235 | fq_put(fq); | 234 | fq_put(fq); |
236 | } | 235 | } |
@@ -636,7 +635,6 @@ static const struct inet6_protocol frag_protocol = | |||
636 | #ifdef CONFIG_SYSCTL | 635 | #ifdef CONFIG_SYSCTL |
637 | static struct ctl_table ip6_frags_ns_ctl_table[] = { | 636 | static struct ctl_table ip6_frags_ns_ctl_table[] = { |
638 | { | 637 | { |
639 | .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, | ||
640 | .procname = "ip6frag_high_thresh", | 638 | .procname = "ip6frag_high_thresh", |
641 | .data = &init_net.ipv6.frags.high_thresh, | 639 | .data = &init_net.ipv6.frags.high_thresh, |
642 | .maxlen = sizeof(int), | 640 | .maxlen = sizeof(int), |
@@ -644,7 +642,6 @@ static struct ctl_table ip6_frags_ns_ctl_table[] = { | |||
644 | .proc_handler = proc_dointvec | 642 | .proc_handler = proc_dointvec |
645 | }, | 643 | }, |
646 | { | 644 | { |
647 | .ctl_name = NET_IPV6_IP6FRAG_LOW_THRESH, | ||
648 | .procname = "ip6frag_low_thresh", | 645 | .procname = "ip6frag_low_thresh", |
649 | .data = &init_net.ipv6.frags.low_thresh, | 646 | .data = &init_net.ipv6.frags.low_thresh, |
650 | .maxlen = sizeof(int), | 647 | .maxlen = sizeof(int), |
@@ -652,26 +649,22 @@ static struct ctl_table ip6_frags_ns_ctl_table[] = { | |||
652 | .proc_handler = proc_dointvec | 649 | .proc_handler = proc_dointvec |
653 | }, | 650 | }, |
654 | { | 651 | { |
655 | .ctl_name = NET_IPV6_IP6FRAG_TIME, | ||
656 | .procname = "ip6frag_time", | 652 | .procname = "ip6frag_time", |
657 | .data = &init_net.ipv6.frags.timeout, | 653 | .data = &init_net.ipv6.frags.timeout, |
658 | .maxlen = sizeof(int), | 654 | .maxlen = sizeof(int), |
659 | .mode = 0644, | 655 | .mode = 0644, |
660 | .proc_handler = proc_dointvec_jiffies, | 656 | .proc_handler = proc_dointvec_jiffies, |
661 | .strategy = sysctl_jiffies, | ||
662 | }, | 657 | }, |
663 | { } | 658 | { } |
664 | }; | 659 | }; |
665 | 660 | ||
666 | static struct ctl_table ip6_frags_ctl_table[] = { | 661 | static struct ctl_table ip6_frags_ctl_table[] = { |
667 | { | 662 | { |
668 | .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, | ||
669 | .procname = "ip6frag_secret_interval", | 663 | .procname = "ip6frag_secret_interval", |
670 | .data = &ip6_frags.secret_interval, | 664 | .data = &ip6_frags.secret_interval, |
671 | .maxlen = sizeof(int), | 665 | .maxlen = sizeof(int), |
672 | .mode = 0644, | 666 | .mode = 0644, |
673 | .proc_handler = proc_dointvec_jiffies, | 667 | .proc_handler = proc_dointvec_jiffies, |
674 | .strategy = sysctl_jiffies | ||
675 | }, | 668 | }, |
676 | { } | 669 | { } |
677 | }; | 670 | }; |
@@ -682,7 +675,7 @@ static int ip6_frags_ns_sysctl_register(struct net *net) | |||
682 | struct ctl_table_header *hdr; | 675 | struct ctl_table_header *hdr; |
683 | 676 | ||
684 | table = ip6_frags_ns_ctl_table; | 677 | table = ip6_frags_ns_ctl_table; |
685 | if (net != &init_net) { | 678 | if (!net_eq(net, &init_net)) { |
686 | table = kmemdup(table, sizeof(ip6_frags_ns_ctl_table), GFP_KERNEL); | 679 | table = kmemdup(table, sizeof(ip6_frags_ns_ctl_table), GFP_KERNEL); |
687 | if (table == NULL) | 680 | if (table == NULL) |
688 | goto err_alloc; | 681 | goto err_alloc; |
@@ -700,7 +693,7 @@ static int ip6_frags_ns_sysctl_register(struct net *net) | |||
700 | return 0; | 693 | return 0; |
701 | 694 | ||
702 | err_reg: | 695 | err_reg: |
703 | if (net != &init_net) | 696 | if (!net_eq(net, &init_net)) |
704 | kfree(table); | 697 | kfree(table); |
705 | err_alloc: | 698 | err_alloc: |
706 | return -ENOMEM; | 699 | return -ENOMEM; |