aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_fragment.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ip_fragment.c')
-rw-r--r--net/ipv4/ip_fragment.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index d3fe10be7219..75347ea70ea0 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -32,6 +32,9 @@
32#include <linux/netdevice.h> 32#include <linux/netdevice.h>
33#include <linux/jhash.h> 33#include <linux/jhash.h>
34#include <linux/random.h> 34#include <linux/random.h>
35#include <linux/slab.h>
36#include <net/route.h>
37#include <net/dst.h>
35#include <net/sock.h> 38#include <net/sock.h>
36#include <net/ip.h> 39#include <net/ip.h>
37#include <net/icmp.h> 40#include <net/icmp.h>
@@ -205,11 +208,35 @@ static void ip_expire(unsigned long arg)
205 if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { 208 if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) {
206 struct sk_buff *head = qp->q.fragments; 209 struct sk_buff *head = qp->q.fragments;
207 210
208 /* Send an ICMP "Fragment Reassembly Timeout" message. */ 211 rcu_read_lock();
209 if ((head->dev = dev_get_by_index(net, qp->iif)) != NULL) { 212 head->dev = dev_get_by_index_rcu(net, qp->iif);
210 icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); 213 if (!head->dev)
211 dev_put(head->dev); 214 goto out_rcu_unlock;
215
216 /*
217 * Only search router table for the head fragment,
218 * when defraging timeout at PRE_ROUTING HOOK.
219 */
220 if (qp->user == IP_DEFRAG_CONNTRACK_IN && !skb_dst(head)) {
221 const struct iphdr *iph = ip_hdr(head);
222 int err = ip_route_input(head, iph->daddr, iph->saddr,
223 iph->tos, head->dev);
224 if (unlikely(err))
225 goto out_rcu_unlock;
226
227 /*
228 * Only an end host needs to send an ICMP
229 * "Fragment Reassembly Timeout" message, per RFC792.
230 */
231 if (skb_rtable(head)->rt_type != RTN_LOCAL)
232 goto out_rcu_unlock;
233
212 } 234 }
235
236 /* Send an ICMP "Fragment Reassembly Timeout" message. */
237 icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
238out_rcu_unlock:
239 rcu_read_unlock();
213 } 240 }
214out: 241out:
215 spin_unlock(&qp->q.lock); 242 spin_unlock(&qp->q.lock);
@@ -603,7 +630,6 @@ static int zero;
603 630
604static struct ctl_table ip4_frags_ns_ctl_table[] = { 631static struct ctl_table ip4_frags_ns_ctl_table[] = {
605 { 632 {
606 .ctl_name = NET_IPV4_IPFRAG_HIGH_THRESH,
607 .procname = "ipfrag_high_thresh", 633 .procname = "ipfrag_high_thresh",
608 .data = &init_net.ipv4.frags.high_thresh, 634 .data = &init_net.ipv4.frags.high_thresh,
609 .maxlen = sizeof(int), 635 .maxlen = sizeof(int),
@@ -611,7 +637,6 @@ static struct ctl_table ip4_frags_ns_ctl_table[] = {
611 .proc_handler = proc_dointvec 637 .proc_handler = proc_dointvec
612 }, 638 },
613 { 639 {
614 .ctl_name = NET_IPV4_IPFRAG_LOW_THRESH,
615 .procname = "ipfrag_low_thresh", 640 .procname = "ipfrag_low_thresh",
616 .data = &init_net.ipv4.frags.low_thresh, 641 .data = &init_net.ipv4.frags.low_thresh,
617 .maxlen = sizeof(int), 642 .maxlen = sizeof(int),
@@ -619,26 +644,22 @@ static struct ctl_table ip4_frags_ns_ctl_table[] = {
619 .proc_handler = proc_dointvec 644 .proc_handler = proc_dointvec
620 }, 645 },
621 { 646 {
622 .ctl_name = NET_IPV4_IPFRAG_TIME,
623 .procname = "ipfrag_time", 647 .procname = "ipfrag_time",
624 .data = &init_net.ipv4.frags.timeout, 648 .data = &init_net.ipv4.frags.timeout,
625 .maxlen = sizeof(int), 649 .maxlen = sizeof(int),
626 .mode = 0644, 650 .mode = 0644,
627 .proc_handler = proc_dointvec_jiffies, 651 .proc_handler = proc_dointvec_jiffies,
628 .strategy = sysctl_jiffies
629 }, 652 },
630 { } 653 { }
631}; 654};
632 655
633static struct ctl_table ip4_frags_ctl_table[] = { 656static struct ctl_table ip4_frags_ctl_table[] = {
634 { 657 {
635 .ctl_name = NET_IPV4_IPFRAG_SECRET_INTERVAL,
636 .procname = "ipfrag_secret_interval", 658 .procname = "ipfrag_secret_interval",
637 .data = &ip4_frags.secret_interval, 659 .data = &ip4_frags.secret_interval,
638 .maxlen = sizeof(int), 660 .maxlen = sizeof(int),
639 .mode = 0644, 661 .mode = 0644,
640 .proc_handler = proc_dointvec_jiffies, 662 .proc_handler = proc_dointvec_jiffies,
641 .strategy = sysctl_jiffies
642 }, 663 },
643 { 664 {
644 .procname = "ipfrag_max_dist", 665 .procname = "ipfrag_max_dist",
@@ -651,13 +672,13 @@ static struct ctl_table ip4_frags_ctl_table[] = {
651 { } 672 { }
652}; 673};
653 674
654static int ip4_frags_ns_ctl_register(struct net *net) 675static int __net_init ip4_frags_ns_ctl_register(struct net *net)
655{ 676{
656 struct ctl_table *table; 677 struct ctl_table *table;
657 struct ctl_table_header *hdr; 678 struct ctl_table_header *hdr;
658 679
659 table = ip4_frags_ns_ctl_table; 680 table = ip4_frags_ns_ctl_table;
660 if (net != &init_net) { 681 if (!net_eq(net, &init_net)) {
661 table = kmemdup(table, sizeof(ip4_frags_ns_ctl_table), GFP_KERNEL); 682 table = kmemdup(table, sizeof(ip4_frags_ns_ctl_table), GFP_KERNEL);
662 if (table == NULL) 683 if (table == NULL)
663 goto err_alloc; 684 goto err_alloc;
@@ -675,13 +696,13 @@ static int ip4_frags_ns_ctl_register(struct net *net)
675 return 0; 696 return 0;
676 697
677err_reg: 698err_reg:
678 if (net != &init_net) 699 if (!net_eq(net, &init_net))
679 kfree(table); 700 kfree(table);
680err_alloc: 701err_alloc:
681 return -ENOMEM; 702 return -ENOMEM;
682} 703}
683 704
684static void ip4_frags_ns_ctl_unregister(struct net *net) 705static void __net_exit ip4_frags_ns_ctl_unregister(struct net *net)
685{ 706{
686 struct ctl_table *table; 707 struct ctl_table *table;
687 708
@@ -709,7 +730,7 @@ static inline void ip4_frags_ctl_register(void)
709} 730}
710#endif 731#endif
711 732
712static int ipv4_frags_init_net(struct net *net) 733static int __net_init ipv4_frags_init_net(struct net *net)
713{ 734{
714 /* 735 /*
715 * Fragment cache limits. We will commit 256K at one time. Should we 736 * Fragment cache limits. We will commit 256K at one time. Should we
@@ -731,7 +752,7 @@ static int ipv4_frags_init_net(struct net *net)
731 return ip4_frags_ns_ctl_register(net); 752 return ip4_frags_ns_ctl_register(net);
732} 753}
733 754
734static void ipv4_frags_exit_net(struct net *net) 755static void __net_exit ipv4_frags_exit_net(struct net *net)
735{ 756{
736 ip4_frags_ns_ctl_unregister(net); 757 ip4_frags_ns_ctl_unregister(net);
737 inet_frags_exit_net(&net->ipv4.frags, &ip4_frags); 758 inet_frags_exit_net(&net->ipv4.frags, &ip4_frags);