aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorCyrill Gorcunov <gorcunov@openvz.org>2009-03-16 11:30:49 -0400
committerPatrick McHardy <kaber@trash.net>2009-03-16 11:30:49 -0400
commit1546000fe8db0d3f47b0ef1dd487ec23fbd95313 (patch)
treedc077facf57dd9b01cd41c16dd45358f7ebcbf18 /net
parent81a1d3c31e3517f9939b3e04d21cf4a6b0997419 (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>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_proto_dccp.c145
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
24static DEFINE_RWLOCK(dccp_lock); 27static DEFINE_RWLOCK(dccp_lock);
25 28
26static 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
75static 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
85static const char * const dccp_state_names[] = { 76static 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 */
388static int dccp_net_id;
389struct 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
398static inline struct dccp_net *dccp_pernet(struct net *net)
399{
400 return net_generic(net, dccp_net_id);
401}
402
396static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, 403static 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
663static unsigned int dccp_sysctl_table_users; 675/* template, data assigned later */
664static struct ctl_table_header *dccp_sysctl_header; 676static struct ctl_table dccp_sysctl_table[] = {
665static 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
761static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { 759static 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
779static __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
828out:
829 kfree(dn);
830 return err;
831}
832
833static __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
845static struct pernet_operations dccp_net_ops = {
846 .init = dccp_net_init,
847 .exit = dccp_net_exit,
784}; 848};
785 849
786static int __init nf_conntrack_proto_dccp_init(void) 850static 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
799err2: 867err3:
800 nf_conntrack_l4proto_unregister(&dccp_proto4); 868 nf_conntrack_l4proto_unregister(&dccp_proto4);
869err2:
870 unregister_pernet_gen_subsys(dccp_net_id, &dccp_net_ops);
801err1: 871err1:
802 return err; 872 return err;
803} 873}
804 874
805static void __exit nf_conntrack_proto_dccp_fini(void) 875static 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}