introduce netfilter conntrack protos pernet functionality v2
Subsystems (3)
v2 cover introduce netfilter conntrack protos pernet functionality v2
Hi all,
here is a second request for comments on netfilter conntrack protos per-net functionality. The following protos are covered
now: dccp, sctp, udplite, tcp, udp, icmp. So I would really like to hear kind of comments (angry screams maybe :) on the series.
To Patric:
Patric I decided to not assign sysctls data by iterative fasion since it could lead for harder grep'ability, and in case if order of "enum entries" changed the sysctls will be silently broken. To make these assignments shorter I've added ___PERNET_TO_DAT macro which has quite a small lifetime inside sources. If you prefer to assign them in for(;;) -- just say the word and I'll remake it :)
So please review and comment (if possible). Thanks! (If someone could even test it -- it would be amaizing!
I've been playing a bit with the series in qemu+lxc)
Hope I didn't miss anything.
Cyrill
RFC v2 1/7 net: sysctl_net - use net_eq to compare nets
--- net/sysctl_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sysctl_net.c +1 -1
@@ -61,7 +61,7 @@ static struct ctl_table_root net_sysctl_static int net_ctl_ro_header_perms (struct ctl_table_root *root,struct nsproxy *namespaces,struct ctl_table *table) { -if (namespaces->net_ns == &init_net) +if (net_eq (namespaces->net_ns, &init_net))return table->mode;else return table->mode & ~0222 ;
RFC v2 2/7 net: netfilter conntrack - add per-net functionality for DCCP protocol
In reply to Cyrill GorcunovModule specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
--- net/netfilter/nf_conntrack_proto_dccp.c | 145 +++++++++++++++++++++++--------- 1 file changed, 108 insertions(+), 37 deletions(-)
net/netfilter/nf_conntrack_proto_dccp.c +108 -37
@@ -16,6 +16,9 @@#include <linux/skbuff.h> #include <linux/dccp.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> +#include <linux/netfilter/nfnetlink_conntrack.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_l4proto.h>
@@ -23,8 +26,6 @@static DEFINE_RWLOCK (dccp_lock); -static int nf_ct_dccp_loose__read_mostly =1 ; -/* Timeouts are based on values from RFC4340: * * - REQUEST:
@@ -72,16 +73,6 @@ static int nf_ct_dccp_loose __read_mostl#define DCCP_MSL (2 * 60 * HZ) -static unsigned int dccp_timeout[CT_DCCP_MAX +1 ]__read_mostly = { - [CT_DCCP_REQUEST ] =2 *DCCP_MSL , - [CT_DCCP_RESPOND ] =4 *DCCP_MSL , - [CT_DCCP_PARTOPEN ] =4 *DCCP_MSL , - [CT_DCCP_OPEN ] =12 *3600 *HZ , - [CT_DCCP_CLOSEREQ ] =64 *HZ , - [CT_DCCP_CLOSING ] =64 *HZ , - [CT_DCCP_TIMEWAIT ] =2 *DCCP_MSL , -}; -static const char *const dccp_state_names[] = { [CT_DCCP_NONE ] ="NONE" , [CT_DCCP_REQUEST ] ="REQUEST" ,
@@ -393,6 +384,22 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][D }, }; +/* this module per-net specifics */ +static int dccp_net_id; +struct dccp_net { +int dccp_loose; +unsigned int dccp_timeout[CT_DCCP_MAX +1 ]; +#ifdef CONFIG_SYSCTL +struct ctl_table_header *sysctl_header; +struct ctl_table *sysctl_table; +#endif +}; + +static inline struct dccp_net *dccp_pernet (struct net *net) +{ +return net_generic (net, dccp_net_id); +} +static bool dccp_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff,struct nf_conntrack_tuple *tuple) {
@@ -419,6 +426,7 @@ static bool dccp_new(struct nf_conn *ct, unsigned int dataoff) {struct net *net =nf_ct_net (ct); +struct dccp_net *dn;struct dccp_hdr _dh, *dh;const char *msg;u_int8_t state;
@@ -429,7 +437,8 @@ static bool dccp_new(struct nf_conn *ct, state = dccp_state_table[CT_DCCP_ROLE_CLIENT ][dh->dccph_type][CT_DCCP_NONE ];switch (state) {default : -if (nf_ct_dccp_loose ==0 ) { + dn =dccp_pernet (net); +if (dn->dccp_loose ==0 ) { msg ="nf_ct_dccp: not picking up existing connection " ; goto out_invalid; }
@@ -465,6 +474,7 @@ static int dccp_packet(struct nf_conn *c u_int8_t pf, unsigned int hooknum) {struct net *net =nf_ct_net (ct); +struct dccp_net *dn;enum ip_conntrack_dir dir =CTINFO2DIR (ctinfo);struct dccp_hdr _dh, *dh;u_int8_t type, old_state, new_state;
@@ -542,7 +552,9 @@ static int dccp_packet(struct nf_conn *c ct->proto.dccp.last_pkt = type; ct->proto.dccp.state = new_state;write_unlock_bh (&dccp_lock); -nf_ct_refresh_acct (ct, ctinfo, skb, dccp_timeout[new_state]); + + dn =dccp_pernet (net); +nf_ct_refresh_acct (ct, ctinfo, skb, dn->dccp_timeout[new_state]);return NF_ACCEPT ; }
@@ -660,13 +672,11 @@ static int nlattr_to_dccp(struct nlattr#endif #ifdef CONFIG_SYSCTL -static unsigned int dccp_sysctl_table_users; -static struct ctl_table_header *dccp_sysctl_header; -static ctl_table dccp_sysctl_table[] = { +/* template, data assigned later */ +static struct ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_request", - .data = &dccp_timeout[CT_DCCP_REQUEST], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -674,7 +684,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_respond", - .data = &dccp_timeout[CT_DCCP_RESPOND], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -682,7 +691,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_partopen", - .data = &dccp_timeout[CT_DCCP_PARTOPEN], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -690,7 +698,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_open", - .data = &dccp_timeout[CT_DCCP_OPEN], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -698,7 +705,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_closereq", - .data = &dccp_timeout[CT_DCCP_CLOSEREQ], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -706,7 +712,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_closing", - .data = &dccp_timeout[CT_DCCP_CLOSING], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -714,7 +719,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_timewait", - .data = &dccp_timeout[CT_DCCP_TIMEWAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -722,8 +726,7 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_loose", - .data = &nf_ct_dccp_loose, - .maxlen = sizeof(nf_ct_dccp_loose), + .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec, },
@@ -751,11 +754,6 @@ static struct nf_conntrack_l4proto dccp_ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &dccp_sysctl_table_users, - .ctl_table_header = &dccp_sysctl_header, - .ctl_table = dccp_sysctl_table, -#endif };static struct nf_conntrack_l4proto dccp_proto6__read_mostly = {
@@ -776,34 +774,107 @@ static struct nf_conntrack_l4proto dccp_ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif +}; + +static __net_init int dccp_net_init (struct net *net) +{ +struct dccp_net *dn; +int err; + + dn =kmalloc (sizeof (*dn),GFP_KERNEL ); +if (!dn) +return -ENOMEM ; + +/* default values */ + dn->dccp_loose =1 ; + dn->dccp_timeout[CT_DCCP_REQUEST ] =2 *DCCP_MSL ; + dn->dccp_timeout[CT_DCCP_RESPOND ] =4 *DCCP_MSL ; + dn->dccp_timeout[CT_DCCP_PARTOPEN ] =4 *DCCP_MSL ; + dn->dccp_timeout[CT_DCCP_OPEN ] =12 *3600 *HZ ; + dn->dccp_timeout[CT_DCCP_CLOSEREQ ] =64 *HZ ; + dn->dccp_timeout[CT_DCCP_CLOSING ] =64 *HZ ; + dn->dccp_timeout[CT_DCCP_TIMEWAIT ] =2 *DCCP_MSL ; + + err =net_assign_generic (net, dccp_net_id, dn); +if (err) + goto out; +#ifdef CONFIG_SYSCTL - .ctl_table_users = &dccp_sysctl_table_users, - .ctl_table_header = &dccp_sysctl_header, - .ctl_table = dccp_sysctl_table, + err = -ENOMEM ; + dn->sysctl_table =kmemdup (dccp_sysctl_table, +sizeof (dccp_sysctl_table),GFP_KERNEL ); +if (!dn->sysctl_table) + goto out; + + dn->sysctl_table[0 ].data = &dn->dccp_timeout[CT_DCCP_REQUEST ]; + dn->sysctl_table[1 ].data = &dn->dccp_timeout[CT_DCCP_RESPOND ]; + dn->sysctl_table[2 ].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN ]; + dn->sysctl_table[3 ].data = &dn->dccp_timeout[CT_DCCP_OPEN ]; + dn->sysctl_table[4 ].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ ]; + dn->sysctl_table[5 ].data = &dn->dccp_timeout[CT_DCCP_CLOSING ]; + dn->sysctl_table[6 ].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT ]; + dn->sysctl_table[7 ].data = &dn->dccp_loose; + + dn->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, dn->sysctl_table); +if (!dn->sysctl_header) { +kfree (dn->sysctl_table); + goto out; + }#endif + +return 0 ; + +out: +kfree (dn); +return err; +} + +static __net_exit void dccp_net_exit(struct net *net) +{ +struct dccp_net *dn =dccp_pernet (net); +#ifdef CONFIG_SYSCTL +unregister_net_sysctl_table (dn->sysctl_header); +kfree (dn->sysctl_table); +#endif +kfree (dn); + +net_assign_generic (net, dccp_net_id,NULL ); +} + +static struct pernet_operations dccp_net_ops = { + .init = dccp_net_init, + .exit = dccp_net_exit, };static int __init nf_conntrack_proto_dccp_init (void ) {int err; - err =nf_conntrack_l4proto_register (&dccp_proto4); + err =register_pernet_gen_subsys (&dccp_net_id, &dccp_net_ops);if (err <0 ) goto err1; - err =nf_conntrack_l4proto_register (&dccp_proto6); + err =nf_conntrack_l4proto_register (&dccp_proto4);if (err <0 ) goto err2; + + err =nf_conntrack_l4proto_register (&dccp_proto6); +if (err <0 ) + goto err3;return 0 ; -err2: +err3:nf_conntrack_l4proto_unregister (&dccp_proto4); +err2: +unregister_pernet_gen_subsys (dccp_net_id, &dccp_net_ops); err1:return err; } static void __exit nf_conntrack_proto_dccp_fini(void) { +unregister_pernet_gen_subsys (dccp_net_id, &dccp_net_ops);nf_conntrack_l4proto_unregister (&dccp_proto6);nf_conntrack_l4proto_unregister (&dccp_proto4); }
RFC v2 3/7 net: netfilter conntrack - add per-net functionality for SCTP protocol
In reply to Cyrill GorcunovModule specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
--- net/netfilter/nf_conntrack_proto_sctp.c | 186 +++++++++++++++++++++++++------- 1 file changed, 146 insertions(+), 40 deletions(-)
net/netfilter/nf_conntrack_proto_sctp.c +146 -40
@@ -21,6 +21,9 @@#include <linux/spinlock.h> #include <linux/interrupt.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> +#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_ecache.h>
@@ -49,16 +52,6 @@ static const char *const sctp_conntrack_#define HOURS * 60 MINS#define DAYS * 24 HOURS -static unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX ]__read_mostly = { - [SCTP_CONNTRACK_CLOSED] = 10 SECS, - [SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS, - [SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS, - [SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS, - [SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000, - [SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000, - [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS, -}; -#define sNO SCTP_CONNTRACK_NONE#define sCL SCTP_CONNTRACK_CLOSED#define sCW SCTP_CONNTRACK_COOKIE_WAIT
@@ -130,6 +123,25 @@ static const u8 sctp_conntracks[2][9][SC } }; +/* this module per-net specifics */ +static int sctp_net_id; +struct sctp_net { +unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX ]; +#ifdef CONFIG_SYSCTL +struct ctl_table_header *sysctl_header; +struct ctl_table *sysctl_table; +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +struct ctl_table_header *compat_sysctl_header; +struct ctl_table *compat_sysctl_table; +#endif +#endif +}; + +static inline struct sctp_net *sctp_pernet (struct net *net) +{ +return net_generic (net, sctp_net_id); +} +static bool sctp_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff,struct nf_conntrack_tuple *tuple) {
@@ -297,6 +309,7 @@ static int sctp_packet(struct nf_conn *cconst struct sctp_chunkhdr *sch;struct sctp_chunkhdr _sch;u_int32_t offset, count; +struct sctp_net *sn;unsigned long map[256 /sizeof (unsigned long )] = {0 }; sh =skb_header_pointer (skb, dataoff,sizeof (_sctph), &_sctph);
@@ -373,7 +386,8 @@ static int sctp_packet(struct nf_conn *c }write_unlock_bh (&sctp_lock); -nf_ct_refresh_acct (ct, ctinfo, skb, sctp_timeouts[new_state]); + sn =sctp_pernet (nf_ct_net (ct)); +nf_ct_refresh_acct (ct, ctinfo, skb, sn->sctp_timeouts[new_state]); if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED && dir == IP_CT_DIR_REPLY &&
@@ -540,54 +554,46 @@ static int nlattr_to_sctp(struct nlattr#endif #ifdef CONFIG_SYSCTL -static unsigned int sctp_sysctl_table_users; -static struct ctl_table_header *sctp_sysctl_header; +/* templates, data assigned later */ static struct ctl_table sctp_sysctl_table[] = { { .procname = "nf_conntrack_sctp_timeout_closed", - .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_cookie_wait", - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_cookie_echoed", - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_established", - .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_sent", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_recd", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -601,49 +607,42 @@ static struct ctl_table sctp_sysctl_tablstatic struct ctl_table sctp_compat_sysctl_table[] = { { .procname ="ip_conntrack_sctp_timeout_closed" , - .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_cookie_wait" , - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_cookie_echoed" , - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_established" , - .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_sent" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_recd" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_ack_sent" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies,
@@ -653,7 +652,7 @@ static struct ctl_table sctp_compat_sysc } };#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ -#endif +#endif /* CONFIG_SYSCTL */ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4__read_mostly = { .l3proto =PF_INET ,
@@ -673,14 +672,6 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &sctp_sysctl_table_users, - .ctl_table_header = &sctp_sysctl_header, - .ctl_table = sctp_sysctl_table, -#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT - .ctl_compat_table = sctp_compat_sysctl_table, -#endif -#endif };static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6__read_mostly = {
@@ -701,21 +692,133 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif +}; + +static __net_init int sctp_net_init (struct net *net) +{ +struct sctp_net *sn; +int err; + + sn =kmalloc (sizeof (*sn),GFP_KERNEL ); +if (!sn) +return -ENOMEM ; + +/* default values */ + sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED] = 10 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS; + + err =net_assign_generic (net, sctp_net_id, sn); +if (err) + goto out; +#ifdef CONFIG_SYSCTL - .ctl_table_users = &sctp_sysctl_table_users, - .ctl_table_header = &sctp_sysctl_header, - .ctl_table = sctp_sysctl_table, + err = -ENOMEM ; + sn->sysctl_table =kmemdup (sctp_sysctl_table, +sizeof (sctp_sysctl_table),GFP_KERNEL ); +if (!sn->sysctl_table) + goto out; + +#define ___PERNET_TO_DAT (i, j) \ + sn->sysctl_table[i].data = &sn->sctp_timeouts[j] + +___PERNET_TO_DAT (0 ,SCTP_CONNTRACK_CLOSED ); +___PERNET_TO_DAT (1 ,SCTP_CONNTRACK_COOKIE_WAIT ); +___PERNET_TO_DAT (2 ,SCTP_CONNTRACK_COOKIE_ECHOED ); +___PERNET_TO_DAT (3 ,SCTP_CONNTRACK_ESTABLISHED ); +___PERNET_TO_DAT (4 ,SCTP_CONNTRACK_SHUTDOWN_SENT ); +___PERNET_TO_DAT (5 ,SCTP_CONNTRACK_SHUTDOWN_RECD ); +___PERNET_TO_DAT (6 ,SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ); + +#undef ___PERNET_TO_DAT + + sn->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, sn->sysctl_table); +if (!sn->sysctl_header) + goto out_free; + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + sn->compat_sysctl_table =kmemdup (sctp_compat_sysctl_table, +sizeof (sctp_compat_sysctl_table),GFP_KERNEL ); +if (!sn->compat_sysctl_table) + goto out_sysctl; + +#define ___PERNET_TO_DAT (i, j) \ + sn->compat_sysctl_table[i].data = &sn->sctp_timeouts[j] + +___PERNET_TO_DAT (0 ,SCTP_CONNTRACK_CLOSED ); +___PERNET_TO_DAT (1 ,SCTP_CONNTRACK_COOKIE_WAIT ); +___PERNET_TO_DAT (2 ,SCTP_CONNTRACK_COOKIE_ECHOED ); +___PERNET_TO_DAT (3 ,SCTP_CONNTRACK_ESTABLISHED ); +___PERNET_TO_DAT (4 ,SCTP_CONNTRACK_SHUTDOWN_SENT ); +___PERNET_TO_DAT (5 ,SCTP_CONNTRACK_SHUTDOWN_RECD ); +___PERNET_TO_DAT (6 ,SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ); + +#undef ___PERNET_TO_DAT + + sn->compat_sysctl_header =register_net_sysctl_table (net, + nf_net_ipv4_netfilter_sysctl_path, sn->compat_sysctl_table); +if (!sn->compat_sysctl_header) + goto out_free_compat; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ +#endif /* CONFIG_SYSCTL */ + +return 0 ; + +#ifdef CONFIG_SYSCTL + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +out_free_compat: +kfree (sn->compat_sysctl_table); +#endif +out_sysctl: +unregister_net_sysctl_table (sn->sysctl_header); +out_free: +kfree (sn->sysctl_table); +#endif + +out: +kfree (sn); +return err; +} + +static __net_exit void sctp_net_exit(struct net *net) +{ +struct sctp_net *sn =sctp_pernet (net); +#ifdef CONFIG_SYSCTL +unregister_net_sysctl_table (sn->sysctl_header); +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +unregister_net_sysctl_table (sn->compat_sysctl_header); +kfree (sn->compat_sysctl_table); +#endif +kfree (sn->sysctl_table);#endif +kfree (sn); + +net_assign_generic (net, sctp_net_id,NULL ); +} + +static struct pernet_operations sctp_net_ops = { + .init = sctp_net_init, + .exit = sctp_net_exit, };static int __init nf_conntrack_proto_sctp_init (void ) {int ret; + ret =register_pernet_gen_subsys (&sctp_net_id, &sctp_net_ops); +if (ret <0 ) + goto out; + ret =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_sctp4);if (ret) {printk ("nf_conntrack_l4proto_sctp4: protocol register failed\n" ); - goto out; + goto cleanup_net; } ret =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_sctp6);if (ret) {
@@ -727,12 +830,15 @@ static int __init nf_conntrack_proto_sct cleanup_sctp4:nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp4); + cleanup_net: +unregister_pernet_gen_subsys (sctp_net_id, &sctp_net_ops); out:return ret; } static void __exit nf_conntrack_proto_sctp_fini(void) { +unregister_pernet_gen_subsys (sctp_net_id, &sctp_net_ops);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp6);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp4); }
RFC v2 4/7 net: netfilter conntrack - add per-net functionality for UDPLITE protocol
In reply to Cyrill GorcunovModule specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
--- net/netfilter/nf_conntrack_proto_udplite.c | 115 ++++++++++++++++++++++++----- 1 file changed, 96 insertions(+), 19 deletions(-)
net/netfilter/nf_conntrack_proto_udplite.c +96 -19
@@ -17,6 +17,9 @@#include <net/ip6_checksum.h> #include <net/checksum.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> +#include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv6.h>
@@ -24,8 +27,21 @@#include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_log.h> -static unsigned int nf_ct_udplite_timeout__read_mostly =30 *HZ ; -static unsigned int nf_ct_udplite_timeout_stream__read_mostly =180 *HZ ; +/* this module per-net specifics */ +static int udplite_net_id; +struct udplite_net { +unsigned int udplite_timeout; +unsigned int udplite_timeout_stream; +#ifdef CONFIG_SYSCTL +struct ctl_table_header *sysctl_header; +struct ctl_table *sysctl_table; +#endif +}; + +static inline struct udplite_net *udplite_pernet (struct net *net) +{ +return net_generic (net, udplite_net_id); +} static bool udplite_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
@@ -68,16 +84,18 @@ static int udplite_packet(struct nf_conn u_int8_t pf, unsigned int hooknum) { +struct udplite_net *un =udplite_pernet (nf_ct_net (ct)); +/* If we've seen traffic both ways, this is some kind of UDP stream. Extend timeout. */ if (test_bit (IPS_SEEN_REPLY_BIT , &ct->status)) {nf_ct_refresh_acct (ct, ctinfo, skb, - nf_ct_udplite_timeout_stream); + un->udplite_timeout_stream);/* Also, more likely to be important, and not a probe */ if (!test_and_set_bit (IPS_ASSURED_BIT , &ct->status))nf_conntrack_event_cache (IPCT_STATUS , ct); }else -nf_ct_refresh_acct (ct, ctinfo, skb, nf_ct_udplite_timeout); +nf_ct_refresh_acct (ct, ctinfo, skb, un->udplite_timeout);return NF_ACCEPT ; }
@@ -142,13 +160,11 @@ static int udplite_error(struct net *net } #ifdef CONFIG_SYSCTL -static unsigned int udplite_sysctl_table_users; -static struct ctl_table_header *udplite_sysctl_header; +/* template, data assigned later */ static struct ctl_table udplite_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_udplite_timeout", - .data = &nf_ct_udplite_timeout, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -156,7 +172,6 @@ static struct ctl_table udplite_sysctl_t { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_udplite_timeout_stream", - .data = &nf_ct_udplite_timeout_stream, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -183,11 +198,6 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &udplite_sysctl_table_users, - .ctl_table_header = &udplite_sysctl_header, - .ctl_table = udplite_sysctl_table, -#endif }; static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
@@ -206,32 +216,99 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif +}; + +static __net_init int udplite_net_init (struct net *net) +{ +struct udplite_net *un; +int err; + + un =kmalloc (sizeof (*un),GFP_KERNEL ); +if (!un) +return -ENOMEM ; + +/* default values */ + un->udplite_timeout =30 *HZ ; + un->udplite_timeout_stream =180 *HZ ; + + err =net_assign_generic (net, udplite_net_id, un); +if (err) + goto out; + +#ifdef CONFIG_SYSCTL + err = -ENOMEM ; + un->sysctl_table =kmemdup (udplite_sysctl_table, +sizeof (udplite_sysctl_table),GFP_KERNEL ); +if (!un->sysctl_table) + goto out; + + un->sysctl_table[0 ].data = &un->udplite_timeout; + un->sysctl_table[1 ].data = &un->udplite_timeout_stream; + + un->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, un->sysctl_table); +if (!un->sysctl_header) + goto out_free; +#endif /* CONFIG_SYSCTL */ + +return 0 ; + +#ifdef CONFIG_SYSCTL +out_free: +kfree (un->sysctl_table); +#endif + +out: +kfree (un); +return err; +} + +static __net_exit void udplite_net_exit(struct net *net) +{ +struct udplite_net *un =udplite_pernet (net);#ifdef CONFIG_SYSCTL - .ctl_table_users = &udplite_sysctl_table_users, - .ctl_table_header = &udplite_sysctl_header, - .ctl_table = udplite_sysctl_table, +unregister_net_sysctl_table (un->sysctl_header); +kfree (un->sysctl_table);#endif +kfree (un); + +net_assign_generic (net, udplite_net_id,NULL ); +} + +static struct pernet_operations udplite_net_ops = { + .init = udplite_net_init, + .exit = udplite_net_exit, };static int __init nf_conntrack_proto_udplite_init (void ) {int err; - err =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_udplite4); + err =register_pernet_gen_subsys (&udplite_net_id, &udplite_net_ops);if (err <0 ) goto err1; - err =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_udplite6); + + err =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_udplite4);if (err <0 ) goto err2; + + err =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_udplite6); +if (err <0 ) + goto err3; +return 0 ; -err2: + +err3:nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_udplite4); +err2: +unregister_pernet_gen_subsys (udplite_net_id, &udplite_net_ops); err1:return err; } static void __exit nf_conntrack_proto_udplite_exit(void) { +unregister_pernet_gen_subsys (udplite_net_id, &udplite_net_ops);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_udplite6);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_udplite4); }
RFC v2 5/7 net: netfilter conntrack - add per-net functionality for TCP protocol
In reply to Cyrill GorcunovModule specific data moved into per-net site and being allocated/freed during net namespace creation/deletion. For this reason module_init/exit calls added.
--- net/netfilter/nf_conntrack_proto_tcp.c | 290 ++++++++++++++++++++++++--------- 1 file changed, 212 insertions(+), 78 deletions(-)
net/netfilter/nf_conntrack_proto_tcp.c +212 -78
@@ -18,6 +18,9 @@#include <net/tcp.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> +#include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv6.h>
@@ -29,20 +32,6 @@/* Protects ct->proto.tcp */ static DEFINE_RWLOCK (tcp_lock); -/* "Be conservative in what you do, -be liberal in what you accept from others." -If it's non-zero, we mark only out of window RST segments as INVALID. */ -static int nf_ct_tcp_be_liberal__read_mostly =0 ; - -/* If it is set to zero, we disable picking up already established -connections. */ -static int nf_ct_tcp_loose__read_mostly =1 ; - -/* Max number of the retransmitted packets without receiving an (acceptable) -ACK from the destination. If this number is reached, a shorter timer -will be started. */ -static int nf_ct_tcp_max_retrans__read_mostly =3 ; -/* FIXME: Examine ipfilter's timeouts and conntrack transitions more closely. They're more complex. --RR */
@@ -64,23 +53,6 @@ static const char *const tcp_conntrack_n#define HOURS * 60 MINS#define DAYS * 24 HOURS -/* RFC1122 says the R2 limit should be at least 100 seconds. -Linux uses 15 packets as limit, which corresponds -to ~13-30min depending on RTO. */ -static unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS; -static unsigned int nf_ct_tcp_timeout_unacknowledged __read_mostly = 5 MINS; - -static unsigned int tcp_timeouts[TCP_CONNTRACK_MAX ]__read_mostly = { - [TCP_CONNTRACK_SYN_SENT] = 2 MINS, - [TCP_CONNTRACK_SYN_RECV] = 60 SECS, - [TCP_CONNTRACK_ESTABLISHED] = 5 DAYS, - [TCP_CONNTRACK_FIN_WAIT] = 2 MINS, - [TCP_CONNTRACK_CLOSE_WAIT] = 60 SECS, - [TCP_CONNTRACK_LAST_ACK] = 30 SECS, - [TCP_CONNTRACK_TIME_WAIT] = 2 MINS, - [TCP_CONNTRACK_CLOSE] = 10 SECS, -}; -#define sNO TCP_CONNTRACK_NONE#define sSS TCP_CONNTRACK_SYN_SENT#define sSR TCP_CONNTRACK_SYN_RECV
@@ -258,6 +230,51 @@ static const u8 tcp_conntracks[2][6][TCP } }; +/* per-net specifics */ +static int tcp_net_id; +struct tcp_net { +/* +* "Be conservative in what you do, +* be liberal in what you accept from others." +* If it's non-zero, we mark only out of window +* RST segments as INVALID. +*/ +int tcp_be_liberal; +/* +* If it is set to zero, we disable picking up +* already established connections. +*/ +int tcp_loose; +/* +* Max number of the retransmitted packets without +* receiving an (acceptable) ACK from the destination. +* If this number is reached, a shorter timer will be started. +*/ +int tcp_max_retrans; +/* +* RFC1122 says the R2 limit should be at least 100 seconds. +* Linux uses 15 packets as limit, which corresponds +* to ~13-30min depending on RTO. +*/ +unsigned int tcp_timeout_max_retrans; +unsigned int tcp_timeout_unacknowledged; + +unsigned int tcp_timeouts[TCP_CONNTRACK_MAX ]; +#ifdef CONFIG_SYSCTL +struct ctl_table_header *sysctl_header; +struct ctl_table *sysctl_table; +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +struct ctl_table_header *compat_sysctl_header; +struct ctl_table *compat_sysctl_table; +#endif +#endif +}; + +static inline struct tcp_net *tcp_pernet (struct net *net) +{ +return net_generic (net, tcp_net_id); +} +static bool tcp_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff,struct nf_conntrack_tuple *tuple) {
@@ -489,6 +506,7 @@ static bool tcp_in_window(const struct n u_int8_t pf) {struct net *net =nf_ct_net (ct); +struct tcp_net *tn;struct ip_ct_tcp_state *sender = &state->seen[dir];struct ip_ct_tcp_state *receiver = &state->seen[!dir];const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
@@ -666,8 +684,9 @@ static bool tcp_in_window(const struct n res = true; }else { res = false; + tn =tcp_pernet (net);if (sender->flags &IP_CT_TCP_FLAG_BE_LIBERAL || - nf_ct_tcp_be_liberal) + tn->tcp_be_liberal) res = true;if (!res &&LOG_INVALID (net,IPPROTO_TCP )) nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
@@ -810,6 +829,7 @@ static int tcp_packet(struct nf_conn *ct unsigned int hooknum) {struct net *net =nf_ct_net (ct); +struct tcp_net *tn;struct nf_conntrack_tuple *tuple;enum tcp_conntrack new_state, old_state;enum ip_conntrack_dir dir;
@@ -948,6 +968,8 @@ static int tcp_packet(struct nf_conn *ct ct->proto.tcp.last_index = index; ct->proto.tcp.last_dir = dir; + tn =tcp_pernet (net); +pr_debug ("tcp_conntracks: " );nf_ct_dump_tuple (tuple); pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
@@ -960,15 +982,15 @@ static int tcp_packet(struct nf_conn *ct && new_state == TCP_CONNTRACK_FIN_WAIT) ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; -if (ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans && - tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans) - timeout = nf_ct_tcp_timeout_max_retrans; +if (ct->proto.tcp.retrans >= tn->tcp_max_retrans && + tn->tcp_timeouts[new_state] > tn->tcp_timeout_max_retrans) + timeout = tn->tcp_timeout_max_retrans;else if ((ct->proto.tcp.seen[0 ].flags | ct->proto.tcp.seen[1 ].flags) &IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED && - tcp_timeouts[new_state] > nf_ct_tcp_timeout_unacknowledged) - timeout = nf_ct_tcp_timeout_unacknowledged; + tn->tcp_timeouts[new_state] > tn->tcp_timeout_unacknowledged) + timeout = tn->tcp_timeout_unacknowledged;else - timeout = tcp_timeouts[new_state]; + timeout = tn->tcp_timeouts[new_state];write_unlock_bh (&tcp_lock);nf_conntrack_event_cache (IPCT_PROTOINFO_VOLATILE , ct);
@@ -1005,6 +1027,7 @@ static bool tcp_new(struct nf_conn *ct, {enum tcp_conntrack new_state;const struct tcphdr *th; +struct tcp_net *tn;struct tcphdr _tcph;const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[0 ];const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[1 ];
@@ -1023,6 +1046,8 @@ static bool tcp_new(struct nf_conn *ct,return false; } + tn =tcp_pernet (nf_ct_net (ct)); +if (new_state ==TCP_CONNTRACK_SYN_SENT ) {/* SYN packet */ ct->proto.tcp.seen[0].td_end =
@@ -1036,7 +1061,7 @@ static bool tcp_new(struct nf_conn *ct,tcp_options (skb, dataoff, th, &ct->proto.tcp.seen[0 ]); ct->proto.tcp.seen[1 ].flags =0 ; - }else if (nf_ct_tcp_loose ==0 ) { + }else if (tn->tcp_loose ==0 ) {/* Don't try to pick up connections. */ return false; }else {
@@ -1184,75 +1209,64 @@ static int nlattr_to_tcp(struct nlattr *#endif #ifdef CONFIG_SYSCTL -static unsigned int tcp_sysctl_table_users; -static struct ctl_table_header *tcp_sysctl_header; +/* templates, data assigned later */ static struct ctl_table tcp_sysctl_table[] = { { .procname = "nf_conntrack_tcp_timeout_syn_sent", - .data = &tcp_timeouts[TCP_CONNTRACK_SYN_SENT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_syn_recv", - .data = &tcp_timeouts[TCP_CONNTRACK_SYN_RECV], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_established", - .data = &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_fin_wait", - .data = &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_close_wait", - .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_last_ack", - .data = &tcp_timeouts[TCP_CONNTRACK_LAST_ACK], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_time_wait", - .data = &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_close", - .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_max_retrans", - .data = &nf_ct_tcp_timeout_max_retrans, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_unacknowledged", - .data = &nf_ct_tcp_timeout_unacknowledged, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -1260,7 +1274,6 @@ static struct ctl_table tcp_sysctl_table { .ctl_name = NET_NF_CONNTRACK_TCP_LOOSE, .procname = "nf_conntrack_tcp_loose", - .data = &nf_ct_tcp_loose, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1268,7 +1281,6 @@ static struct ctl_table tcp_sysctl_table { .ctl_name = NET_NF_CONNTRACK_TCP_BE_LIBERAL, .procname = "nf_conntrack_tcp_be_liberal", - .data = &nf_ct_tcp_be_liberal, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1276,7 +1288,6 @@ static struct ctl_table tcp_sysctl_table { .ctl_name = NET_NF_CONNTRACK_TCP_MAX_RETRANS, .procname = "nf_conntrack_tcp_max_retrans", - .data = &nf_ct_tcp_max_retrans, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1290,63 +1301,54 @@ static struct ctl_table tcp_sysctl_tablestatic struct ctl_table tcp_compat_sysctl_table[] = { { .procname ="ip_conntrack_tcp_timeout_syn_sent" , - .data = &tcp_timeouts[TCP_CONNTRACK_SYN_SENT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_syn_recv" , - .data = &tcp_timeouts[TCP_CONNTRACK_SYN_RECV ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_established" , - .data = &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_fin_wait" , - .data = &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_close_wait" , - .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_last_ack" , - .data = &tcp_timeouts[TCP_CONNTRACK_LAST_ACK ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_time_wait" , - .data = &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_close" , - .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_max_retrans" , - .data = &nf_ct_tcp_timeout_max_retrans, .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies,
@@ -1354,7 +1356,6 @@ static struct ctl_table tcp_compat_sysct { .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_LOOSE, .procname = "ip_conntrack_tcp_loose", - .data = &nf_ct_tcp_loose, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1362,7 +1363,6 @@ static struct ctl_table tcp_compat_sysct { .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL, .procname = "ip_conntrack_tcp_be_liberal", - .data = &nf_ct_tcp_be_liberal, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1370,7 +1370,6 @@ static struct ctl_table tcp_compat_sysct { .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS, .procname = "ip_conntrack_tcp_max_retrans", - .data = &nf_ct_tcp_max_retrans, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1401,14 +1400,6 @@ struct nf_conntrack_l4proto nf_conntrack .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &tcp_sysctl_table_users, - .ctl_table_header = &tcp_sysctl_header, - .ctl_table = tcp_sysctl_table, -#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT - .ctl_compat_table = tcp_compat_sysctl_table, -#endif -#endif };EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_tcp4);
@@ -1431,10 +1422,153 @@ struct nf_conntrack_l4proto nf_conntrack .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif +}; +EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_tcp6); + +static __net_init int tcp_net_init (struct net *net) +{ +struct tcp_net *tn; +int err; + + tn =kmalloc (sizeof (*tn),GFP_KERNEL ); +if (!tn) +return -ENOMEM ; + +/* default values */ + tn->tcp_be_liberal =0 ; + tn->tcp_loose =1 ; + tn->tcp_max_retrans =3 ; + + tn->tcp_timeout_max_retrans = 5 MINS; + tn->tcp_timeout_unacknowledged = 5 MINS; + + tn->tcp_timeouts[TCP_CONNTRACK_SYN_SENT] = 2 MINS; + tn->tcp_timeouts[TCP_CONNTRACK_SYN_RECV] = 60 SECS; + tn->tcp_timeouts[TCP_CONNTRACK_ESTABLISHED] = 5 DAYS; + tn->tcp_timeouts[TCP_CONNTRACK_FIN_WAIT] = 2 MINS; + tn->tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT] = 60 SECS; + tn->tcp_timeouts[TCP_CONNTRACK_LAST_ACK] = 30 SECS; + tn->tcp_timeouts[TCP_CONNTRACK_TIME_WAIT] = 2 MINS; + tn->tcp_timeouts[TCP_CONNTRACK_CLOSE] = 10 SECS; + + err =net_assign_generic (net, tcp_net_id, tn); +if (err) + goto out; + +#ifdef CONFIG_SYSCTL + err = -ENOMEM ; + tn->sysctl_table =kmemdup (tcp_sysctl_table, +sizeof (tcp_sysctl_table),GFP_KERNEL ); +if (!tn->sysctl_table) + goto out; + +#define ___PERNET_TO_DAT (i, j) \ + tn->sysctl_table[i].data = &tn->tcp_timeouts[j] + +___PERNET_TO_DAT (0 ,TCP_CONNTRACK_SYN_SENT ); +___PERNET_TO_DAT (1 ,TCP_CONNTRACK_SYN_RECV ); +___PERNET_TO_DAT (2 ,TCP_CONNTRACK_ESTABLISHED ); +___PERNET_TO_DAT (3 ,TCP_CONNTRACK_FIN_WAIT ); +___PERNET_TO_DAT (4 ,TCP_CONNTRACK_CLOSE_WAIT ); +___PERNET_TO_DAT (5 ,TCP_CONNTRACK_LAST_ACK ); +___PERNET_TO_DAT (6 ,TCP_CONNTRACK_TIME_WAIT ); +___PERNET_TO_DAT (7 ,TCP_CONNTRACK_CLOSE ); + +#undef ___PERNET_TO_DAT + + tn->sysctl_table[8 ].data = &tn->tcp_timeout_max_retrans; + tn->sysctl_table[9 ].data = &tn->tcp_timeout_unacknowledged; + tn->sysctl_table[10 ].data = &tn->tcp_loose; + tn->sysctl_table[11 ].data = &tn->tcp_be_liberal; + tn->sysctl_table[12 ].data = &tn->tcp_max_retrans; + + tn->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, tn->sysctl_table); +if (!tn->sysctl_header) + goto out_free; + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + tn->compat_sysctl_table =kmemdup (tcp_compat_sysctl_table, +sizeof (tcp_compat_sysctl_table),GFP_KERNEL ); +if (!tn->compat_sysctl_table) + goto out_sysctl; + +#define ___PERNET_TO_DAT (i, j) \ + tn->compat_sysctl_table[i].data = &tn->tcp_timeouts[j] + +___PERNET_TO_DAT (0 ,TCP_CONNTRACK_SYN_SENT ); +___PERNET_TO_DAT (1 ,TCP_CONNTRACK_SYN_RECV ); +___PERNET_TO_DAT (2 ,TCP_CONNTRACK_ESTABLISHED ); +___PERNET_TO_DAT (3 ,TCP_CONNTRACK_FIN_WAIT ); +___PERNET_TO_DAT (4 ,TCP_CONNTRACK_CLOSE_WAIT ); +___PERNET_TO_DAT (5 ,TCP_CONNTRACK_LAST_ACK ); +___PERNET_TO_DAT (6 ,TCP_CONNTRACK_TIME_WAIT ); +___PERNET_TO_DAT (7 ,TCP_CONNTRACK_CLOSE ); + +#undef ___PERNET_TO_DAT + + tn->compat_sysctl_table[8 ].data = &tn->tcp_timeout_max_retrans; + tn->compat_sysctl_table[9 ].data = &tn->tcp_loose; + tn->compat_sysctl_table[10 ].data = &tn->tcp_be_liberal; + tn->compat_sysctl_table[11 ].data = &tn->tcp_max_retrans; + + tn->compat_sysctl_header =register_net_sysctl_table (net, + nf_net_ipv4_netfilter_sysctl_path, + tn->compat_sysctl_table); +if (!tn->compat_sysctl_header) + goto out_free_compat; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ +#endif /* CONFIG_SYSCTL */ + +return 0 ; + +#ifdef CONFIG_SYSCTL +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +out_free_compat: +kfree (tn->compat_sysctl_table); +#endif +out_sysctl: +unregister_net_sysctl_table (tn->sysctl_header); +out_free: +kfree (tn->sysctl_table); +#endif + +out: +kfree (tn); +return err; +} + +static __net_exit void tcp_net_exit(struct net *net) +{ +struct tcp_net *tn =tcp_pernet (net);#ifdef CONFIG_SYSCTL - .ctl_table_users = &tcp_sysctl_table_users, - .ctl_table_header = &tcp_sysctl_header, - .ctl_table = tcp_sysctl_table, +unregister_net_sysctl_table (tn->sysctl_header); +kfree (tn->sysctl_table); +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +unregister_net_sysctl_table (tn->compat_sysctl_header); +kfree (tn->compat_sysctl_table);#endif +#endif +kfree (tn); + +net_assign_generic (net, tcp_net_id,NULL ); }; -EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_tcp6); + +static struct pernet_operations tcp_net_ops = { + .init = tcp_net_init, + .exit = tcp_net_exit, +}; + +static int __init nf_ct_tcp_proto_init (void ) +{ +return register_pernet_gen_subsys (&tcp_net_id, &tcp_net_ops); +} + +static void __exit nf_ct_tcp_proto_fini(void) +{ +unregister_pernet_gen_subsys (tcp_net_id, &tcp_net_ops); +} + +module_init (nf_ct_tcp_proto_init); +module_exit (nf_ct_tcp_proto_fini); +MODULE_LICENSE ("GPL" );
RFC v2 6/7 net: netfilter conntrack - add per-net functionality for UDP protocol
In reply to Cyrill GorcunovModule specific data moved into per-net site and being allocated/freed during net namespace creation/deletion. For this reason module_init/exit calls added.
--- net/netfilter/nf_conntrack_proto_udp.c | 152 ++++++++++++++++++++++++++++----- 1 file changed, 130 insertions(+), 22 deletions(-)
net/netfilter/nf_conntrack_proto_udp.c +130 -22
@@ -16,6 +16,9 @@#include <net/ip6_checksum.h> #include <net/checksum.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> +#include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv6.h>
@@ -23,8 +26,25 @@#include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_log.h> -static unsigned int nf_ct_udp_timeout__read_mostly =30 *HZ ; -static unsigned int nf_ct_udp_timeout_stream__read_mostly =180 *HZ ; +/* per-net specifics */ +static int udp_net_id; +struct udp_net { +unsigned int udp_timeout; +unsigned int udp_timeout_stream; +#ifdef CONFIG_SYSCTL +struct ctl_table_header *sysctl_header; +struct ctl_table *sysctl_table; +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +struct ctl_table_header *compat_sysctl_header; +struct ctl_table *compat_sysctl_table; +#endif +#endif +}; + +static inline struct udp_net *udp_pernet (struct net *net) +{ +return net_generic (net, udp_net_id); +} static bool udp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
@@ -69,15 +89,17 @@ static int udp_packet(struct nf_conn *ct u_int8_t pf, unsigned int hooknum) { +struct udp_net *un =udp_pernet (nf_ct_net (ct)); +/* If we've seen traffic both ways, this is some kind of UDP stream. Extend timeout. */ if (test_bit (IPS_SEEN_REPLY_BIT , &ct->status)) { -nf_ct_refresh_acct (ct, ctinfo, skb, nf_ct_udp_timeout_stream); +nf_ct_refresh_acct (ct, ctinfo, skb, un->udp_timeout_stream);/* Also, more likely to be important, and not a probe */ if (!test_and_set_bit (IPS_ASSURED_BIT , &ct->status))nf_conntrack_event_cache (IPCT_STATUS , ct); }else -nf_ct_refresh_acct (ct, ctinfo, skb, nf_ct_udp_timeout); +nf_ct_refresh_acct (ct, ctinfo, skb, un->udp_timeout);return NF_ACCEPT ; }
@@ -135,19 +157,16 @@ static int udp_error(struct net *net, st } #ifdef CONFIG_SYSCTL -static unsigned int udp_sysctl_table_users; -static struct ctl_table_header *udp_sysctl_header; +/* templates, data assigned later */ static struct ctl_table udp_sysctl_table[] = { { .procname = "nf_conntrack_udp_timeout", - .data = &nf_ct_udp_timeout, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_udp_timeout_stream", - .data = &nf_ct_udp_timeout_stream, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -160,14 +179,12 @@ static struct ctl_table udp_sysctl_tablestatic struct ctl_table udp_compat_sysctl_table[] = { { .procname ="ip_conntrack_udp_timeout" , - .data = &nf_ct_udp_timeout, .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_udp_timeout_stream" , - .data = &nf_ct_udp_timeout_stream, .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies,
@@ -195,14 +212,7 @@ struct nf_conntrack_l4proto nf_conntrack .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy, #endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &udp_sysctl_table_users, - .ctl_table_header = &udp_sysctl_header, - .ctl_table = udp_sysctl_table, -#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT - .ctl_compat_table = udp_compat_sysctl_table, -#endif -#endif + .me =THIS_MODULE , };EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_udp4);
@@ -222,10 +232,108 @@ struct nf_conntrack_l4proto nf_conntrack .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy, #endif + .me =THIS_MODULE , +}; +EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_udp6); + +static __net_init int udp_net_init (struct net *net) +{ +struct udp_net *un; +int err; + + un =kmalloc (sizeof (*un),GFP_KERNEL ); +if (!un) +return -ENOMEM ; + +/* default values */ + un->udp_timeout =30 *HZ ; + un->udp_timeout_stream =180 *HZ ; + + err =net_assign_generic (net, udp_net_id, un); +if (err) + goto out; + +#ifdef CONFIG_SYSCTL + err = -ENOMEM ; + un->sysctl_table =kmemdup (udp_sysctl_table, +sizeof (udp_sysctl_table),GFP_KERNEL ); +if (!un->sysctl_table) + goto out; + + un->sysctl_table[0 ].data = &un->udp_timeout; + un->sysctl_table[1 ].data = &un->udp_timeout_stream; + + un->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, un->sysctl_table); +if (!un->sysctl_header) + goto out_free; + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + un->compat_sysctl_table =kmemdup (udp_compat_sysctl_table, +sizeof (udp_compat_sysctl_table),GFP_KERNEL ); +if (!un->compat_sysctl_table) + goto out_sysctl; + + un->compat_sysctl_table[0 ].data = &un->udp_timeout; + un->compat_sysctl_table[1 ].data = &un->udp_timeout_stream; + + un->compat_sysctl_header =register_net_sysctl_table (net, + nf_net_ipv4_netfilter_sysctl_path, + un->compat_sysctl_table); +if (!un->compat_sysctl_header) + goto out_free_compat; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ +#endif /* CONFIG_SYSCTL */ + +return 0 ; + +#ifdef CONFIG_SYSCTL +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +out_free_compat: +kfree (un->compat_sysctl_table); +#endif +out_sysctl: +unregister_net_sysctl_table (un->sysctl_header); +out_free: +kfree (un->sysctl_table); +#endif + +out: +kfree (un); +return err; +} + +static __net_exit void udp_net_exit(struct net *net) +{ +struct udp_net *un =udp_pernet (net);#ifdef CONFIG_SYSCTL - .ctl_table_users = &udp_sysctl_table_users, - .ctl_table_header = &udp_sysctl_header, - .ctl_table = udp_sysctl_table, +unregister_net_sysctl_table (un->sysctl_header); +kfree (un->sysctl_table); +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +unregister_net_sysctl_table (un->compat_sysctl_header); +kfree (un->compat_sysctl_table);#endif +#endif +kfree (un); + +net_assign_generic (net, udp_net_id,NULL ); +} + +static struct pernet_operations udp_net_ops = { + .init = udp_net_init, + .exit = udp_net_exit, }; -EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_udp6); + +int __init nf_ct_udp_proto_init (void ) +{ +return register_pernet_gen_subsys (&udp_net_id, &udp_net_ops); +} + +void __exit nf_ct_udp_proto_fini(void) +{ +unregister_pernet_gen_subsys (udp_net_id, &udp_net_ops); +} + +module_init (nf_ct_udp_proto_init); +module_exit (nf_ct_udp_proto_fini); +MODULE_LICENSE ("GPL" );
RFC v2 7/7 net: netfilter conntrack - add per-net functionality for ICMP protocol
In reply to Cyrill GorcunovModule specific data moved into per-net site and being allocated/freed during net namespace creation/deletion. For this reason module_init/exit calls added.
--- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 128 +++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 8 deletions(-)
net/ipv4/netfilter/nf_conntrack_proto_icmp.c +120 -8
@@ -9,6 +9,7 @@#include <linux/types.h> #include <linux/timer.h> #include <linux/netfilter.h> +#include <linux/module.h> #include <linux/in.h> #include <linux/icmp.h> #include <linux/seq_file.h>
@@ -20,7 +21,27 @@#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_log.h> -static unsigned int nf_ct_icmp_timeout__read_mostly =30 *HZ ; +#include <net/net_namespace.h> +#include <net/netns/generic.h> + +/* per-net specifics */ +static int icmp_net_id; +struct icmp_net { +unsigned int icmp_timeout; +#ifdef CONFIG_SYSCTL +struct ctl_table_header *sysctl_header; +struct ctl_table *sysctl_table; +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +struct ctl_table_header *compat_sysctl_header; +struct ctl_table *compat_sysctl_table; +#endif +#endif +}; + +static inline struct icmp_net *icmp_pernet (struct net *net) +{ +return net_generic (net, icmp_net_id); +}static bool icmp_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff,struct nf_conntrack_tuple *tuple)
@@ -90,9 +111,10 @@ static int icmp_packet(struct nf_conn *cif (atomic_dec_and_test (&ct->proto.icmp.count))nf_ct_kill_acct (ct, ctinfo, skb); }else { +struct icmp_net *in =icmp_pernet (nf_ct_net (ct));atomic_inc (&ct->proto.icmp.count);nf_conntrack_event_cache (IPCT_PROTOINFO_VOLATILE , ct); -nf_ct_refresh_acct (ct, ctinfo, skb, nf_ct_icmp_timeout); +nf_ct_refresh_acct (ct, ctinfo, skb, in->icmp_timeout); }return NF_ACCEPT ;
@@ -265,11 +287,10 @@ static int icmp_nlattr_to_tuple(struct n#endif #ifdef CONFIG_SYSCTL -static struct ctl_table_header *icmp_sysctl_header; +/* templates, data assigned later */ static struct ctl_table icmp_sysctl_table[] = { { .procname = "nf_conntrack_icmp_timeout", - .data = &nf_ct_icmp_timeout, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -282,7 +303,6 @@ static struct ctl_table icmp_sysctl_tablstatic struct ctl_table icmp_compat_sysctl_table[] = { { .procname ="ip_conntrack_icmp_timeout" , - .data = &nf_ct_icmp_timeout, .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies,
@@ -312,11 +332,103 @@ struct nf_conntrack_l4proto nf_conntrack .nlattr_to_tuple = icmp_nlattr_to_tuple, .nla_policy = icmp_nla_policy,#endif +}; + +static __net_init int icmp_net_init (struct net *net) +{ +struct icmp_net *in; +int err; + + in =kmalloc (sizeof (*in),GFP_KERNEL ); +if (!in) +return -ENOMEM ; + +/* default values */ + in->icmp_timeout =30 *HZ ; + + err =net_assign_generic (net, icmp_net_id, in); +if (err) + goto out; + +#ifdef CONFIG_SYSCTL + err = -ENOMEM ; + in->sysctl_table =kmemdup (icmp_sysctl_table, +sizeof (icmp_sysctl_table),GFP_KERNEL ); +if (!in->sysctl_table) + goto out; + + in->sysctl_table[0 ].data = &in->icmp_timeout; + + in->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, in->sysctl_table); +if (!in->sysctl_header) + goto out_free; + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + in->compat_sysctl_table =kmemdup (icmp_compat_sysctl_table, +sizeof (icmp_compat_sysctl_table),GFP_KERNEL ); +if (!in->compat_sysctl_table) + goto out_sysctl; + + in->compat_sysctl_table[0 ].data = &in->icmp_timeout; + + in->compat_sysctl_header =register_net_sysctl_table (net, + nf_net_ipv4_netfilter_sysctl_path, + in->compat_sysctl_table); +if (!in->compat_sysctl_header) + goto out_free_compat; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ +#endif /* CONFIG_SYSCTL */ + +return 0 ; + +#ifdef CONFIG_SYSCTL +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +out_free_compat: +kfree (in->compat_sysctl_table); +#endif +out_sysctl: +unregister_net_sysctl_table (in->sysctl_header); +out_free: +kfree (in->sysctl_table); +#endif + +out: +kfree (in); +return err; +} + +static __net_exit void icmp_net_exit(struct net *net) +{ +struct icmp_net *in =icmp_pernet (net);#ifdef CONFIG_SYSCTL - .ctl_table_header = &icmp_sysctl_header, - .ctl_table = icmp_sysctl_table, +unregister_net_sysctl_table (in->sysctl_header); +kfree (in->sysctl_table);#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT - .ctl_compat_table = icmp_compat_sysctl_table, +unregister_net_sysctl_table (in->compat_sysctl_header); +kfree (in->compat_sysctl_table);#endif #endif +kfree (in); + +net_assign_generic (net, icmp_net_id,NULL ); +} + +static struct pernet_operations icmp_net_ops = { + .init = icmp_net_init, + .exit = icmp_net_exit, }; + +int __init nf_ct_icmp_proto_init (void ) +{ +return register_pernet_gen_subsys (&icmp_net_id, &icmp_net_ops); +} + +void __exit nf_ct_icmp_proto_fini(void) +{ +unregister_pernet_gen_subsys (icmp_net_id, &icmp_net_ops); +} + +module_init (nf_ct_icmp_proto_init); +module_exit (nf_ct_icmp_proto_fini); +MODULE_LICENSE ("GPL" );
Re: [RFC v2 1/7] net: sysctl_net - use net_eq to compare nets
In reply to Cyrill GorcunovQuoted 4 lines · Cyrill Gorcunov
Signed-off-by Cyrill Gorcunov <[email protected]>---
Re: [RFC v2 2/7] net: netfilter conntrack - add per-net functionality for DCCP protocol
In reply to Cyrill GorcunovQuoted 6 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
Signed-off-by Cyrill Gorcunov <[email protected]>---
Re: [RFC v2 3/7] net: netfilter conntrack - add per-net functionality for SCTP protocol
In reply to Cyrill GorcunovQuoted 6 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
Signed-off-by Cyrill Gorcunov <[email protected]>---
Re: [RFC v2 4/7] net: netfilter conntrack - add per-net functionality for UDPLITE protocol
In reply to Cyrill GorcunovQuoted 6 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
Signed-off-by Cyrill Gorcunov <[email protected]>---
Re: [RFC v2 5/7] net: netfilter conntrack - add per-net functionality for TCP protocol
In reply to Cyrill GorcunovQuoted 7 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion. For this reason module_init/exit calls added.
Signed-off-by Cyrill Gorcunov <[email protected]>---
Re: [RFC v2 6/7] net: netfilter conntrack - add per-net functionality for UDP protocol
In reply to Cyrill GorcunovQuoted 7 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion. For this reason module_init/exit calls added.
Signed-off-by Cyrill Gorcunov <[email protected]>---
Re: [RFC v2 7/7] net: netfilter conntrack - add per-net functionality for ICMP protocol
In reply to Cyrill GorcunovQuoted 7 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion. For this reason module_init/exit calls added.
Signed-off-by Cyrill Gorcunov <[email protected]>---
Patrick McHardy
AppliedRe: [RFC v2 1/7] net: sysctl_net - use net_eq to compare nets
In reply to Daniel LezcanoQuoted 6 lines · Daniel Lezcano
Quoted 4 lines · Cyrill Gorcunov
Signed-off-by Cyrill Gorcunov <[email protected]>---
Acked-by Daniel Lezcano <[email protected]>
Applied, thanks.
Patrick McHardy
AppliedRe: [RFC v2 2/7] net: netfilter conntrack - add per-net functionality for DCCP protocol
In reply to Daniel LezcanoQuoted 8 lines · Daniel Lezcano
Quoted 6 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
Signed-off-by Cyrill Gorcunov <[email protected]>---
Acked-by Daniel Lezcano <[email protected]>
Applied, thanks.
Re: [RFC v2 3/7] net: netfilter conntrack - add per-net functionality for SCTP protocol
In reply to Cyrill GorcunovQuoted 29 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
net/netfilter/nf_conntrack_proto_sctp.c +26
-0+#define ___PERNET_TO_DAT (i, j) \ + sn->sysctl_table[i].data = &sn->sctp_timeouts[j] + +___PERNET_TO_DAT (0 ,SCTP_CONNTRACK_CLOSED ); +___PERNET_TO_DAT (1 ,SCTP_CONNTRACK_COOKIE_WAIT ); +___PERNET_TO_DAT (2 ,SCTP_CONNTRACK_COOKIE_ECHOED ); +___PERNET_TO_DAT (3 ,SCTP_CONNTRACK_ESTABLISHED ); +___PERNET_TO_DAT (4 ,SCTP_CONNTRACK_SHUTDOWN_SENT ); +___PERNET_TO_DAT (5 ,SCTP_CONNTRACK_SHUTDOWN_RECD ); +___PERNET_TO_DAT (6 ,SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ); + +#undef ___PERNET_TO_DAT + + sn->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, sn->sysctl_table); +if (!sn->sysctl_header) + goto out_free; + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + sn->compat_sysctl_table =kmemdup (sctp_compat_sysctl_table, +sizeof (sctp_compat_sysctl_table),GFP_KERNEL ); +if (!sn->compat_sysctl_table) + goto out_sysctl; + +#define ___PERNET_TO_DAT (i, j) \ + sn->compat_sysctl_table[i].data = &sn->sctp_timeouts[j]
net/netfilter/nf_conntrack_proto_sctp.c static struct nf_conntrack_l4proto nf_co · line 761
Quoted 10 lines
net/netfilter/nf_conntrack_proto_sctp.c +10
-0+ +___PERNET_TO_DAT (0 ,SCTP_CONNTRACK_CLOSED ); +___PERNET_TO_DAT (1 ,SCTP_CONNTRACK_COOKIE_WAIT ); +___PERNET_TO_DAT (2 ,SCTP_CONNTRACK_COOKIE_ECHOED ); +___PERNET_TO_DAT (3 ,SCTP_CONNTRACK_ESTABLISHED ); +___PERNET_TO_DAT (4 ,SCTP_CONNTRACK_SHUTDOWN_SENT ); +___PERNET_TO_DAT (5 ,SCTP_CONNTRACK_SHUTDOWN_RECD ); +___PERNET_TO_DAT (6 ,SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ); + +#undef ___PERNET_TO_DAT
This is really ugly and is somewhat risky since those magic offsets need to be kept in sync. Any chance (I don't have a suggestion currently) to do this in a nicer way?
Re: [RFC v2 3/7] net: netfilter conntrack - add per-net functionality for SCTP protocol
[Patrick McHardy - Mon, Mar 16, 2009 at 04:35:11PM +0100]
...
Quoted 17 lines
+#define
___PERNET_TO_DAT(i, j)\net/netfilter/nf_conntrack_proto_sctp.c static struct nf_conntrack_l4proto nf_co · line 761
Quoted 11 lines
net/netfilter/nf_conntrack_proto_sctp.c +11
-0+ sn->compat_sysctl_table[i].data = &sn->sctp_timeouts[j] + +___PERNET_TO_DAT (0 ,SCTP_CONNTRACK_CLOSED ); +___PERNET_TO_DAT (1 ,SCTP_CONNTRACK_COOKIE_WAIT ); +___PERNET_TO_DAT (2 ,SCTP_CONNTRACK_COOKIE_ECHOED ); +___PERNET_TO_DAT (3 ,SCTP_CONNTRACK_ESTABLISHED ); +___PERNET_TO_DAT (4 ,SCTP_CONNTRACK_SHUTDOWN_SENT ); +___PERNET_TO_DAT (5 ,SCTP_CONNTRACK_SHUTDOWN_RECD ); +___PERNET_TO_DAT (6 ,SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ); + +#undef ___PERNET_TO_DATThis is really ugly and is somewhat risky since those magic offsets need to be kept in sync. Any chance (I don't have a suggestion currently) to do this in a nicer way?
Give me some time Patrick, will try. Actually initial idea of these macros was to eliminate 'possible' problems caused by for (;;) form (enum could be rearranged and we will fail silently). So I guess the some 'new' form of template would help (instead of current "ctrl table as a templae"). So will return with new proposal. Thanks for review!
- Cyrill -
Re: [RFC v2 3/7] net: netfilter conntrack - add per-net functionality for SCTP protocol
Quoted 19 lines · Cyrill Gorcunov
[Patrick McHardy - Mon, Mar 16, 2009 at 04:35:11PM +0100]
...Quoted 16 lines
+#define
___PERNET_TO_DAT(i, j)\net/netfilter/nf_conntrack_proto_sctp.c static struct nf_conntrack_l4proto nf_co · line 761
Quoted 11 lines
net/netfilter/nf_conntrack_proto_sctp.c +11
-0+ sn->compat_sysctl_table[i].data = &sn->sctp_timeouts[j] + +___PERNET_TO_DAT (0 ,SCTP_CONNTRACK_CLOSED ); +___PERNET_TO_DAT (1 ,SCTP_CONNTRACK_COOKIE_WAIT ); +___PERNET_TO_DAT (2 ,SCTP_CONNTRACK_COOKIE_ECHOED ); +___PERNET_TO_DAT (3 ,SCTP_CONNTRACK_ESTABLISHED ); +___PERNET_TO_DAT (4 ,SCTP_CONNTRACK_SHUTDOWN_SENT ); +___PERNET_TO_DAT (5 ,SCTP_CONNTRACK_SHUTDOWN_RECD ); +___PERNET_TO_DAT (6 ,SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ); + +#undef ___PERNET_TO_DATThis is really ugly and is somewhat risky since those magic offsets need to be kept in sync. Any chance (I don't have a suggestion currently) to do this in a nicer way?
Quoted 4 lines
Give me some time Patrick, will try. Actually initial idea of these macros was to eliminate 'possible' problems caused by for (;;) form (enum could be rearranged and we will fail silently).
The state enums are pretty much set in stone as they're part of the userspace ABI.
Quoted 3 lines
So I guess the some 'new' form of template would help (instead of current "ctrl table as a templae"). So will return with new proposal. Thanks for review!
Thanks.
Re: [RFC v2 3/7] net: netfilter conntrack - add per-net functionality for SCTP protocol
[Patrick McHardy - Mon, Mar 16, 2009 at 04:48:28PM +0100]
...
Quoted 6 lines
Quoted 5 lines
Give me some time Patrick, will try. Actually initial idea of these macros was to eliminate 'possible' problems caused by for (;;) form (enum could be rearranged and we will fail silently).
Quoted 9 lines
The state enums are pretty much set in stone as they're part of the userspace ABI.
Quoted 3 lines
So I guess the some 'new' form of template would help (instead of current "ctrl table as a templae"). So will return with new proposal. Thanks for review!
Thanks.
After playing a bit with ctrl tables (thought about additional mapping set or say new sysctl helper structure, or even using extra1 member from struct ctl_table as temporary index) -- you were right in your first propose on this patch. Iterative fasion is only more or less convenient here indeed :)
Patrick, take a look please on the snippet below (that is how it looks now).
...
+static __net_init int sctp_net_init(struct net *net) +{
+ struct sctp_net *sn;
+ int err;
+
+ sn = kmalloc(sizeof(*sn), GFP_KERNEL);
+ if (!sn)
+ return -ENOMEM;
+
+ /* default values */
+ sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED] = 10 SECS;
+ sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS;
+ sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS;
+ sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS;
+ sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000;
+ sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000;
+ sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS;
+
+ err = net_assign_generic(net, sctp_net_id, sn);
+ if (err)
+ goto out;
+
+ /*
+ * Pin per-net data to sysctl tables
+ *
+ * We allocate new ctrl tables from predefined templates
+ * and then assign .data fields iteratively, we allowed
+ * to do so since SCTP_CONNTRACK_... enum is a part of
+ * userspace ABI and it's hardly that the enum entries
+ * will be rearranged
+ */
+
#ifdef CONFIG_SYSCTL
- .ctl_table_users = &sctp_sysctl_table_users,
- .ctl_table_header = &sctp_sysctl_header,
- .ctl_table = sctp_sysctl_table,
+ {
+ int i;
+ err = -ENOMEM;
+ sn->sysctl_table = kmemdup(sctp_sysctl_table,
+ sizeof(sctp_sysctl_table), GFP_KERNEL);
+ if (!sn->sysctl_table)
+ goto out;
+
+ for (i = SCTP_CONNTRACK_CLOSED; i < SCTP_CONNTRACK_MAX; i++)
+ sn->sysctl_table[i - 1].data = &sn->sctp_timeouts[i];
+
+ sn->sysctl_header = register_net_sysctl_table(net,
+ nf_net_netfilter_sysctl_path, sn->sysctl_table);
+ if (!sn->sysctl_header)
+ goto out_free;
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ sn->compat_sysctl_table = kmemdup(sctp_compat_sysctl_table,
+ sizeof(sctp_compat_sysctl_table), GFP_KERNEL);
+ if (!sn->compat_sysctl_table)
+ goto out_sysctl;
+
+ for (i = SCTP_CONNTRACK_CLOSED; i < SCTP_CONNTRACK_MAX; i++)
+ sn->compat_sysctl_table[err - 1].data = &sn->sctp_timeouts[i];
+
+ sn->compat_sysctl_header = register_net_sysctl_table(net,
+ nf_net_ipv4_netfilter_sysctl_path, sn->compat_sysctl_table);
+ if (!sn->compat_sysctl_header)
+ goto out_free_compat;
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+ }
+#endif /* CONFIG_SYSCTL */
+
+ return 0;
+
+#ifdef CONFIG_SYSCTL
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +out_free_compat:
+ kfree(sn->compat_sysctl_table);
+#endif
+out_sysctl:
+ unregister_net_sysctl_table(sn->sysctl_header);
+out_free:
+ kfree(sn->sysctl_table);
+#endif
+
+out:
+ kfree(sn);
+ return err;
+}
...
If such an approach is fine -- I will fix the TCP proto as well. Btw, this two patches (SCTP and TCP) are only involved in such a modification, are there some problems with patches for UDP, UDPlite and ICMP protos?
- Cyrill -
Re: [RFC v2 3/7] net: netfilter conntrack - add per-net functionality for SCTP protocol
Review
Quoted 11 lines · Cyrill Gorcunov
After playing a bit with ctrl tables (thought about additional
mapping set or say new sysctl helper structure, or even using
extra1 member from structctl_tableas temporary index) -- you were right in your first propose on this patch. Iterative fasion is only more or less convenient here indeed :)Patrick, take a look please on the snippet below (that is how it looks now).
...(quoted diff) +2
-0+ for (i = SCTP_CONNTRACK_CLOSED; i < SCTP_CONNTRACK_MAX; i++) + sn->sysctl_table[i - 1].data = &sn->sctp_timeouts[i];
That definitely looks nicer. Does this work (-1) for the other protocols as well?
Quoted 4 lines
If such an approach is fine -- I will fix the TCP proto as well. Btw, this two patches (SCTP and TCP) are only involved in such a modification, are there some problems with patches for UDP, UDPlite and ICMP protos?
Its better than the macro and I don't really see a better way, so this is fine with me. About the other patches - I just stopped at SCTP since it was the first one I truely didn't like :)
Re: [RFC v2 3/7] net: netfilter conntrack - add per-net functionality for SCTP protocol
[Patrick McHardy - Mon, Mar 16, 2009 at 07:29:02PM +0100]
Quoted 11 lines
Quoted 9 lines · Cyrill Gorcunov
After playing a bit with ctrl tables (thought about additional mapping set or say new sysctl helper structure, or even using extra1 member from struct
ctl_tableas temporary index) -- you were right in your first propose on this patch. Iterative fasion is only more or less convenient here indeed :)Patrick, take a look please on the snippet below (that is how it looks now).
...
Quoted 5 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ for (i = SCTP_CONNTRACK_CLOSED; i < SCTP_CONNTRACK_MAX; i++) + sn->sysctl_table[i - 1].data = &sn->sctp_timeouts[i];That definitely looks nicer. Does this work (-1) for the other protocols as well?
Yes, it's allowable for TCP_CONNTRACK_ to use the same way referring just fine, though we use only a subset of the enum for sysctl table.
Quoted 10 lines
Quoted 5 lines
If such an approach is fine -- I will fix the TCP proto as well. Btw, this two patches (SCTP and TCP) are only involved in such a modification, are there some problems with patches for UDP, UDPlite and ICMP protos?
Its better than the macro and I don't really see a better way, so this is fine with me. About the other patches - I just stopped at SCTP since it was the first one I truely didn't like :)
Ah :) Then I update only these two patches (SCTP and TCP protos) since other are not related in this. Or I could resend the whole series excluding the patches you've already picked up. Just say what would be more convenient for you.
- Cyrill -
Re: [RFC v2 5/7] net: netfilter conntrack - add per-net functionality for TCP protocol
In reply to Cyrill GorcunovHere is an updated version which uses iterative assignment of sysctl data. Please review.
---
From: Cyrill Gorcunov <[email protected]>
Subject: [RFC v2 5/7] net: netfilter conntrack - add per-net functionality for TCP protocol
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion. For this reason module_init/exit calls added.
--- net/netfilter/nf_conntrack_proto_tcp.c | 281 +++++++++++++++++++++++---------- 1 file changed, 203 insertions(+), 78 deletions(-)
net/netfilter/nf_conntrack_proto_tcp.c +203 -78
@@ -18,6 +18,9 @@#include <net/tcp.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> +#include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv6.h>
@@ -29,20 +32,6 @@/* Protects ct->proto.tcp */ static DEFINE_RWLOCK (tcp_lock); -/* "Be conservative in what you do, -be liberal in what you accept from others." -If it's non-zero, we mark only out of window RST segments as INVALID. */ -static int nf_ct_tcp_be_liberal__read_mostly =0 ; - -/* If it is set to zero, we disable picking up already established -connections. */ -static int nf_ct_tcp_loose__read_mostly =1 ; - -/* Max number of the retransmitted packets without receiving an (acceptable) -ACK from the destination. If this number is reached, a shorter timer -will be started. */ -static int nf_ct_tcp_max_retrans__read_mostly =3 ; -/* FIXME: Examine ipfilter's timeouts and conntrack transitions more closely. They're more complex. --RR */
@@ -64,23 +53,6 @@ static const char *const tcp_conntrack_n#define HOURS * 60 MINS#define DAYS * 24 HOURS -/* RFC1122 says the R2 limit should be at least 100 seconds. -Linux uses 15 packets as limit, which corresponds -to ~13-30min depending on RTO. */ -static unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS; -static unsigned int nf_ct_tcp_timeout_unacknowledged __read_mostly = 5 MINS; - -static unsigned int tcp_timeouts[TCP_CONNTRACK_MAX ]__read_mostly = { - [TCP_CONNTRACK_SYN_SENT] = 2 MINS, - [TCP_CONNTRACK_SYN_RECV] = 60 SECS, - [TCP_CONNTRACK_ESTABLISHED] = 5 DAYS, - [TCP_CONNTRACK_FIN_WAIT] = 2 MINS, - [TCP_CONNTRACK_CLOSE_WAIT] = 60 SECS, - [TCP_CONNTRACK_LAST_ACK] = 30 SECS, - [TCP_CONNTRACK_TIME_WAIT] = 2 MINS, - [TCP_CONNTRACK_CLOSE] = 10 SECS, -}; -#define sNO TCP_CONNTRACK_NONE#define sSS TCP_CONNTRACK_SYN_SENT#define sSR TCP_CONNTRACK_SYN_RECV
@@ -258,6 +230,51 @@ static const u8 tcp_conntracks[2][6][TCP } }; +/* per-net specifics */ +static int tcp_net_id; +struct tcp_net { +/* +* "Be conservative in what you do, +* be liberal in what you accept from others." +* If it's non-zero, we mark only out of window +* RST segments as INVALID. +*/ +int tcp_be_liberal; +/* +* If it is set to zero, we disable picking up +* already established connections. +*/ +int tcp_loose; +/* +* Max number of the retransmitted packets without +* receiving an (acceptable) ACK from the destination. +* If this number is reached, a shorter timer will be started. +*/ +int tcp_max_retrans; +/* +* RFC1122 says the R2 limit should be at least 100 seconds. +* Linux uses 15 packets as limit, which corresponds +* to ~13-30min depending on RTO. +*/ +unsigned int tcp_timeout_max_retrans; +unsigned int tcp_timeout_unacknowledged; + +unsigned int tcp_timeouts[TCP_CONNTRACK_MAX ]; +#ifdef CONFIG_SYSCTL +struct ctl_table_header *sysctl_header; +struct ctl_table *sysctl_table; +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +struct ctl_table_header *compat_sysctl_header; +struct ctl_table *compat_sysctl_table; +#endif +#endif +}; + +static inline struct tcp_net *tcp_pernet (struct net *net) +{ +return net_generic (net, tcp_net_id); +} +static bool tcp_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff,struct nf_conntrack_tuple *tuple) {
@@ -489,6 +506,7 @@ static bool tcp_in_window(const struct n u_int8_t pf) {struct net *net =nf_ct_net (ct); +struct tcp_net *tn;struct ip_ct_tcp_state *sender = &state->seen[dir];struct ip_ct_tcp_state *receiver = &state->seen[!dir];const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
@@ -666,8 +684,9 @@ static bool tcp_in_window(const struct n res = true; }else { res = false; + tn =tcp_pernet (net);if (sender->flags &IP_CT_TCP_FLAG_BE_LIBERAL || - nf_ct_tcp_be_liberal) + tn->tcp_be_liberal) res = true;if (!res &&LOG_INVALID (net,IPPROTO_TCP )) nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
@@ -810,6 +829,7 @@ static int tcp_packet(struct nf_conn *ct unsigned int hooknum) {struct net *net =nf_ct_net (ct); +struct tcp_net *tn;struct nf_conntrack_tuple *tuple;enum tcp_conntrack new_state, old_state;enum ip_conntrack_dir dir;
@@ -948,6 +968,8 @@ static int tcp_packet(struct nf_conn *ct ct->proto.tcp.last_index = index; ct->proto.tcp.last_dir = dir; + tn =tcp_pernet (net); +pr_debug ("tcp_conntracks: " );nf_ct_dump_tuple (tuple); pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
@@ -960,15 +982,15 @@ static int tcp_packet(struct nf_conn *ct && new_state == TCP_CONNTRACK_FIN_WAIT) ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; -if (ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans && - tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans) - timeout = nf_ct_tcp_timeout_max_retrans; +if (ct->proto.tcp.retrans >= tn->tcp_max_retrans && + tn->tcp_timeouts[new_state] > tn->tcp_timeout_max_retrans) + timeout = tn->tcp_timeout_max_retrans;else if ((ct->proto.tcp.seen[0 ].flags | ct->proto.tcp.seen[1 ].flags) &IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED && - tcp_timeouts[new_state] > nf_ct_tcp_timeout_unacknowledged) - timeout = nf_ct_tcp_timeout_unacknowledged; + tn->tcp_timeouts[new_state] > tn->tcp_timeout_unacknowledged) + timeout = tn->tcp_timeout_unacknowledged;else - timeout = tcp_timeouts[new_state]; + timeout = tn->tcp_timeouts[new_state];write_unlock_bh (&tcp_lock);nf_conntrack_event_cache (IPCT_PROTOINFO_VOLATILE , ct);
@@ -1005,6 +1027,7 @@ static bool tcp_new(struct nf_conn *ct, {enum tcp_conntrack new_state;const struct tcphdr *th; +struct tcp_net *tn;struct tcphdr _tcph;const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[0 ];const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[1 ];
@@ -1023,6 +1046,8 @@ static bool tcp_new(struct nf_conn *ct,return false; } + tn =tcp_pernet (nf_ct_net (ct)); +if (new_state ==TCP_CONNTRACK_SYN_SENT ) {/* SYN packet */ ct->proto.tcp.seen[0].td_end =
@@ -1036,7 +1061,7 @@ static bool tcp_new(struct nf_conn *ct,tcp_options (skb, dataoff, th, &ct->proto.tcp.seen[0 ]); ct->proto.tcp.seen[1 ].flags =0 ; - }else if (nf_ct_tcp_loose ==0 ) { + }else if (tn->tcp_loose ==0 ) {/* Don't try to pick up connections. */ return false; }else {
@@ -1184,75 +1209,64 @@ static int nlattr_to_tcp(struct nlattr *#endif #ifdef CONFIG_SYSCTL -static unsigned int tcp_sysctl_table_users; -static struct ctl_table_header *tcp_sysctl_header; +/* templates, data assigned later */ static struct ctl_table tcp_sysctl_table[] = { { .procname = "nf_conntrack_tcp_timeout_syn_sent", - .data = &tcp_timeouts[TCP_CONNTRACK_SYN_SENT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_syn_recv", - .data = &tcp_timeouts[TCP_CONNTRACK_SYN_RECV], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_established", - .data = &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_fin_wait", - .data = &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_close_wait", - .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_last_ack", - .data = &tcp_timeouts[TCP_CONNTRACK_LAST_ACK], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_time_wait", - .data = &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_close", - .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_max_retrans", - .data = &nf_ct_tcp_timeout_max_retrans, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_tcp_timeout_unacknowledged", - .data = &nf_ct_tcp_timeout_unacknowledged, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -1260,7 +1274,6 @@ static struct ctl_table tcp_sysctl_table { .ctl_name = NET_NF_CONNTRACK_TCP_LOOSE, .procname = "nf_conntrack_tcp_loose", - .data = &nf_ct_tcp_loose, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1268,7 +1281,6 @@ static struct ctl_table tcp_sysctl_table { .ctl_name = NET_NF_CONNTRACK_TCP_BE_LIBERAL, .procname = "nf_conntrack_tcp_be_liberal", - .data = &nf_ct_tcp_be_liberal, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1276,7 +1288,6 @@ static struct ctl_table tcp_sysctl_table { .ctl_name = NET_NF_CONNTRACK_TCP_MAX_RETRANS, .procname = "nf_conntrack_tcp_max_retrans", - .data = &nf_ct_tcp_max_retrans, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1290,63 +1301,54 @@ static struct ctl_table tcp_sysctl_tablestatic struct ctl_table tcp_compat_sysctl_table[] = { { .procname ="ip_conntrack_tcp_timeout_syn_sent" , - .data = &tcp_timeouts[TCP_CONNTRACK_SYN_SENT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_syn_recv" , - .data = &tcp_timeouts[TCP_CONNTRACK_SYN_RECV ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_established" , - .data = &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_fin_wait" , - .data = &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_close_wait" , - .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_last_ack" , - .data = &tcp_timeouts[TCP_CONNTRACK_LAST_ACK ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_time_wait" , - .data = &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_close" , - .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_tcp_timeout_max_retrans" , - .data = &nf_ct_tcp_timeout_max_retrans, .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies,
@@ -1354,7 +1356,6 @@ static struct ctl_table tcp_compat_sysct { .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_LOOSE, .procname = "ip_conntrack_tcp_loose", - .data = &nf_ct_tcp_loose, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1362,7 +1363,6 @@ static struct ctl_table tcp_compat_sysct { .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL, .procname = "ip_conntrack_tcp_be_liberal", - .data = &nf_ct_tcp_be_liberal, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1370,7 +1370,6 @@ static struct ctl_table tcp_compat_sysct { .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS, .procname = "ip_conntrack_tcp_max_retrans", - .data = &nf_ct_tcp_max_retrans, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec,
@@ -1401,14 +1400,6 @@ struct nf_conntrack_l4proto nf_conntrack .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &tcp_sysctl_table_users, - .ctl_table_header = &tcp_sysctl_header, - .ctl_table = tcp_sysctl_table, -#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT - .ctl_compat_table = tcp_compat_sysctl_table, -#endif -#endif };EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_tcp4);
@@ -1431,10 +1422,144 @@ struct nf_conntrack_l4proto nf_conntrack .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif +}; +EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_tcp6); + +static __net_init int tcp_net_init (struct net *net) +{ +struct tcp_net *tn; +int err; + + tn =kmalloc (sizeof (*tn),GFP_KERNEL ); +if (!tn) +return -ENOMEM ; + +/* default values */ + tn->tcp_be_liberal =0 ; + tn->tcp_loose =1 ; + tn->tcp_max_retrans =3 ; + + tn->tcp_timeout_max_retrans = 5 MINS; + tn->tcp_timeout_unacknowledged = 5 MINS; + + tn->tcp_timeouts[TCP_CONNTRACK_SYN_SENT] = 2 MINS; + tn->tcp_timeouts[TCP_CONNTRACK_SYN_RECV] = 60 SECS; + tn->tcp_timeouts[TCP_CONNTRACK_ESTABLISHED] = 5 DAYS; + tn->tcp_timeouts[TCP_CONNTRACK_FIN_WAIT] = 2 MINS; + tn->tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT] = 60 SECS; + tn->tcp_timeouts[TCP_CONNTRACK_LAST_ACK] = 30 SECS; + tn->tcp_timeouts[TCP_CONNTRACK_TIME_WAIT] = 2 MINS; + tn->tcp_timeouts[TCP_CONNTRACK_CLOSE] = 10 SECS; + + err =net_assign_generic (net, tcp_net_id, tn); +if (err) + goto out; + +/* +* Pin per-net data to sysctl tables +* +* We allocate new ctrl tables from predefined templates +* and then assign .data fields iteratively, we allowed +* to do so since TCP_CONNTRACK_... (enum tcp_conntrack) +* is a part of userspace ABI and it's hardly that the enum +* entries will be rearranged +*/ + +#ifdef CONFIG_SYSCTL + { +int i; + err = -ENOMEM ; + tn->sysctl_table =kmemdup (tcp_sysctl_table, +sizeof (tcp_sysctl_table),GFP_KERNEL ); +if (!tn->sysctl_table) + goto out; + +for (i =TCP_CONNTRACK_SYN_SENT ; i <TCP_CONNTRACK_LISTEN ; i++) + tn->sysctl_table[i -1 ].data = &tn->tcp_timeouts[i]; + + tn->sysctl_table[8 ].data = &tn->tcp_timeout_max_retrans; + tn->sysctl_table[9 ].data = &tn->tcp_timeout_unacknowledged; + tn->sysctl_table[10 ].data = &tn->tcp_loose; + tn->sysctl_table[11 ].data = &tn->tcp_be_liberal; + tn->sysctl_table[12 ].data = &tn->tcp_max_retrans; + + tn->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, tn->sysctl_table); +if (!tn->sysctl_header) + goto out_free; + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + tn->compat_sysctl_table =kmemdup (tcp_compat_sysctl_table, +sizeof (tcp_compat_sysctl_table),GFP_KERNEL ); +if (!tn->compat_sysctl_table) + goto out_sysctl; + +for (i =TCP_CONNTRACK_SYN_SENT ; i <TCP_CONNTRACK_LISTEN ; i++) + tn->compat_sysctl_table[i -1 ].data = &tn->tcp_timeouts[i]; + + tn->compat_sysctl_table[8 ].data = &tn->tcp_timeout_max_retrans; + tn->compat_sysctl_table[9 ].data = &tn->tcp_loose; + tn->compat_sysctl_table[10 ].data = &tn->tcp_be_liberal; + tn->compat_sysctl_table[11 ].data = &tn->tcp_max_retrans; + + tn->compat_sysctl_header =register_net_sysctl_table (net, + nf_net_ipv4_netfilter_sysctl_path, + tn->compat_sysctl_table); +if (!tn->compat_sysctl_header) + goto out_free_compat; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ + } +#endif /* CONFIG_SYSCTL */ + +return 0 ; + +#ifdef CONFIG_SYSCTL +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +out_free_compat: +kfree (tn->compat_sysctl_table); +#endif +out_sysctl: +unregister_net_sysctl_table (tn->sysctl_header); +out_free: +kfree (tn->sysctl_table); +#endif + +out: +kfree (tn); +return err; +} + +static __net_exit void tcp_net_exit(struct net *net) +{ +struct tcp_net *tn =tcp_pernet (net);#ifdef CONFIG_SYSCTL - .ctl_table_users = &tcp_sysctl_table_users, - .ctl_table_header = &tcp_sysctl_header, - .ctl_table = tcp_sysctl_table, +unregister_net_sysctl_table (tn->sysctl_header); +kfree (tn->sysctl_table); +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +unregister_net_sysctl_table (tn->compat_sysctl_header); +kfree (tn->compat_sysctl_table);#endif +#endif +kfree (tn); + +net_assign_generic (net, tcp_net_id,NULL ); }; -EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_tcp6); + +static struct pernet_operations tcp_net_ops = { + .init = tcp_net_init, + .exit = tcp_net_exit, +}; + +static int __init nf_ct_tcp_proto_init (void ) +{ +return register_pernet_gen_subsys (&tcp_net_id, &tcp_net_ops); +} + +static void __exit nf_ct_tcp_proto_fini(void) +{ +unregister_pernet_gen_subsys (tcp_net_id, &tcp_net_ops); +} + +module_init (nf_ct_tcp_proto_init); +module_exit (nf_ct_tcp_proto_fini); +MODULE_LICENSE ("GPL" );
Re: [RFC v2 3/7] net: netfilter conntrack - add per-net functionality for SCTP protocol
In reply to Patrick McHardy[Patrick McHardy - Mon, Mar 16, 2009 at 07:29:02PM +0100]
...
Quoted 4 lines
Its better than the macro and I don't really see a better way, so this is fine with me. About the other patches - I just stopped at SCTP since it was the first one I truely didn't like :)
Here is an updated version of the patch with assignment in cycle. Please review. If all this series become a mess which hard to unwind (ie what version of patch is last, which is not) -- I could resend the whole series (excluding already applied). Just say. Thanks!
---
From: Cyrill Gorcunov <[email protected]>
Subject: [RFC v2 3/7] net: netfilter conntrack - add per-net functionality for SCTP protocol
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
--- net/netfilter/nf_conntrack_proto_sctp.c | 179 ++++++++++++++++++++++++-------- 1 file changed, 139 insertions(+), 40 deletions(-)
net/netfilter/nf_conntrack_proto_sctp.c +139 -40
@@ -21,6 +21,9 @@#include <linux/spinlock.h> #include <linux/interrupt.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> +#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_ecache.h>
@@ -49,16 +52,6 @@ static const char *const sctp_conntrack_#define HOURS * 60 MINS#define DAYS * 24 HOURS -static unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX ]__read_mostly = { - [SCTP_CONNTRACK_CLOSED] = 10 SECS, - [SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS, - [SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS, - [SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS, - [SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000, - [SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000, - [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS, -}; -#define sNO SCTP_CONNTRACK_NONE#define sCL SCTP_CONNTRACK_CLOSED#define sCW SCTP_CONNTRACK_COOKIE_WAIT
@@ -130,6 +123,25 @@ static const u8 sctp_conntracks[2][9][SC } }; +/* this module per-net specifics */ +static int sctp_net_id; +struct sctp_net { +unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX ]; +#ifdef CONFIG_SYSCTL +struct ctl_table_header *sysctl_header; +struct ctl_table *sysctl_table; +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +struct ctl_table_header *compat_sysctl_header; +struct ctl_table *compat_sysctl_table; +#endif +#endif +}; + +static inline struct sctp_net *sctp_pernet (struct net *net) +{ +return net_generic (net, sctp_net_id); +} +static bool sctp_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff,struct nf_conntrack_tuple *tuple) {
@@ -297,6 +309,7 @@ static int sctp_packet(struct nf_conn *cconst struct sctp_chunkhdr *sch;struct sctp_chunkhdr _sch;u_int32_t offset, count; +struct sctp_net *sn;unsigned long map[256 /sizeof (unsigned long )] = {0 }; sh =skb_header_pointer (skb, dataoff,sizeof (_sctph), &_sctph);
@@ -373,7 +386,8 @@ static int sctp_packet(struct nf_conn *c }write_unlock_bh (&sctp_lock); -nf_ct_refresh_acct (ct, ctinfo, skb, sctp_timeouts[new_state]); + sn =sctp_pernet (nf_ct_net (ct)); +nf_ct_refresh_acct (ct, ctinfo, skb, sn->sctp_timeouts[new_state]); if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED && dir == IP_CT_DIR_REPLY &&
@@ -540,54 +554,46 @@ static int nlattr_to_sctp(struct nlattr#endif #ifdef CONFIG_SYSCTL -static unsigned int sctp_sysctl_table_users; -static struct ctl_table_header *sctp_sysctl_header; +/* templates, data assigned later */ static struct ctl_table sctp_sysctl_table[] = { { .procname = "nf_conntrack_sctp_timeout_closed", - .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_cookie_wait", - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_cookie_echoed", - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_established", - .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_sent", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_recd", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -601,49 +607,42 @@ static struct ctl_table sctp_sysctl_tablstatic struct ctl_table sctp_compat_sysctl_table[] = { { .procname ="ip_conntrack_sctp_timeout_closed" , - .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_cookie_wait" , - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_cookie_echoed" , - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_established" , - .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_sent" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_recd" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_ack_sent" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies,
@@ -653,7 +652,7 @@ static struct ctl_table sctp_compat_sysc } };#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ -#endif +#endif /* CONFIG_SYSCTL */ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4__read_mostly = { .l3proto =PF_INET ,
@@ -673,14 +672,6 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &sctp_sysctl_table_users, - .ctl_table_header = &sctp_sysctl_header, - .ctl_table = sctp_sysctl_table, -#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT - .ctl_compat_table = sctp_compat_sysctl_table, -#endif -#endif };static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6__read_mostly = {
@@ -701,21 +692,126 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif +}; + +static __net_init int sctp_net_init (struct net *net) +{ +struct sctp_net *sn; +int err; + + sn =kmalloc (sizeof (*sn),GFP_KERNEL ); +if (!sn) +return -ENOMEM ; + +/* default values */ + sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED] = 10 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS; + + err =net_assign_generic (net, sctp_net_id, sn); +if (err) + goto out; + +/* +* Pin per-net data to sysctl tables +* +* We allocate new ctrl tables from predefined templates +* and then assign .data fields iteratively, we allowed +* to do so since SCTP_CONNTRACK_... (enum sctp_conntrack) +* is a part of userspace ABI and it's hardly that the enum +* entries will be rearranged +*/ +#ifdef CONFIG_SYSCTL - .ctl_table_users = &sctp_sysctl_table_users, - .ctl_table_header = &sctp_sysctl_header, - .ctl_table = sctp_sysctl_table, + { +int i; + err = -ENOMEM ; + sn->sysctl_table =kmemdup (sctp_sysctl_table, +sizeof (sctp_sysctl_table),GFP_KERNEL ); +if (!sn->sysctl_table) + goto out; + +for (i =SCTP_CONNTRACK_CLOSED ; i <SCTP_CONNTRACK_MAX ; i++) + sn->sysctl_table[i -1 ].data = &sn->sctp_timeouts[i]; + + sn->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, sn->sysctl_table); +if (!sn->sysctl_header) + goto out_free; + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + sn->compat_sysctl_table =kmemdup (sctp_compat_sysctl_table, +sizeof (sctp_compat_sysctl_table),GFP_KERNEL ); +if (!sn->compat_sysctl_table) + goto out_sysctl; + +for (i =SCTP_CONNTRACK_CLOSED ; i <SCTP_CONNTRACK_MAX ; i++) + sn->compat_sysctl_table[err -1 ].data = &sn->sctp_timeouts[i]; + + sn->compat_sysctl_header =register_net_sysctl_table (net, + nf_net_ipv4_netfilter_sysctl_path, sn->compat_sysctl_table); +if (!sn->compat_sysctl_header) + goto out_free_compat; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ + } +#endif /* CONFIG_SYSCTL */ + +return 0 ; + +#ifdef CONFIG_SYSCTL + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +out_free_compat: +kfree (sn->compat_sysctl_table); +#endif +out_sysctl: +unregister_net_sysctl_table (sn->sysctl_header); +out_free: +kfree (sn->sysctl_table); +#endif + +out: +kfree (sn); +return err; +} + +static __net_exit void sctp_net_exit(struct net *net) +{ +struct sctp_net *sn =sctp_pernet (net); +#ifdef CONFIG_SYSCTL +unregister_net_sysctl_table (sn->sysctl_header); +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +unregister_net_sysctl_table (sn->compat_sysctl_header); +kfree (sn->compat_sysctl_table);#endif +kfree (sn->sysctl_table); +#endif +kfree (sn); + +net_assign_generic (net, sctp_net_id,NULL ); +} + +static struct pernet_operations sctp_net_ops = { + .init = sctp_net_init, + .exit = sctp_net_exit, };static int __init nf_conntrack_proto_sctp_init (void ) {int ret; + ret =register_pernet_gen_subsys (&sctp_net_id, &sctp_net_ops); +if (ret <0 ) + goto out; + ret =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_sctp4);if (ret) {printk ("nf_conntrack_l4proto_sctp4: protocol register failed\n" ); - goto out; + goto cleanup_net; } ret =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_sctp6);if (ret) {
@@ -727,12 +823,15 @@ static int __init nf_conntrack_proto_sct cleanup_sctp4:nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp4); + cleanup_net: +unregister_pernet_gen_subsys (sctp_net_id, &sctp_net_ops); out:return ret; } static void __exit nf_conntrack_proto_sctp_fini(void) { +unregister_pernet_gen_subsys (sctp_net_id, &sctp_net_ops);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp6);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp4); }
Re: [RFC v2 5/7] net: netfilter conntrack - add per-net functionality for TCP protocol
In reply to Cyrill GorcunovQuoted 10 lines · Cyrill Gorcunov
Here is an updated version which uses iterative assignment of sysctl data. Please review.
---From: Cyrill Gorcunov <[email protected]>
Subject: [RFC v2 5/7] net: netfilter conntrack - add per-net functionality for TCP protocolModule specific data moved into per-net site and being allocated/freed during net namespace creation/deletion. For this reason module_init/exit calls added.
I guess this isn't going to get any prettier :) Could you please send me the latest version of the missing patches against the current nf-next tree?
Re: [RFC v2 5/7] net: netfilter conntrack - add per-net functionality for TCP protocol
[Patrick McHardy - Thu, Mar 26, 2009 at 04:13:58PM +0100]
Quoted 8 lines
Quoted 7 lines · Cyrill Gorcunov
Here is an updated version which uses iterative assignment of sysctl data. Please review.
---From: Cyrill Gorcunov <[email protected]>
Subject: [RFC v2 5/7] net: netfilter conntrack - add per-net functionality for TCP protocol
Quoted 9 lines
Quoted 3 lines
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion. For this reason module_init/exit calls added.
I guess this isn't going to get any prettier :) Could you please send me the latest version of the missing patches against the current nf-next tree?
Yes, no problem, wait a bit please.
Btw, I think the bestest way (and surely more clean) would be to use some new form of the sysctl templates.
But I didn't find such a form of writting which would sutisfy me. Since you said those enums are written in stone it's safe to use iterative fasion indeed but as I see you found them not that "pretty" too :)
On the other hand -- if per-net initialization is not that critical in speed (ie some speed could be sacrificed for the code clarity -- I could play with those templates maybe). Just a thought.
Cyrill
Re: [RFC v2 5/7] net: netfilter conntrack - add per-net functionality for TCP protocol
Quoted 9 lines · Cyrill Gorcunov
Yes, no problem, wait a bit please.
Btw, I think the bestest way (and surely more clean) would be to use some new form of the sysctl templates.
But I didn't find such a form of writting which would sutisfy me. Since you said those enums are written in stone it's safe to use iterative fasion indeed but as I see you found them not that "pretty" too :)
I just like the code structure with all definitions and initializations at the top better. But that obviously isn't possible with network namespaces, so just ignore me :)
Quoted 4 lines
On the other hand -- if per-net initialization is not that critical in speed (ie some speed could be sacrificed for the code clarity -- I could play with those templates maybe). Just a thought.
For now lets just get this stuff in since I think its about the last bits for full netfilter namespace support. I'll happily take further cleanups of course, but I don't think its worth delaying this any longer.
Re: [RFC v2 5/7] net: netfilter conntrack - add per-net functionality for TCP protocol
[Patrick McHardy - Thu, Mar 26, 2009 at 04:46:16PM +0100]
Quoted 20 lines
Quoted 9 lines · Cyrill Gorcunov
Yes, no problem, wait a bit please.
Btw, I think the bestest way (and surely more clean) would be to use some new form of the sysctl templates.
But I didn't find such a form of writting which would sutisfy me. Since you said those enums are written in stone it's safe to use iterative fasion indeed but as I see you found them not that "pretty" too :)
I just like the code structure with all definitions and initializations at the top better. But that obviously isn't possible with network namespaces, so just ignore me :)
Quoted 4 lines
On the other hand -- if per-net initialization is not that critical in speed (ie some speed could be sacrificed for the code clarity -- I could play with those templates maybe). Just a thought.
Quoted 5 lines
For now lets just get this stuff in since I think its about the last bits for full netfilter namespace support. I'll happily take further cleanups of course, but I don't think its worth delaying this any longer.
ok, I'm almost sending them (last compile test on every patch, please give me a few minutes)
Cyrill