xt_recent: netns support
Subsystems (2)
PATCH 3/4 xt_recent: netns support
Make recent table list per-netns.
Make proc files per-netns.
Signed-off-by Alexey Dobriyan <[email protected]>
---
net/netfilter/xt_recent.c | 136 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 41 deletions(-)
net/netfilter/xt_recent.c +95 -41
@@ -28,6 +28,7 @@#include <linux/skbuff.h> #include <linux/inet.h> #include <net/net_namespace.h> +#include <net/netns/generic.h> #include <linux/netfilter/x_tables.h> #include <linux/netfilter/xt_recent.h>
@@ -78,15 +79,26 @@ struct recent_table {struct list_head iphash[0 ]; }; -static LIST_HEAD (tables); +struct recent_net { +struct list_head tables; +#ifdef CONFIG_PROC_FS +struct proc_dir_entry *xt_recent; +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT +struct proc_dir_entry *ipt_recent; +#endif +#endif +}; + +static int recent_net_id; +static inline struct recent_net *recent_pernet (struct net *net) +{ +return net_generic (net, recent_net_id); +} +static DEFINE_SPINLOCK (recent_lock);static DEFINE_MUTEX (recent_mutex);#ifdef CONFIG_PROC_FS -#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT -static struct proc_dir_entry *proc_old_dir; -#endif -static struct proc_dir_entry *recent_proc_dir;static const struct file_operations recent_old_fops, recent_mt_fops;#endif
@@ -180,11 +192,12 @@ static void recent_entry_update(struct recent_table *t, struct recent_entry *e)list_move_tail (&e->lru_list, &t->lru_list); } -static struct recent_table *recent_table_lookup (const char *name) +static struct recent_table *recent_table_lookup (struct recent_net *recent_net, +const char *name) {struct recent_table *t; -list_for_each_entry (t, &tables, list) +list_for_each_entry (t, &recent_net->tables, list)if (!strcmp (t->name, name))return t;return NULL ;
@@ -203,6 +216,8 @@ static void recent_table_flush(struct recent_table *t)static bool recent_mt (const struct sk_buff *skb,const struct xt_match_param *par) { +struct net *net =dev_net (par->in ? par->in : par->out); +struct recent_net *recent_net =recent_pernet (net);const struct xt_recent_mtinfo *info = par->matchinfo;struct recent_table *t;struct recent_entry *e;
@@ -235,7 +250,7 @@ recent_mt(const struct sk_buff *skb, const struct xt_match_param *par) ttl++;spin_lock_bh (&recent_lock); - t =recent_table_lookup (info->name); + t =recent_table_lookup (recent_net, info->name); e =recent_entry_lookup (t, &addr, par->match->family, (info->check_set &XT_RECENT_TTL ) ? ttl :0 );if (e ==NULL ) {
@@ -279,6 +294,7 @@ out:static bool recent_mt_check (const struct xt_mtchk_param *par) { +struct recent_net *recent_net =recent_pernet (par->net);const struct xt_recent_mtinfo *info = par->matchinfo;struct recent_table *t;#ifdef CONFIG_PROC_FS
@@ -301,7 +317,7 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)return false;mutex_lock (&recent_mutex); - t =recent_table_lookup (info->name); + t =recent_table_lookup (recent_net, info->name);if (t !=NULL ) { t->refcnt++; ret = true;
@@ -318,7 +334,7 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)for (i =0 ; i < ip_list_hash_size; i++)INIT_LIST_HEAD (&t->iphash[i]);#ifdef CONFIG_PROC_FS - pde =proc_create_data (t->name, ip_list_perms, recent_proc_dir, + pde =proc_create_data (t->name, ip_list_perms, recent_net->xt_recent, &recent_mt_fops, t);if (pde ==NULL ) {kfree (t);
@@ -327,10 +343,10 @@ static bool recent_mt_check(const struct xt_mtchk_param *par) pde->uid = ip_list_uid; pde->gid = ip_list_gid;#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT - pde =proc_create_data (t->name, ip_list_perms, proc_old_dir, + pde =proc_create_data (t->name, ip_list_perms, recent_net->ipt_recent, &recent_old_fops, t);if (pde ==NULL ) { -remove_proc_entry (t->name, proc_old_dir); +remove_proc_entry (t->name, recent_net->xt_recent);kfree (t); goto out; }
@@ -339,7 +355,7 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)#endif #endif spin_lock_bh (&recent_lock); -list_add_tail (&t->list, &tables); +list_add_tail (&t->list, &recent_net->tables);spin_unlock_bh (&recent_lock); ret = true; out:
@@ -349,20 +365,21 @@ out:static void recent_mt_destroy (const struct xt_mtdtor_param *par) { +struct recent_net *recent_net =recent_pernet (par->net);const struct xt_recent_mtinfo *info = par->matchinfo;struct recent_table *t;mutex_lock (&recent_mutex); - t =recent_table_lookup (info->name); + t =recent_table_lookup (recent_net, info->name);if (--t->refcnt ==0 ) {spin_lock_bh (&recent_lock);list_del (&t->list);spin_unlock_bh (&recent_lock);#ifdef CONFIG_PROC_FS #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT -remove_proc_entry (t->name, proc_old_dir); +remove_proc_entry (t->name, recent_net->ipt_recent);#endif -remove_proc_entry (t->name, recent_proc_dir); +remove_proc_entry (t->name, recent_net->xt_recent);#endif recent_table_flush (t);kfree (t);
@@ -611,8 +628,65 @@ static const struct file_operations recent_mt_fops = { .release = seq_release_private, .owner = THIS_MODULE, }; + +static int __net_init recent_proc_net_init (struct net *net) +{ +struct recent_net *recent_net =recent_pernet (net); + + recent_net->xt_recent =proc_mkdir ("xt_recent" , net->proc_net); +if (!recent_net->xt_recent) +return -ENOMEM ; +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT + recent_net->ipt_recent =proc_mkdir ("ipt_recent" , net->proc_net); +if (!recent_net->ipt_recent) { +proc_net_remove (net,"xt_recent" ); +return -ENOMEM ; + } +#endif +return 0 ; +} + +static void __net_exit recent_proc_net_exit(struct net *net) +{ +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT +proc_net_remove (net,"ipt_recent" ); +#endif +proc_net_remove (net,"xt_recent" ); +} +#else +static inline int recent_proc_net_init (struct net *net) +{ +return 0 ; +} + +static inline void recent_proc_net_exit (struct net *net) +{ +}#endif /* CONFIG_PROC_FS */ +static int __net_init recent_net_init (struct net *net) +{ +struct recent_net *recent_net =recent_pernet (net); + +INIT_LIST_HEAD (&recent_net->tables); +return recent_proc_net_init (net); +} + +static void __net_exit recent_net_exit(struct net *net) +{ +struct recent_net *recent_net =recent_pernet (net); + +BUG_ON (!list_empty (&recent_net->tables)); +recent_proc_net_exit (net); +} + +static struct pernet_operations recent_net_ops = { + .init = recent_net_init, + .exit = recent_net_exit, + .id = &recent_net_id, + .size =sizeof (struct recent_net ), +}; +static struct xt_match recent_mt_reg[]__read_mostly = { { .name ="recent" ,
@@ -644,39 +718,19 @@ static int __init recent_mt_init(void)return -EINVAL ; ip_list_hash_size =1 <<fls (ip_list_tot); - err =xt_register_matches (recent_mt_reg,ARRAY_SIZE (recent_mt_reg)); -#ifdef CONFIG_PROC_FS + err =register_pernet_subsys (&recent_net_ops);if (err)return err; - recent_proc_dir =proc_mkdir ("xt_recent" , init_net.proc_net); -if (recent_proc_dir ==NULL ) { -xt_unregister_matches (recent_mt_reg,ARRAY_SIZE (recent_mt_reg)); - err = -ENOMEM ; - } -#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT -if (err <0 ) -return err; - proc_old_dir =proc_mkdir ("ipt_recent" , init_net.proc_net); -if (proc_old_dir ==NULL ) { -remove_proc_entry ("xt_recent" , init_net.proc_net); -xt_unregister_matches (recent_mt_reg,ARRAY_SIZE (recent_mt_reg)); - err = -ENOMEM ; - } -#endif -#endif + err =xt_register_matches (recent_mt_reg,ARRAY_SIZE (recent_mt_reg)); +if (err) +unregister_pernet_subsys (&recent_net_ops);return err; } static void __exit recent_mt_exit(void) { -BUG_ON (!list_empty (&tables));xt_unregister_matches (recent_mt_reg,ARRAY_SIZE (recent_mt_reg)); -#ifdef CONFIG_PROC_FS -#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT -remove_proc_entry ("ipt_recent" , init_net.proc_net); -#endif -remove_proc_entry ("xt_recent" , init_net.proc_net); -#endif +unregister_pernet_subsys (&recent_net_ops); }module_init (recent_mt_init);
Patrick McHardy
AppliedQuoted 2 lines · Alexey Dobriyan
Make recent table list per-netns.
Make proc files per-netns.
Applied, thanks.