@@ -184,9 +184,14 @@ struct xt_target {
unsigned short family;
};
+struct nf_hook_state;
+typedef unsigned int xt_hookfn(void *priv,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state);
/* Furniture shopping... */
struct xt_table {
struct list_head list;
+ struct net *net;
/* What hooks you will enter on */
unsigned int valid_hooks;
@@ -200,6 +205,9 @@ struct xt_table {
u_int8_t af; /* address/protocol family */
int priority; /* hook order */
+ /* Default hook function */
+ xt_hookfn *fn;
+
/* A unique name... */
const char name[XT_TABLE_MAXNAMELEN];
};
@@ -38,7 +38,7 @@ static struct nf_hook_ops *arpfilter_ops __read_mostly;
static int __net_init arptable_filter_net_init(struct net *net)
{
struct arpt_replace *repl;
-
+
repl = arpt_alloc_initial_table(&packet_filter);
if (repl == NULL)
return -ENOMEM;
@@ -833,6 +833,57 @@ xt_replace_table(struct xt_table *table,
}
EXPORT_SYMBOL_GPL(xt_replace_table);
+static void xt_unregister_hooks(const struct xt_table *table)
+{
+ unsigned long bits = table->valid_hooks;
+ struct net *net = table->net;
+ struct nf_hook_ops ops = {
+ .hook = table->fn,
+ .owner = table->me,
+ .pf = table->af,
+ .hooknum = 0,
+ .priority = table->priority,
+ };
+ unsigned bit;
+
+ for_each_set_bit(bit, &bits, NF_MAX_HOOKS) {
+ ops.hooknum = bit;
+ nf_unregister_hook(net, &ops);
+ }
+}
+
+static int xt_register_hooks(const struct xt_table *table)
+{
+ unsigned long bits = table->valid_hooks;
+ unsigned long registered = 0;
+ struct net *net = table->net;
+ struct nf_hook_ops ops = {
+ .hook = table->fn,
+ .owner = table->me,
+ .pf = table->af,
+ .hooknum = 0,
+ .priority = table->priority,
+ };
+ unsigned bit;
+ int ret;
+
+ for_each_set_bit(bit, &bits, NF_MAX_HOOKS) {
+ ops.hooknum = bit;
+ ret = nf_register_hook(net, &ops);
+ if (ret)
+ goto cleanup;
+ registered |= 1 << bit;
+ }
+ return 0;
+
+cleanup:
+ for_each_set_bit(bit, ®istered, NF_MAX_HOOKS) {
+ ops.hooknum = bit;
+ nf_unregister_hook(net, &ops);
+ }
+ return ret;
+}
+
struct xt_table *xt_register_table(struct net *net,
const struct xt_table *input_table,
struct xt_table_info *bootstrap,
@@ -871,7 +922,15 @@ struct xt_table *xt_register_table(struct net *net,
private->initial_entries = private->number;
list_add(&table->list, &net->xt.tables[table->af]);
+ table->net = net;
mutex_unlock(&xt[table->af].mutex);
+
+ if (table->fn) {
+ ret = xt_register_hooks(table);
+ if (ret)
+ goto out_unregister;
+ }
+
return table;
unlock:
@@ -879,6 +938,10 @@ unlock:
kfree(table);
out:
return ERR_PTR(ret);
+out_unregister:
+ mutex_lock(&xt[table->af].mutex);
+ list_del(&table->list);
+ goto unlock;
}
EXPORT_SYMBOL_GPL(xt_register_table);
@@ -886,6 +949,9 @@ void *xt_unregister_table(struct xt_table *table)
{
struct xt_table_info *private;
+ if (table->fn)
+ xt_unregister_hooks(table);
+
mutex_lock(&xt[table->af].mutex);
private = table->private;
list_del(&table->list);