diff -uprN a/include/linux/netfilter_ipv4/ipt_recent.h b/include/linux/netfilter_ipv4/ipt_recent.h --- a/include/linux/netfilter_ipv4/ipt_recent.h 2007-10-23 12:09:36.000000000 +0400 +++ b/include/linux/netfilter_ipv4/ipt_recent.h 2007-10-23 16:29:30.000000000 +0400 @@ -24,4 +24,10 @@ struct ipt_recent_info { u_int8_t side; }; +struct ve_ipt_recent { + struct list_head tables; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc_dir; +#endif +}; #endif /*_IPT_RECENT_H*/ diff -uprN a/include/linux/ve.h b/include/linux/ve.h --- a/include/linux/ve.h 2007-10-23 12:09:49.000000000 +0400 +++ b/include/linux/ve.h 2007-10-23 12:26:32.000000000 +0400 @@ -115,6 +115,8 @@ struct ve_cpu_stats { cputime64_t system; } ____cacheline_aligned; +struct ve_ipt_recent; + struct ve_struct { struct list_head ve_list; @@ -254,6 +256,7 @@ struct ve_struct { __u64 _iptables_modules; struct ve_ip_conntrack *_ip_conntrack; + struct ve_ipt_recent *_ipt_recent; #endif /* CONFIG_VE_IPTABLES */ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) diff -uprN a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c --- a/net/ipv4/netfilter/ipt_recent.c 2007-10-23 12:10:18.000000000 +0400 +++ b/net/ipv4/netfilter/ipt_recent.c 2007-10-23 16:36:11.000000000 +0400 @@ -44,6 +44,18 @@ MODULE_PARM_DESC(ip_pkt_list_tot, "numbe MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs"); MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/ipt_recent/* files"); +#include + +#if defined(CONFIG_VE_IPTABLES) +#define tables (get_exec_env()->_ipt_recent->tables) +#define proc_dir (get_exec_env()->_ipt_recent->proc_dir) +#else +static LIST_HEAD(tables); +static struct proc_dir_entry *proc_dir; +#endif /* CONFIG_VE_IPTABLES */ + +static int init_ipt_recent(void); +static void fini_ipt_recent(void); struct recent_entry { struct list_head list; @@ -67,12 +79,10 @@ struct recent_table { struct list_head iphash[0]; }; -static LIST_HEAD(tables); static DEFINE_SPINLOCK(recent_lock); static DEFINE_MUTEX(recent_mutex); #ifdef CONFIG_PROC_FS -static struct proc_dir_entry *proc_dir; static struct file_operations recent_fops; #endif @@ -237,8 +247,10 @@ ipt_recent_checkentry(const char *tablen const struct ipt_recent_info *info = matchinfo; struct recent_table *t; unsigned i; + struct ve_struct *env; int ret = 0; + env = get_exec_env(); if (hweight8(info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE | IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) != 1) @@ -250,6 +262,13 @@ ipt_recent_checkentry(const char *tablen strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN) return 0; +#ifdef CONFIG_VE_IPTABLES + if (!env->_ipt_recent) { + if (init_ipt_recent()) + return 0; + } +#endif + mutex_lock(&recent_mutex); t = recent_table_lookup(info->name); if (t != NULL) { @@ -291,6 +310,13 @@ ipt_recent_destroy(const struct xt_match { const struct ipt_recent_info *info = matchinfo; struct recent_table *t; + struct ve_struct *env; + + env = get_exec_env(); +#ifdef CONFIG_VE_IPTABLES + if (!env->_ipt_recent) + return; +#endif mutex_lock(&recent_mutex); t = recent_table_lookup(info->name); @@ -305,6 +331,8 @@ ipt_recent_destroy(const struct xt_match kfree(t); } mutex_unlock(&recent_mutex); + if ((!ve_is_super(env)) && list_empty(&tables)) + fini_ipt_recent(); } #ifdef CONFIG_PROC_FS @@ -465,34 +493,83 @@ static struct ipt_match recent_match = { .me = THIS_MODULE, }; -static int __init ipt_recent_init(void) +static int init_ipt_recent(void) { - int err; + struct ve_struct *env; + int err = 0; - if (!ip_list_tot || !ip_pkt_list_tot || ip_pkt_list_tot > 255) - return -EINVAL; - ip_list_hash_size = 1 << fls(ip_list_tot); + env = get_exec_env(); +#ifdef CONFIG_VE_IPTABLES + env->_ipt_recent = + kmalloc(sizeof(struct ve_ipt_recent), GFP_KERNEL); + if (!env->_ipt_recent) { + err = -ENOMEM; + goto out; + } + memset(env->_ipt_recent, 0, sizeof(struct ve_ipt_recent)); - err = ipt_register_match(&recent_match); + INIT_LIST_HEAD(&tables); +#endif + if (ve_is_super(env)) { + err = ipt_register_match(&recent_match); + if (err) + goto out_mem; + } #ifdef CONFIG_PROC_FS if (err) return err; proc_dir = proc_mkdir("ipt_recent", proc_net); if (proc_dir == NULL) { - ipt_unregister_match(&recent_match); + if (ve_is_super(env)) + ipt_unregister_match(&recent_match); err = -ENOMEM; + goto out_mem; } #endif +out: return err; +out_mem: + kfree(env->_ipt_recent); + goto out; } -static void __exit ipt_recent_exit(void) +static void fini_ipt_recent(void) { - BUG_ON(!list_empty(&tables)); - ipt_unregister_match(&recent_match); + struct ve_struct *env; + + env = get_exec_env(); #ifdef CONFIG_PROC_FS remove_proc_entry("ipt_recent", proc_net); #endif + if (ve_is_super(env)) + ipt_unregister_match(&recent_match); +#ifdef CONFIG_VE_IPTABLES + if (env->_ipt_recent) + kfree(env->_ipt_recent); + env->_ipt_recent = NULL; +#endif +} + +static int __init ipt_recent_init(void) +{ + int err; + + if (!ip_list_tot || !ip_pkt_list_tot || ip_pkt_list_tot > 255) + return -EINVAL; + ip_list_hash_size = 1 << fls(ip_list_tot); + + err = init_ipt_recent(); + if (err) + return err; + + return 0; +} + +static void __exit ipt_recent_exit(void) +{ + BUG_ON(!list_empty(&tables)); + + fini_ipt_recent(); } module_init(ipt_recent_init);