diff options
Diffstat (limited to 'net/ipv4/ip_fragment.c')
-rw-r--r-- | net/ipv4/ip_fragment.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 37221f659159..38d38f058018 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * The IP fragmentation functionality. | 6 | * The IP fragmentation functionality. |
7 | * | 7 | * |
8 | * Version: $Id: ip_fragment.c,v 1.59 2002/01/12 07:54:56 davem Exp $ | ||
9 | * | ||
10 | * Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG> | 8 | * Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG> |
11 | * Alan Cox <Alan.Cox@linux.org> | 9 | * Alan Cox <Alan.Cox@linux.org> |
12 | * | 10 | * |
@@ -180,7 +178,7 @@ static void ip_evictor(struct net *net) | |||
180 | 178 | ||
181 | evicted = inet_frag_evictor(&net->ipv4.frags, &ip4_frags); | 179 | evicted = inet_frag_evictor(&net->ipv4.frags, &ip4_frags); |
182 | if (evicted) | 180 | if (evicted) |
183 | IP_ADD_STATS_BH(IPSTATS_MIB_REASMFAILS, evicted); | 181 | IP_ADD_STATS_BH(net, IPSTATS_MIB_REASMFAILS, evicted); |
184 | } | 182 | } |
185 | 183 | ||
186 | /* | 184 | /* |
@@ -189,8 +187,10 @@ static void ip_evictor(struct net *net) | |||
189 | static void ip_expire(unsigned long arg) | 187 | static void ip_expire(unsigned long arg) |
190 | { | 188 | { |
191 | struct ipq *qp; | 189 | struct ipq *qp; |
190 | struct net *net; | ||
192 | 191 | ||
193 | qp = container_of((struct inet_frag_queue *) arg, struct ipq, q); | 192 | qp = container_of((struct inet_frag_queue *) arg, struct ipq, q); |
193 | net = container_of(qp->q.net, struct net, ipv4.frags); | ||
194 | 194 | ||
195 | spin_lock(&qp->q.lock); | 195 | spin_lock(&qp->q.lock); |
196 | 196 | ||
@@ -199,14 +199,12 @@ static void ip_expire(unsigned long arg) | |||
199 | 199 | ||
200 | ipq_kill(qp); | 200 | ipq_kill(qp); |
201 | 201 | ||
202 | IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); | 202 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMTIMEOUT); |
203 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 203 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); |
204 | 204 | ||
205 | if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { | 205 | if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { |
206 | struct sk_buff *head = qp->q.fragments; | 206 | struct sk_buff *head = qp->q.fragments; |
207 | struct net *net; | ||
208 | 207 | ||
209 | net = container_of(qp->q.net, struct net, ipv4.frags); | ||
210 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ | 208 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ |
211 | if ((head->dev = dev_get_by_index(net, qp->iif)) != NULL) { | 209 | if ((head->dev = dev_get_by_index(net, qp->iif)) != NULL) { |
212 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); | 210 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); |
@@ -263,7 +261,10 @@ static inline int ip_frag_too_far(struct ipq *qp) | |||
263 | rc = qp->q.fragments && (end - start) > max; | 261 | rc = qp->q.fragments && (end - start) > max; |
264 | 262 | ||
265 | if (rc) { | 263 | if (rc) { |
266 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 264 | struct net *net; |
265 | |||
266 | net = container_of(qp->q.net, struct net, ipv4.frags); | ||
267 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); | ||
267 | } | 268 | } |
268 | 269 | ||
269 | return rc; | 270 | return rc; |
@@ -547,7 +548,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | |||
547 | iph = ip_hdr(head); | 548 | iph = ip_hdr(head); |
548 | iph->frag_off = 0; | 549 | iph->frag_off = 0; |
549 | iph->tot_len = htons(len); | 550 | iph->tot_len = htons(len); |
550 | IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS); | 551 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_REASMOKS); |
551 | qp->q.fragments = NULL; | 552 | qp->q.fragments = NULL; |
552 | return 0; | 553 | return 0; |
553 | 554 | ||
@@ -562,7 +563,7 @@ out_oversize: | |||
562 | "Oversized IP packet from " NIPQUAD_FMT ".\n", | 563 | "Oversized IP packet from " NIPQUAD_FMT ".\n", |
563 | NIPQUAD(qp->saddr)); | 564 | NIPQUAD(qp->saddr)); |
564 | out_fail: | 565 | out_fail: |
565 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 566 | IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_REASMFAILS); |
566 | return err; | 567 | return err; |
567 | } | 568 | } |
568 | 569 | ||
@@ -572,9 +573,9 @@ int ip_defrag(struct sk_buff *skb, u32 user) | |||
572 | struct ipq *qp; | 573 | struct ipq *qp; |
573 | struct net *net; | 574 | struct net *net; |
574 | 575 | ||
575 | IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS); | ||
576 | |||
577 | net = skb->dev ? dev_net(skb->dev) : dev_net(skb->dst->dev); | 576 | net = skb->dev ? dev_net(skb->dev) : dev_net(skb->dst->dev); |
577 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); | ||
578 | |||
578 | /* Start by cleaning up the memory. */ | 579 | /* Start by cleaning up the memory. */ |
579 | if (atomic_read(&net->ipv4.frags.mem) > net->ipv4.frags.high_thresh) | 580 | if (atomic_read(&net->ipv4.frags.mem) > net->ipv4.frags.high_thresh) |
580 | ip_evictor(net); | 581 | ip_evictor(net); |
@@ -592,7 +593,7 @@ int ip_defrag(struct sk_buff *skb, u32 user) | |||
592 | return ret; | 593 | return ret; |
593 | } | 594 | } |
594 | 595 | ||
595 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 596 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); |
596 | kfree_skb(skb); | 597 | kfree_skb(skb); |
597 | return -ENOMEM; | 598 | return -ENOMEM; |
598 | } | 599 | } |
@@ -600,7 +601,7 @@ int ip_defrag(struct sk_buff *skb, u32 user) | |||
600 | #ifdef CONFIG_SYSCTL | 601 | #ifdef CONFIG_SYSCTL |
601 | static int zero; | 602 | static int zero; |
602 | 603 | ||
603 | static struct ctl_table ip4_frags_ctl_table[] = { | 604 | static struct ctl_table ip4_frags_ns_ctl_table[] = { |
604 | { | 605 | { |
605 | .ctl_name = NET_IPV4_IPFRAG_HIGH_THRESH, | 606 | .ctl_name = NET_IPV4_IPFRAG_HIGH_THRESH, |
606 | .procname = "ipfrag_high_thresh", | 607 | .procname = "ipfrag_high_thresh", |
@@ -626,6 +627,10 @@ static struct ctl_table ip4_frags_ctl_table[] = { | |||
626 | .proc_handler = &proc_dointvec_jiffies, | 627 | .proc_handler = &proc_dointvec_jiffies, |
627 | .strategy = &sysctl_jiffies | 628 | .strategy = &sysctl_jiffies |
628 | }, | 629 | }, |
630 | { } | ||
631 | }; | ||
632 | |||
633 | static struct ctl_table ip4_frags_ctl_table[] = { | ||
629 | { | 634 | { |
630 | .ctl_name = NET_IPV4_IPFRAG_SECRET_INTERVAL, | 635 | .ctl_name = NET_IPV4_IPFRAG_SECRET_INTERVAL, |
631 | .procname = "ipfrag_secret_interval", | 636 | .procname = "ipfrag_secret_interval", |
@@ -646,22 +651,20 @@ static struct ctl_table ip4_frags_ctl_table[] = { | |||
646 | { } | 651 | { } |
647 | }; | 652 | }; |
648 | 653 | ||
649 | static int ip4_frags_ctl_register(struct net *net) | 654 | static int ip4_frags_ns_ctl_register(struct net *net) |
650 | { | 655 | { |
651 | struct ctl_table *table; | 656 | struct ctl_table *table; |
652 | struct ctl_table_header *hdr; | 657 | struct ctl_table_header *hdr; |
653 | 658 | ||
654 | table = ip4_frags_ctl_table; | 659 | table = ip4_frags_ns_ctl_table; |
655 | if (net != &init_net) { | 660 | if (net != &init_net) { |
656 | table = kmemdup(table, sizeof(ip4_frags_ctl_table), GFP_KERNEL); | 661 | table = kmemdup(table, sizeof(ip4_frags_ns_ctl_table), GFP_KERNEL); |
657 | if (table == NULL) | 662 | if (table == NULL) |
658 | goto err_alloc; | 663 | goto err_alloc; |
659 | 664 | ||
660 | table[0].data = &net->ipv4.frags.high_thresh; | 665 | table[0].data = &net->ipv4.frags.high_thresh; |
661 | table[1].data = &net->ipv4.frags.low_thresh; | 666 | table[1].data = &net->ipv4.frags.low_thresh; |
662 | table[2].data = &net->ipv4.frags.timeout; | 667 | table[2].data = &net->ipv4.frags.timeout; |
663 | table[3].mode &= ~0222; | ||
664 | table[4].mode &= ~0222; | ||
665 | } | 668 | } |
666 | 669 | ||
667 | hdr = register_net_sysctl_table(net, net_ipv4_ctl_path, table); | 670 | hdr = register_net_sysctl_table(net, net_ipv4_ctl_path, table); |
@@ -678,7 +681,7 @@ err_alloc: | |||
678 | return -ENOMEM; | 681 | return -ENOMEM; |
679 | } | 682 | } |
680 | 683 | ||
681 | static void ip4_frags_ctl_unregister(struct net *net) | 684 | static void ip4_frags_ns_ctl_unregister(struct net *net) |
682 | { | 685 | { |
683 | struct ctl_table *table; | 686 | struct ctl_table *table; |
684 | 687 | ||
@@ -686,13 +689,22 @@ static void ip4_frags_ctl_unregister(struct net *net) | |||
686 | unregister_net_sysctl_table(net->ipv4.frags_hdr); | 689 | unregister_net_sysctl_table(net->ipv4.frags_hdr); |
687 | kfree(table); | 690 | kfree(table); |
688 | } | 691 | } |
692 | |||
693 | static void ip4_frags_ctl_register(void) | ||
694 | { | ||
695 | register_net_sysctl_rotable(net_ipv4_ctl_path, ip4_frags_ctl_table); | ||
696 | } | ||
689 | #else | 697 | #else |
690 | static inline int ip4_frags_ctl_register(struct net *net) | 698 | static inline int ip4_frags_ns_ctl_register(struct net *net) |
691 | { | 699 | { |
692 | return 0; | 700 | return 0; |
693 | } | 701 | } |
694 | 702 | ||
695 | static inline void ip4_frags_ctl_unregister(struct net *net) | 703 | static inline void ip4_frags_ns_ctl_unregister(struct net *net) |
704 | { | ||
705 | } | ||
706 | |||
707 | static inline void ip4_frags_ctl_register(void) | ||
696 | { | 708 | { |
697 | } | 709 | } |
698 | #endif | 710 | #endif |
@@ -716,12 +728,12 @@ static int ipv4_frags_init_net(struct net *net) | |||
716 | 728 | ||
717 | inet_frags_init_net(&net->ipv4.frags); | 729 | inet_frags_init_net(&net->ipv4.frags); |
718 | 730 | ||
719 | return ip4_frags_ctl_register(net); | 731 | return ip4_frags_ns_ctl_register(net); |
720 | } | 732 | } |
721 | 733 | ||
722 | static void ipv4_frags_exit_net(struct net *net) | 734 | static void ipv4_frags_exit_net(struct net *net) |
723 | { | 735 | { |
724 | ip4_frags_ctl_unregister(net); | 736 | ip4_frags_ns_ctl_unregister(net); |
725 | inet_frags_exit_net(&net->ipv4.frags, &ip4_frags); | 737 | inet_frags_exit_net(&net->ipv4.frags, &ip4_frags); |
726 | } | 738 | } |
727 | 739 | ||
@@ -732,6 +744,7 @@ static struct pernet_operations ip4_frags_ops = { | |||
732 | 744 | ||
733 | void __init ipfrag_init(void) | 745 | void __init ipfrag_init(void) |
734 | { | 746 | { |
747 | ip4_frags_ctl_register(); | ||
735 | register_pernet_subsys(&ip4_frags_ops); | 748 | register_pernet_subsys(&ip4_frags_ops); |
736 | ip4_frags.hashfn = ip4_hashfn; | 749 | ip4_frags.hashfn = ip4_hashfn; |
737 | ip4_frags.constructor = ip4_frag_init; | 750 | ip4_frags.constructor = ip4_frag_init; |