aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/reassembly.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/reassembly.c')
-rw-r--r--net/ipv6/reassembly.c23
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);
230out_rcu_unlock:
231 rcu_read_unlock();
231out: 232out:
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
637static struct ctl_table ip6_frags_ns_ctl_table[] = { 636static 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
666static struct ctl_table ip6_frags_ctl_table[] = { 661static 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
702err_reg: 695err_reg:
703 if (net != &init_net) 696 if (!net_eq(net, &init_net))
704 kfree(table); 697 kfree(table);
705err_alloc: 698err_alloc:
706 return -ENOMEM; 699 return -ENOMEM;