1616#include <linux/skbuff.h>
1717#include <linux/dccp.h>
1818
19+ #include <net/net_namespace.h>
20+ #include <net/netns/generic.h>
21+
1922#include <linux/netfilter/nfnetlink_conntrack.h>
2023#include <net/netfilter/nf_conntrack.h>
2124#include <net/netfilter/nf_conntrack_l4proto.h>
2225#include <net/netfilter/nf_log.h>
2326
2427static DEFINE_RWLOCK (dccp_lock );
2528
26- static int nf_ct_dccp_loose __read_mostly = 1 ;
27-
2829/* Timeouts are based on values from RFC4340:
2930 *
3031 * - REQUEST:
@@ -72,16 +73,6 @@ static int nf_ct_dccp_loose __read_mostly = 1;
7273
7374#define DCCP_MSL (2 * 60 * HZ)
7475
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-
8576static const char * const dccp_state_names [] = {
8677 [CT_DCCP_NONE ] = "NONE" ,
8778 [CT_DCCP_REQUEST ] = "REQUEST" ,
@@ -393,6 +384,22 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] =
393384 },
394385};
395386
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+
396403static bool dccp_pkt_to_tuple (const struct sk_buff * skb , unsigned int dataoff ,
397404 struct nf_conntrack_tuple * tuple )
398405{
@@ -419,6 +426,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
419426 unsigned int dataoff )
420427{
421428 struct net * net = nf_ct_net (ct );
429+ struct dccp_net * dn ;
422430 struct dccp_hdr _dh , * dh ;
423431 const char * msg ;
424432 u_int8_t state ;
@@ -429,7 +437,8 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
429437 state = dccp_state_table [CT_DCCP_ROLE_CLIENT ][dh -> dccph_type ][CT_DCCP_NONE ];
430438 switch (state ) {
431439 default :
432- if (nf_ct_dccp_loose == 0 ) {
440+ dn = dccp_pernet (net );
441+ if (dn -> dccp_loose == 0 ) {
433442 msg = "nf_ct_dccp: not picking up existing connection " ;
434443 goto out_invalid ;
435444 }
@@ -465,6 +474,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
465474 u_int8_t pf , unsigned int hooknum )
466475{
467476 struct net * net = nf_ct_net (ct );
477+ struct dccp_net * dn ;
468478 enum ip_conntrack_dir dir = CTINFO2DIR (ctinfo );
469479 struct dccp_hdr _dh , * dh ;
470480 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,
542552 ct -> proto .dccp .last_pkt = type ;
543553 ct -> proto .dccp .state = new_state ;
544554 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 ]);
546558
547559 return NF_ACCEPT ;
548560}
@@ -660,70 +672,61 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
660672#endif
661673
662674#ifdef CONFIG_SYSCTL
663- static unsigned int dccp_sysctl_table_users ;
664- static struct ctl_table_header * dccp_sysctl_header ;
665- static ctl_table dccp_sysctl_table [] = {
675+ /* template, data assigned later */
676+ static struct ctl_table dccp_sysctl_table [] = {
666677 {
667678 .ctl_name = CTL_UNNUMBERED ,
668679 .procname = "nf_conntrack_dccp_timeout_request" ,
669- .data = & dccp_timeout [CT_DCCP_REQUEST ],
670680 .maxlen = sizeof (unsigned int ),
671681 .mode = 0644 ,
672682 .proc_handler = proc_dointvec_jiffies ,
673683 },
674684 {
675685 .ctl_name = CTL_UNNUMBERED ,
676686 .procname = "nf_conntrack_dccp_timeout_respond" ,
677- .data = & dccp_timeout [CT_DCCP_RESPOND ],
678687 .maxlen = sizeof (unsigned int ),
679688 .mode = 0644 ,
680689 .proc_handler = proc_dointvec_jiffies ,
681690 },
682691 {
683692 .ctl_name = CTL_UNNUMBERED ,
684693 .procname = "nf_conntrack_dccp_timeout_partopen" ,
685- .data = & dccp_timeout [CT_DCCP_PARTOPEN ],
686694 .maxlen = sizeof (unsigned int ),
687695 .mode = 0644 ,
688696 .proc_handler = proc_dointvec_jiffies ,
689697 },
690698 {
691699 .ctl_name = CTL_UNNUMBERED ,
692700 .procname = "nf_conntrack_dccp_timeout_open" ,
693- .data = & dccp_timeout [CT_DCCP_OPEN ],
694701 .maxlen = sizeof (unsigned int ),
695702 .mode = 0644 ,
696703 .proc_handler = proc_dointvec_jiffies ,
697704 },
698705 {
699706 .ctl_name = CTL_UNNUMBERED ,
700707 .procname = "nf_conntrack_dccp_timeout_closereq" ,
701- .data = & dccp_timeout [CT_DCCP_CLOSEREQ ],
702708 .maxlen = sizeof (unsigned int ),
703709 .mode = 0644 ,
704710 .proc_handler = proc_dointvec_jiffies ,
705711 },
706712 {
707713 .ctl_name = CTL_UNNUMBERED ,
708714 .procname = "nf_conntrack_dccp_timeout_closing" ,
709- .data = & dccp_timeout [CT_DCCP_CLOSING ],
710715 .maxlen = sizeof (unsigned int ),
711716 .mode = 0644 ,
712717 .proc_handler = proc_dointvec_jiffies ,
713718 },
714719 {
715720 .ctl_name = CTL_UNNUMBERED ,
716721 .procname = "nf_conntrack_dccp_timeout_timewait" ,
717- .data = & dccp_timeout [CT_DCCP_TIMEWAIT ],
718722 .maxlen = sizeof (unsigned int ),
719723 .mode = 0644 ,
720724 .proc_handler = proc_dointvec_jiffies ,
721725 },
722726 {
723727 .ctl_name = CTL_UNNUMBERED ,
724728 .procname = "nf_conntrack_dccp_loose" ,
725- .data = & nf_ct_dccp_loose ,
726- .maxlen = sizeof (nf_ct_dccp_loose ),
729+ .maxlen = sizeof (int ),
727730 .mode = 0644 ,
728731 .proc_handler = proc_dointvec ,
729732 },
@@ -751,11 +754,6 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
751754 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple ,
752755 .nla_policy = nf_ct_port_nla_policy ,
753756#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
759757};
760758
761759static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
@@ -776,34 +774,107 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
776774 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple ,
777775 .nla_policy = nf_ct_port_nla_policy ,
778776#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+
779802#ifdef CONFIG_SYSCTL
780- .ctl_table_users = & dccp_sysctl_table_users ,
781- .ctl_table_header = & dccp_sysctl_header ,
782- .ctl_table = dccp_sysctl_table ,
803+ err = - ENOMEM ;
804+ dn -> sysctl_table = kmemdup (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+ }
783824#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 ,
784848};
785849
786850static int __init nf_conntrack_proto_dccp_init (void )
787851{
788852 int err ;
789853
790- err = nf_conntrack_l4proto_register ( & dccp_proto4 );
854+ err = register_pernet_gen_subsys ( & dccp_net_id , & dccp_net_ops );
791855 if (err < 0 )
792856 goto err1 ;
793857
794- err = nf_conntrack_l4proto_register (& dccp_proto6 );
858+ err = nf_conntrack_l4proto_register (& dccp_proto4 );
795859 if (err < 0 )
796860 goto err2 ;
861+
862+ err = nf_conntrack_l4proto_register (& dccp_proto6 );
863+ if (err < 0 )
864+ goto err3 ;
797865 return 0 ;
798866
799- err2 :
867+ err3 :
800868 nf_conntrack_l4proto_unregister (& dccp_proto4 );
869+ err2 :
870+ unregister_pernet_gen_subsys (dccp_net_id , & dccp_net_ops );
801871err1 :
802872 return err ;
803873}
804874
805875static void __exit nf_conntrack_proto_dccp_fini (void )
806876{
877+ unregister_pernet_gen_subsys (dccp_net_id , & dccp_net_ops );
807878 nf_conntrack_l4proto_unregister (& dccp_proto6 );
808879 nf_conntrack_l4proto_unregister (& dccp_proto4 );
809880}
0 commit comments