diff options
Diffstat (limited to 'net/ipv6/reassembly.c')
-rw-r--r-- | net/ipv6/reassembly.c | 65 |
1 files changed, 52 insertions, 13 deletions
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 798cabc7535b..6ab957ec2dd6 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * | 7 | * |
8 | * $Id: reassembly.c,v 1.26 2001/03/07 22:00:57 davem Exp $ | ||
9 | * | ||
10 | * Based on: net/ipv4/ip_fragment.c | 8 | * Based on: net/ipv4/ip_fragment.c |
11 | * | 9 | * |
12 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
@@ -247,6 +245,8 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, | |||
247 | arg.id = id; | 245 | arg.id = id; |
248 | arg.src = src; | 246 | arg.src = src; |
249 | arg.dst = dst; | 247 | arg.dst = dst; |
248 | |||
249 | read_lock(&ip6_frags.lock); | ||
250 | hash = ip6qhashfn(id, src, dst); | 250 | hash = ip6qhashfn(id, src, dst); |
251 | 251 | ||
252 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); | 252 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); |
@@ -632,7 +632,7 @@ static struct inet6_protocol frag_protocol = | |||
632 | }; | 632 | }; |
633 | 633 | ||
634 | #ifdef CONFIG_SYSCTL | 634 | #ifdef CONFIG_SYSCTL |
635 | static struct ctl_table ip6_frags_ctl_table[] = { | 635 | static struct ctl_table ip6_frags_ns_ctl_table[] = { |
636 | { | 636 | { |
637 | .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, | 637 | .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, |
638 | .procname = "ip6frag_high_thresh", | 638 | .procname = "ip6frag_high_thresh", |
@@ -658,6 +658,10 @@ static struct ctl_table ip6_frags_ctl_table[] = { | |||
658 | .proc_handler = &proc_dointvec_jiffies, | 658 | .proc_handler = &proc_dointvec_jiffies, |
659 | .strategy = &sysctl_jiffies, | 659 | .strategy = &sysctl_jiffies, |
660 | }, | 660 | }, |
661 | { } | ||
662 | }; | ||
663 | |||
664 | static struct ctl_table ip6_frags_ctl_table[] = { | ||
661 | { | 665 | { |
662 | .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, | 666 | .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, |
663 | .procname = "ip6frag_secret_interval", | 667 | .procname = "ip6frag_secret_interval", |
@@ -670,21 +674,20 @@ static struct ctl_table ip6_frags_ctl_table[] = { | |||
670 | { } | 674 | { } |
671 | }; | 675 | }; |
672 | 676 | ||
673 | static int ip6_frags_sysctl_register(struct net *net) | 677 | static int ip6_frags_ns_sysctl_register(struct net *net) |
674 | { | 678 | { |
675 | struct ctl_table *table; | 679 | struct ctl_table *table; |
676 | struct ctl_table_header *hdr; | 680 | struct ctl_table_header *hdr; |
677 | 681 | ||
678 | table = ip6_frags_ctl_table; | 682 | table = ip6_frags_ns_ctl_table; |
679 | if (net != &init_net) { | 683 | if (net != &init_net) { |
680 | table = kmemdup(table, sizeof(ip6_frags_ctl_table), GFP_KERNEL); | 684 | table = kmemdup(table, sizeof(ip6_frags_ns_ctl_table), GFP_KERNEL); |
681 | if (table == NULL) | 685 | if (table == NULL) |
682 | goto err_alloc; | 686 | goto err_alloc; |
683 | 687 | ||
684 | table[0].data = &net->ipv6.frags.high_thresh; | 688 | table[0].data = &net->ipv6.frags.high_thresh; |
685 | table[1].data = &net->ipv6.frags.low_thresh; | 689 | table[1].data = &net->ipv6.frags.low_thresh; |
686 | table[2].data = &net->ipv6.frags.timeout; | 690 | table[2].data = &net->ipv6.frags.timeout; |
687 | table[3].mode &= ~0222; | ||
688 | } | 691 | } |
689 | 692 | ||
690 | hdr = register_net_sysctl_table(net, net_ipv6_ctl_path, table); | 693 | hdr = register_net_sysctl_table(net, net_ipv6_ctl_path, table); |
@@ -701,7 +704,7 @@ err_alloc: | |||
701 | return -ENOMEM; | 704 | return -ENOMEM; |
702 | } | 705 | } |
703 | 706 | ||
704 | static void ip6_frags_sysctl_unregister(struct net *net) | 707 | static void ip6_frags_ns_sysctl_unregister(struct net *net) |
705 | { | 708 | { |
706 | struct ctl_table *table; | 709 | struct ctl_table *table; |
707 | 710 | ||
@@ -709,13 +712,36 @@ static void ip6_frags_sysctl_unregister(struct net *net) | |||
709 | unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr); | 712 | unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr); |
710 | kfree(table); | 713 | kfree(table); |
711 | } | 714 | } |
715 | |||
716 | static struct ctl_table_header *ip6_ctl_header; | ||
717 | |||
718 | static int ip6_frags_sysctl_register(void) | ||
719 | { | ||
720 | ip6_ctl_header = register_net_sysctl_rotable(net_ipv6_ctl_path, | ||
721 | ip6_frags_ctl_table); | ||
722 | return ip6_ctl_header == NULL ? -ENOMEM : 0; | ||
723 | } | ||
724 | |||
725 | static void ip6_frags_sysctl_unregister(void) | ||
726 | { | ||
727 | unregister_net_sysctl_table(ip6_ctl_header); | ||
728 | } | ||
712 | #else | 729 | #else |
713 | static inline int ip6_frags_sysctl_register(struct net *net) | 730 | static inline int ip6_frags_ns_sysctl_register(struct net *net) |
714 | { | 731 | { |
715 | return 0; | 732 | return 0; |
716 | } | 733 | } |
717 | 734 | ||
718 | static inline void ip6_frags_sysctl_unregister(struct net *net) | 735 | static inline void ip6_frags_ns_sysctl_unregister(struct net *net) |
736 | { | ||
737 | } | ||
738 | |||
739 | static inline int ip6_frags_sysctl_register(void) | ||
740 | { | ||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | static inline void ip6_frags_sysctl_unregister(void) | ||
719 | { | 745 | { |
720 | } | 746 | } |
721 | #endif | 747 | #endif |
@@ -728,12 +754,12 @@ static int ipv6_frags_init_net(struct net *net) | |||
728 | 754 | ||
729 | inet_frags_init_net(&net->ipv6.frags); | 755 | inet_frags_init_net(&net->ipv6.frags); |
730 | 756 | ||
731 | return ip6_frags_sysctl_register(net); | 757 | return ip6_frags_ns_sysctl_register(net); |
732 | } | 758 | } |
733 | 759 | ||
734 | static void ipv6_frags_exit_net(struct net *net) | 760 | static void ipv6_frags_exit_net(struct net *net) |
735 | { | 761 | { |
736 | ip6_frags_sysctl_unregister(net); | 762 | ip6_frags_ns_sysctl_unregister(net); |
737 | inet_frags_exit_net(&net->ipv6.frags, &ip6_frags); | 763 | inet_frags_exit_net(&net->ipv6.frags, &ip6_frags); |
738 | } | 764 | } |
739 | 765 | ||
@@ -750,7 +776,13 @@ int __init ipv6_frag_init(void) | |||
750 | if (ret) | 776 | if (ret) |
751 | goto out; | 777 | goto out; |
752 | 778 | ||
753 | register_pernet_subsys(&ip6_frags_ops); | 779 | ret = ip6_frags_sysctl_register(); |
780 | if (ret) | ||
781 | goto err_sysctl; | ||
782 | |||
783 | ret = register_pernet_subsys(&ip6_frags_ops); | ||
784 | if (ret) | ||
785 | goto err_pernet; | ||
754 | 786 | ||
755 | ip6_frags.hashfn = ip6_hashfn; | 787 | ip6_frags.hashfn = ip6_hashfn; |
756 | ip6_frags.constructor = ip6_frag_init; | 788 | ip6_frags.constructor = ip6_frag_init; |
@@ -763,11 +795,18 @@ int __init ipv6_frag_init(void) | |||
763 | inet_frags_init(&ip6_frags); | 795 | inet_frags_init(&ip6_frags); |
764 | out: | 796 | out: |
765 | return ret; | 797 | return ret; |
798 | |||
799 | err_pernet: | ||
800 | ip6_frags_sysctl_unregister(); | ||
801 | err_sysctl: | ||
802 | inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT); | ||
803 | goto out; | ||
766 | } | 804 | } |
767 | 805 | ||
768 | void ipv6_frag_exit(void) | 806 | void ipv6_frag_exit(void) |
769 | { | 807 | { |
770 | inet_frags_fini(&ip6_frags); | 808 | inet_frags_fini(&ip6_frags); |
809 | ip6_frags_sysctl_unregister(); | ||
771 | unregister_pernet_subsys(&ip6_frags_ops); | 810 | unregister_pernet_subsys(&ip6_frags_ops); |
772 | inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT); | 811 | inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT); |
773 | } | 812 | } |