|
@@ -694,12 +694,45 @@ EXPORT_SYMBOL(xt_free_table_info);
|
|
|
struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
|
|
|
const char *name)
|
|
|
{
|
|
|
- struct xt_table *t;
|
|
|
+ struct xt_table *t, *found = NULL;
|
|
|
|
|
|
mutex_lock(&xt[af].mutex);
|
|
|
list_for_each_entry(t, &net->xt.tables[af], list)
|
|
|
if (strcmp(t->name, name) == 0 && try_module_get(t->me))
|
|
|
return t;
|
|
|
+
|
|
|
+ if (net == &init_net)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ /* Table doesn't exist in this netns, re-try init */
|
|
|
+ list_for_each_entry(t, &init_net.xt.tables[af], list) {
|
|
|
+ if (strcmp(t->name, name))
|
|
|
+ continue;
|
|
|
+ if (!try_module_get(t->me))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ mutex_unlock(&xt[af].mutex);
|
|
|
+ if (t->table_init(net) != 0) {
|
|
|
+ module_put(t->me);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ found = t;
|
|
|
+
|
|
|
+ mutex_lock(&xt[af].mutex);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!found)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ /* and once again: */
|
|
|
+ list_for_each_entry(t, &net->xt.tables[af], list)
|
|
|
+ if (strcmp(t->name, name) == 0)
|
|
|
+ return t;
|
|
|
+
|
|
|
+ module_put(found->me);
|
|
|
+ out:
|
|
|
mutex_unlock(&xt[af].mutex);
|
|
|
return NULL;
|
|
|
}
|
|
@@ -1170,20 +1203,20 @@ static const struct file_operations xt_target_ops = {
|
|
|
#endif /* CONFIG_PROC_FS */
|
|
|
|
|
|
/**
|
|
|
- * xt_hook_link - set up hooks for a new table
|
|
|
+ * xt_hook_ops_alloc - set up hooks for a new table
|
|
|
* @table: table with metadata needed to set up hooks
|
|
|
* @fn: Hook function
|
|
|
*
|
|
|
- * This function will take care of creating and registering the necessary
|
|
|
- * Netfilter hooks for XT tables.
|
|
|
+ * This function will create the nf_hook_ops that the x_table needs
|
|
|
+ * to hand to xt_hook_link_net().
|
|
|
*/
|
|
|
-struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
|
|
|
+struct nf_hook_ops *
|
|
|
+xt_hook_ops_alloc(const struct xt_table *table, nf_hookfn *fn)
|
|
|
{
|
|
|
unsigned int hook_mask = table->valid_hooks;
|
|
|
uint8_t i, num_hooks = hweight32(hook_mask);
|
|
|
uint8_t hooknum;
|
|
|
struct nf_hook_ops *ops;
|
|
|
- int ret;
|
|
|
|
|
|
ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL);
|
|
|
if (ops == NULL)
|
|
@@ -1200,27 +1233,9 @@ struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
|
|
|
++i;
|
|
|
}
|
|
|
|
|
|
- ret = nf_register_hooks(ops, num_hooks);
|
|
|
- if (ret < 0) {
|
|
|
- kfree(ops);
|
|
|
- return ERR_PTR(ret);
|
|
|
- }
|
|
|
-
|
|
|
return ops;
|
|
|
}
|
|
|
-EXPORT_SYMBOL_GPL(xt_hook_link);
|
|
|
-
|
|
|
-/**
|
|
|
- * xt_hook_unlink - remove hooks for a table
|
|
|
- * @ops: nf_hook_ops array as returned by nf_hook_link
|
|
|
- * @hook_mask: the very same mask that was passed to nf_hook_link
|
|
|
- */
|
|
|
-void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops)
|
|
|
-{
|
|
|
- nf_unregister_hooks(ops, hweight32(table->valid_hooks));
|
|
|
- kfree(ops);
|
|
|
-}
|
|
|
-EXPORT_SYMBOL_GPL(xt_hook_unlink);
|
|
|
+EXPORT_SYMBOL_GPL(xt_hook_ops_alloc);
|
|
|
|
|
|
int xt_proto_init(struct net *net, u_int8_t af)
|
|
|
{
|