diff options
author | Cyrill Gorcunov <gorcunov@openvz.org> | 2009-03-16 11:30:49 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2009-03-16 11:30:49 -0400 |
commit | 1546000fe8db0d3f47b0ef1dd487ec23fbd95313 (patch) | |
tree | dc077facf57dd9b01cd41c16dd45358f7ebcbf18 | |
parent | 81a1d3c31e3517f9939b3e04d21cf4a6b0997419 (diff) |
net: netfilter conntrack - add per-net functionality for DCCP protocol
Module specific data moved into per-net site and being allocated/freed
during net namespace creation/deletion.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Acked-by: Daniel Lezcano <daniel.lezcano@free.fr>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | net/netfilter/nf_conntrack_proto_dccp.c | 145 |
1 files changed, 108 insertions, 37 deletions
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 8fcf1762fabf..d3d5a7fd73ce 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c | |||
@@ -16,6 +16,9 @@ | |||
16 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
17 | #include <linux/dccp.h> | 17 | #include <linux/dccp.h> |
18 | 18 | ||
19 | #include <net/net_namespace.h> | ||
20 | #include <net/netns/generic.h> | ||
21 | |||
19 | #include <linux/netfilter/nfnetlink_conntrack.h> | 22 | #include <linux/netfilter/nfnetlink_conntrack.h> |
20 | #include <net/netfilter/nf_conntrack.h> | 23 | #include <net/netfilter/nf_conntrack.h> |
21 | #include <net/netfilter/nf_conntrack_l4proto.h> | 24 | #include <net/netfilter/nf_conntrack_l4proto.h> |
@@ -23,8 +26,6 @@ | |||
23 | 26 | ||
24 | static DEFINE_RWLOCK(dccp_lock); | 27 | static DEFINE_RWLOCK(dccp_lock); |
25 | 28 | ||
26 | static int nf_ct_dccp_loose __read_mostly = 1; | ||
27 | |||
28 | /* Timeouts are based on values from RFC4340: | 29 | /* Timeouts are based on values from RFC4340: |
29 | * | 30 | * |
30 | * - REQUEST: | 31 | * - REQUEST: |
@@ -72,16 +73,6 @@ static int nf_ct_dccp_loose __read_mostly = 1; | |||
72 | 73 | ||
73 | #define DCCP_MSL (2 * 60 * HZ) | 74 | #define DCCP_MSL (2 * 60 * HZ) |
74 | 75 | ||
75 | static unsigned int dccp_timeout[CT_DCCP_MAX + 1] __read_mostly = { | ||
76 | [CT_DCCP_REQUEST] = 2 * DCCP_MSL, | ||
77 | [CT_DCCP_RESPOND] = 4 * DCCP_MSL, | ||
78 | [CT_DCCP_PARTOPEN] = 4 * DCCP_MSL, | ||
79 | [CT_DCCP_OPEN] = 12 * 3600 * HZ, | ||
80 | [CT_DCCP_CLOSEREQ] = 64 * HZ, | ||
81 | [CT_DCCP_CLOSING] = 64 * HZ, | ||
82 | [CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL, | ||
83 | }; | ||
84 | |||
85 | static const char * const dccp_state_names[] = { | 76 | static const char * const dccp_state_names[] = { |
86 | [CT_DCCP_NONE] = "NONE", | 77 | [CT_DCCP_NONE] = "NONE", |
87 | [CT_DCCP_REQUEST] = "REQUEST", | 78 | [CT_DCCP_REQUEST] = "REQUEST", |
@@ -393,6 +384,22 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = | |||
393 | }, | 384 | }, |
394 | }; | 385 | }; |
395 | 386 | ||
387 | /* this module per-net specifics */ | ||
388 | static int dccp_net_id; | ||
389 | struct dccp_net { | ||
390 | int dccp_loose; | ||
391 | unsigned int dccp_timeout[CT_DCCP_MAX + 1]; | ||
392 | #ifdef CONFIG_SYSCTL | ||
393 | struct ctl_table_header *sysctl_header; | ||
394 | struct ctl_table *sysctl_table; | ||
395 | #endif | ||
396 | }; | ||
397 | |||
398 | static inline struct dccp_net *dccp_pernet(struct net *net) | ||
399 | { | ||
400 | return net_generic(net, dccp_net_id); | ||
401 | } | ||
402 | |||
396 | static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, | 403 | static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, |
397 | struct nf_conntrack_tuple *tuple) | 404 | struct nf_conntrack_tuple *tuple) |
398 | { | 405 | { |
@@ -419,6 +426,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
419 | unsigned int dataoff) | 426 | unsigned int dataoff) |
420 | { | 427 | { |
421 | struct net *net = nf_ct_net(ct); | 428 | struct net *net = nf_ct_net(ct); |
429 | struct dccp_net *dn; | ||
422 | struct dccp_hdr _dh, *dh; | 430 | struct dccp_hdr _dh, *dh; |
423 | const char *msg; | 431 | const char *msg; |
424 | u_int8_t state; | 432 | u_int8_t state; |
@@ -429,7 +437,8 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
429 | state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; | 437 | state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; |
430 | switch (state) { | 438 | switch (state) { |
431 | default: | 439 | default: |
432 | if (nf_ct_dccp_loose == 0) { | 440 | dn = dccp_pernet(net); |
441 | if (dn->dccp_loose == 0) { | ||
433 | msg = "nf_ct_dccp: not picking up existing connection "; | 442 | msg = "nf_ct_dccp: not picking up existing connection "; |
434 | goto out_invalid; | 443 | goto out_invalid; |
435 | } | 444 | } |
@@ -465,6 +474,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, | |||
465 | u_int8_t pf, unsigned int hooknum) | 474 | u_int8_t pf, unsigned int hooknum) |
466 | { | 475 | { |
467 | struct net *net = nf_ct_net(ct); | 476 | struct net *net = nf_ct_net(ct); |
477 | struct dccp_net *dn; | ||
468 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 478 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
469 | struct dccp_hdr _dh, *dh; | 479 | struct dccp_hdr _dh, *dh; |
470 | u_int8_t type, old_state, new_state; | 480 | u_int8_t type, old_state, new_state; |
@@ -542,7 +552,9 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, | |||
542 | ct->proto.dccp.last_pkt = type; | 552 | ct->proto.dccp.last_pkt = type; |
543 | ct->proto.dccp.state = new_state; | 553 | ct->proto.dccp.state = new_state; |
544 | write_unlock_bh(&dccp_lock); | 554 | write_unlock_bh(&dccp_lock); |
545 | nf_ct_refresh_acct(ct, ctinfo, skb, dccp_timeout[new_state]); | 555 | |
556 | dn = dccp_pernet(net); | ||
557 | nf_ct_refresh_acct(ct, ctinfo, skb, dn->dccp_timeout[new_state]); | ||
546 | 558 | ||
547 | return NF_ACCEPT; | 559 | return NF_ACCEPT; |
548 | } | 560 | } |
@@ -660,13 +672,11 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) | |||
660 | #endif | 672 | #endif |
661 | 673 | ||
662 | #ifdef CONFIG_SYSCTL | 674 | #ifdef CONFIG_SYSCTL |
663 | static unsigned int dccp_sysctl_table_users; | 675 | /* template, data assigned later */ |
664 | static struct ctl_table_header *dccp_sysctl_header; | 676 | static struct ctl_table dccp_sysctl_table[] = { |
665 | static ctl_table dccp_sysctl_table[] = { | ||
666 | { | 677 | { |
667 | .ctl_name = CTL_UNNUMBERED, | 678 | .ctl_name = CTL_UNNUMBERED, |
668 | .procname = "nf_conntrack_dccp_timeout_request", | 679 | .procname = "nf_conntrack_dccp_timeout_request", |
669 | .data = &dccp_timeout[CT_DCCP_REQUEST], | ||
670 | .maxlen = sizeof(unsigned int), | 680 | .maxlen = sizeof(unsigned int), |
671 | .mode = 0644, | 681 | .mode = 0644, |
672 | .proc_handler = proc_dointvec_jiffies, | 682 | .proc_handler = proc_dointvec_jiffies, |
@@ -674,7 +684,6 @@ static ctl_table dccp_sysctl_table[] = { | |||
674 | { | 684 | { |
675 | .ctl_name = CTL_UNNUMBERED, | 685 | .ctl_name = CTL_UNNUMBERED, |
676 | .procname = "nf_conntrack_dccp_timeout_respond", | 686 | .procname = "nf_conntrack_dccp_timeout_respond", |
677 | .data = &dccp_timeout[CT_DCCP_RESPOND], | ||
678 | .maxlen = sizeof(unsigned int), | 687 | .maxlen = sizeof(unsigned int), |
679 | .mode = 0644, | 688 | .mode = 0644, |
680 | .proc_handler = proc_dointvec_jiffies, | 689 | .proc_handler = proc_dointvec_jiffies, |
@@ -682,7 +691,6 @@ static ctl_table dccp_sysctl_table[] = { | |||
682 | { | 691 | { |
683 | .ctl_name = CTL_UNNUMBERED, | 692 | .ctl_name = CTL_UNNUMBERED, |
684 | .procname = "nf_conntrack_dccp_timeout_partopen", | 693 | .procname = "nf_conntrack_dccp_timeout_partopen", |
685 | .data = &dccp_timeout[CT_DCCP_PARTOPEN], | ||
686 | .maxlen = sizeof(unsigned int), | 694 | .maxlen = sizeof(unsigned int), |
687 | .mode = 0644, | 695 | .mode = 0644, |
688 | .proc_handler = proc_dointvec_jiffies, | 696 | .proc_handler = proc_dointvec_jiffies, |
@@ -690,7 +698,6 @@ static ctl_table dccp_sysctl_table[] = { | |||
690 | { | 698 | { |
691 | .ctl_name = CTL_UNNUMBERED, | 699 | .ctl_name = CTL_UNNUMBERED, |
692 | .procname = "nf_conntrack_dccp_timeout_open", | 700 | .procname = "nf_conntrack_dccp_timeout_open", |
693 | .data = &dccp_timeout[CT_DCCP_OPEN], | ||
694 | .maxlen = sizeof(unsigned int), | 701 | .maxlen = sizeof(unsigned int), |
695 | .mode = 0644, | 702 | .mode = 0644, |
696 | .proc_handler = proc_dointvec_jiffies, | 703 | .proc_handler = proc_dointvec_jiffies, |
@@ -698,7 +705,6 @@ static ctl_table dccp_sysctl_table[] = { | |||
698 | { | 705 | { |
699 | .ctl_name = CTL_UNNUMBERED, | 706 | .ctl_name = CTL_UNNUMBERED, |
700 | .procname = "nf_conntrack_dccp_timeout_closereq", | 707 | .procname = "nf_conntrack_dccp_timeout_closereq", |
701 | .data = &dccp_timeout[CT_DCCP_CLOSEREQ], | ||
702 | .maxlen = sizeof(unsigned int), | 708 | .maxlen = sizeof(unsigned int), |
703 | .mode = 0644, | 709 | .mode = 0644, |
704 | .proc_handler = proc_dointvec_jiffies, | 710 | .proc_handler = proc_dointvec_jiffies, |
@@ -706,7 +712,6 @@ static ctl_table dccp_sysctl_table[] = { | |||
706 | { | 712 | { |
707 | .ctl_name = CTL_UNNUMBERED, | 713 | .ctl_name = CTL_UNNUMBERED, |
708 | .procname = "nf_conntrack_dccp_timeout_closing", | 714 | .procname = "nf_conntrack_dccp_timeout_closing", |
709 | .data = &dccp_timeout[CT_DCCP_CLOSING], | ||
710 | .maxlen = sizeof(unsigned int), | 715 | .maxlen = sizeof(unsigned int), |
711 | .mode = 0644, | 716 | .mode = 0644, |
712 | .proc_handler = proc_dointvec_jiffies, | 717 | .proc_handler = proc_dointvec_jiffies, |
@@ -714,7 +719,6 @@ static ctl_table dccp_sysctl_table[] = { | |||
714 | { | 719 | { |
715 | .ctl_name = CTL_UNNUMBERED, | 720 | .ctl_name = CTL_UNNUMBERED, |
716 | .procname = "nf_conntrack_dccp_timeout_timewait", | 721 | .procname = "nf_conntrack_dccp_timeout_timewait", |
717 | .data = &dccp_timeout[CT_DCCP_TIMEWAIT], | ||
718 | .maxlen = sizeof(unsigned int), | 722 | .maxlen = sizeof(unsigned int), |
719 | .mode = 0644, | 723 | .mode = 0644, |
720 | .proc_handler = proc_dointvec_jiffies, | 724 | .proc_handler = proc_dointvec_jiffies, |
@@ -722,8 +726,7 @@ static ctl_table dccp_sysctl_table[] = { | |||
722 | { | 726 | { |
723 | .ctl_name = CTL_UNNUMBERED, | 727 | .ctl_name = CTL_UNNUMBERED, |
724 | .procname = "nf_conntrack_dccp_loose", | 728 | .procname = "nf_conntrack_dccp_loose", |
725 | .data = &nf_ct_dccp_loose, | 729 | .maxlen = sizeof(int), |
726 | .maxlen = sizeof(nf_ct_dccp_loose), | ||
727 | .mode = 0644, | 730 | .mode = 0644, |
728 | .proc_handler = proc_dointvec, | 731 | .proc_handler = proc_dointvec, |
729 | }, | 732 | }, |
@@ -751,11 +754,6 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { | |||
751 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, | 754 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, |
752 | .nla_policy = nf_ct_port_nla_policy, | 755 | .nla_policy = nf_ct_port_nla_policy, |
753 | #endif | 756 | #endif |
754 | #ifdef CONFIG_SYSCTL | ||
755 | .ctl_table_users = &dccp_sysctl_table_users, | ||
756 | .ctl_table_header = &dccp_sysctl_header, | ||
757 | .ctl_table = dccp_sysctl_table, | ||
758 | #endif | ||
759 | }; | 757 | }; |
760 | 758 | ||
761 | static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { | 759 | static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { |
@@ -776,34 +774,107 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { | |||
776 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, | 774 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, |
777 | .nla_policy = nf_ct_port_nla_policy, | 775 | .nla_policy = nf_ct_port_nla_policy, |
778 | #endif | 776 | #endif |
777 | }; | ||
778 | |||
779 | static __net_init int dccp_net_init(struct net *net) | ||
780 | { | ||
781 | struct dccp_net *dn; | ||
782 | int err; | ||
783 | |||
784 | dn = kmalloc(sizeof(*dn), GFP_KERNEL); | ||
785 | if (!dn) | ||
786 | return -ENOMEM; | ||
787 | |||
788 | /* default values */ | ||
789 | dn->dccp_loose = 1; | ||
790 | dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL; | ||
791 | dn->dccp_timeout[CT_DCCP_RESPOND] = 4 * DCCP_MSL; | ||
792 | dn->dccp_timeout[CT_DCCP_PARTOPEN] = 4 * DCCP_MSL; | ||
793 | dn->dccp_timeout[CT_DCCP_OPEN] = 12 * 3600 * HZ; | ||
794 | dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ; | ||
795 | dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ; | ||
796 | dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL; | ||
797 | |||
798 | err = net_assign_generic(net, dccp_net_id, dn); | ||
799 | if (err) | ||
800 | goto out; | ||
801 | |||
779 | #ifdef CONFIG_SYSCTL | 802 | #ifdef CONFIG_SYSCTL |
780 | .ctl_table_users = &dccp_sysctl_table_users, | 803 | err = -ENOMEM; |
781 | .ctl_table_header = &dccp_sysctl_header, | 804 | dn->sysctl_table = kmemdup(dccp_sysctl_table, |
782 | .ctl_table = dccp_sysctl_table, | 805 | sizeof(dccp_sysctl_table), GFP_KERNEL); |
806 | if (!dn->sysctl_table) | ||
807 | goto out; | ||
808 | |||
809 | dn->sysctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST]; | ||
810 | dn->sysctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND]; | ||
811 | dn->sysctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN]; | ||
812 | dn->sysctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN]; | ||
813 | dn->sysctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ]; | ||
814 | dn->sysctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING]; | ||
815 | dn->sysctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT]; | ||
816 | dn->sysctl_table[7].data = &dn->dccp_loose; | ||
817 | |||
818 | dn->sysctl_header = register_net_sysctl_table(net, | ||
819 | nf_net_netfilter_sysctl_path, dn->sysctl_table); | ||
820 | if (!dn->sysctl_header) { | ||
821 | kfree(dn->sysctl_table); | ||
822 | goto out; | ||
823 | } | ||
783 | #endif | 824 | #endif |
825 | |||
826 | return 0; | ||
827 | |||
828 | out: | ||
829 | kfree(dn); | ||
830 | return err; | ||
831 | } | ||
832 | |||
833 | static __net_exit void dccp_net_exit(struct net *net) | ||
834 | { | ||
835 | struct dccp_net *dn = dccp_pernet(net); | ||
836 | #ifdef CONFIG_SYSCTL | ||
837 | unregister_net_sysctl_table(dn->sysctl_header); | ||
838 | kfree(dn->sysctl_table); | ||
839 | #endif | ||
840 | kfree(dn); | ||
841 | |||
842 | net_assign_generic(net, dccp_net_id, NULL); | ||
843 | } | ||
844 | |||
845 | static struct pernet_operations dccp_net_ops = { | ||
846 | .init = dccp_net_init, | ||
847 | .exit = dccp_net_exit, | ||
784 | }; | 848 | }; |
785 | 849 | ||
786 | static int __init nf_conntrack_proto_dccp_init(void) | 850 | static int __init nf_conntrack_proto_dccp_init(void) |
787 | { | 851 | { |
788 | int err; | 852 | int err; |
789 | 853 | ||
790 | err = nf_conntrack_l4proto_register(&dccp_proto4); | 854 | err = register_pernet_gen_subsys(&dccp_net_id, &dccp_net_ops); |
791 | if (err < 0) | 855 | if (err < 0) |
792 | goto err1; | 856 | goto err1; |
793 | 857 | ||
794 | err = nf_conntrack_l4proto_register(&dccp_proto6); | 858 | err = nf_conntrack_l4proto_register(&dccp_proto4); |
795 | if (err < 0) | 859 | if (err < 0) |
796 | goto err2; | 860 | goto err2; |
861 | |||
862 | err = nf_conntrack_l4proto_register(&dccp_proto6); | ||
863 | if (err < 0) | ||
864 | goto err3; | ||
797 | return 0; | 865 | return 0; |
798 | 866 | ||
799 | err2: | 867 | err3: |
800 | nf_conntrack_l4proto_unregister(&dccp_proto4); | 868 | nf_conntrack_l4proto_unregister(&dccp_proto4); |
869 | err2: | ||
870 | unregister_pernet_gen_subsys(dccp_net_id, &dccp_net_ops); | ||
801 | err1: | 871 | err1: |
802 | return err; | 872 | return err; |
803 | } | 873 | } |
804 | 874 | ||
805 | static void __exit nf_conntrack_proto_dccp_fini(void) | 875 | static void __exit nf_conntrack_proto_dccp_fini(void) |
806 | { | 876 | { |
877 | unregister_pernet_gen_subsys(dccp_net_id, &dccp_net_ops); | ||
807 | nf_conntrack_l4proto_unregister(&dccp_proto6); | 878 | nf_conntrack_l4proto_unregister(&dccp_proto6); |
808 | nf_conntrack_l4proto_unregister(&dccp_proto4); | 879 | nf_conntrack_l4proto_unregister(&dccp_proto4); |
809 | } | 880 | } |