diff options
-rw-r--r-- | include/linux/netfilter/x_tables.h | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/arptable_filter.c | 33 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_filter.c | 33 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_mangle.c | 47 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_raw.c | 27 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_security.c | 33 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_filter.c | 33 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_mangle.c | 48 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_raw.c | 26 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_security.c | 33 | ||||
-rw-r--r-- | net/netfilter/x_tables.c | 54 |
11 files changed, 250 insertions, 121 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index a18119fb88f0..31a97c55d72a 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -360,7 +360,6 @@ struct xt_table { struct module *me; u_int8_t af; /* address/protocol family */ - int priority; /* hook order */ /* A unique name... */ const char name[XT_TABLE_MAXNAMELEN]; @@ -522,9 +521,6 @@ static inline unsigned long ifname_compare_aligned(const char *_a, return ret; } -extern struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *); -extern void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *); - #ifdef CONFIG_COMPAT #include <net/compat.h> diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index bfe26f32b930..ae619de581b8 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -21,7 +21,6 @@ static const struct xt_table packet_filter = { .valid_hooks = FILTER_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_ARP, - .priority = NF_IP_PRI_FILTER, }; /* The work comes in here from netfilter.c */ @@ -35,7 +34,29 @@ arptable_filter_hook(unsigned int hook, struct sk_buff *skb, return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter); } -static struct nf_hook_ops *arpfilter_ops __read_mostly; +static struct nf_hook_ops arpt_ops[] __read_mostly = { + { + .hook = arptable_filter_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_ARP, + .hooknum = NF_ARP_IN, + .priority = NF_IP_PRI_FILTER, + }, + { + .hook = arptable_filter_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_ARP, + .hooknum = NF_ARP_OUT, + .priority = NF_IP_PRI_FILTER, + }, + { + .hook = arptable_filter_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_ARP, + .hooknum = NF_ARP_FORWARD, + .priority = NF_IP_PRI_FILTER, + }, +}; static int __net_init arptable_filter_net_init(struct net *net) { @@ -70,11 +91,9 @@ static int __init arptable_filter_init(void) if (ret < 0) return ret; - arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook); - if (IS_ERR(arpfilter_ops)) { - ret = PTR_ERR(arpfilter_ops); + ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); + if (ret < 0) goto cleanup_table; - } return ret; cleanup_table: @@ -84,7 +103,7 @@ cleanup_table: static void __exit arptable_filter_fini(void) { - xt_hook_unlink(&packet_filter, arpfilter_ops); + nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); unregister_pernet_subsys(&arptable_filter_net_ops); } diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index c8dc9800d620..4724297419a9 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -28,7 +28,6 @@ static const struct xt_table packet_filter = { .valid_hooks = FILTER_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV4, - .priority = NF_IP_PRI_FILTER, }; static unsigned int @@ -48,7 +47,29 @@ iptable_filter_hook(unsigned int hook, struct sk_buff *skb, return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter); } -static struct nf_hook_ops *filter_ops __read_mostly; +static struct nf_hook_ops ipt_ops[] __read_mostly = { + { + .hook = iptable_filter_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_LOCAL_IN, + .priority = NF_IP_PRI_FILTER, + }, + { + .hook = iptable_filter_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_FORWARD, + .priority = NF_IP_PRI_FILTER, + }, + { + .hook = iptable_filter_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP_PRI_FILTER, + }, +}; /* Default to forward because I got too much mail already. */ static int forward = NF_ACCEPT; @@ -97,11 +118,9 @@ static int __init iptable_filter_init(void) return ret; /* Register hooks */ - filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook); - if (IS_ERR(filter_ops)) { - ret = PTR_ERR(filter_ops); + ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); + if (ret < 0) goto cleanup_table; - } return ret; @@ -112,7 +131,7 @@ static int __init iptable_filter_init(void) static void __exit iptable_filter_fini(void) { - xt_hook_unlink(&packet_filter, filter_ops); + nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); unregister_pernet_subsys(&iptable_filter_net_ops); } diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index b9b83464cbf4..6bdddc8f8862 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -32,7 +32,6 @@ static const struct xt_table packet_mangler = { .valid_hooks = MANGLE_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV4, - .priority = NF_IP_PRI_MANGLE, }; static unsigned int @@ -91,7 +90,43 @@ iptable_mangle_hook(unsigned int hook, dev_net(in)->ipv4.iptable_mangle); } -static struct nf_hook_ops *mangle_ops __read_mostly; +static struct nf_hook_ops ipt_ops[] __read_mostly = { + { + .hook = iptable_mangle_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_PRE_ROUTING, + .priority = NF_IP_PRI_MANGLE, + }, + { + .hook = iptable_mangle_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_LOCAL_IN, + .priority = NF_IP_PRI_MANGLE, + }, + { + .hook = iptable_mangle_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_FORWARD, + .priority = NF_IP_PRI_MANGLE, + }, + { + .hook = iptable_mangle_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP_PRI_MANGLE, + }, + { + .hook = iptable_mangle_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_POST_ROUTING, + .priority = NF_IP_PRI_MANGLE, + }, +}; static int __net_init iptable_mangle_net_init(struct net *net) { @@ -127,11 +162,9 @@ static int __init iptable_mangle_init(void) return ret; /* Register hooks */ - mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook); - if (IS_ERR(mangle_ops)) { - ret = PTR_ERR(mangle_ops); + ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); + if (ret < 0) goto cleanup_table; - } return ret; @@ -142,7 +175,7 @@ static int __init iptable_mangle_init(void) static void __exit iptable_mangle_fini(void) { - xt_hook_unlink(&packet_mangler, mangle_ops); + nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); unregister_pernet_subsys(&iptable_mangle_net_ops); } diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 06fb9d11953c..5af3c7d43cd5 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -14,7 +14,6 @@ static const struct xt_table packet_raw = { .valid_hooks = RAW_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV4, - .priority = NF_IP_PRI_RAW, }; /* The work comes in here from netfilter.c. */ @@ -35,7 +34,23 @@ iptable_raw_hook(unsigned int hook, struct sk_buff *skb, return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw); } -static struct nf_hook_ops *rawtable_ops __read_mostly; +/* 'raw' is the very first table. */ +static struct nf_hook_ops ipt_ops[] __read_mostly = { + { + .hook = iptable_raw_hook, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_PRE_ROUTING, + .priority = NF_IP_PRI_RAW, + .owner = THIS_MODULE, + }, + { + .hook = iptable_raw_hook, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP_PRI_RAW, + .owner = THIS_MODULE, + }, +}; static int __net_init iptable_raw_net_init(struct net *net) { @@ -71,11 +86,9 @@ static int __init iptable_raw_init(void) return ret; /* Register hooks */ - rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook); - if (IS_ERR(rawtable_ops)) { - ret = PTR_ERR(rawtable_ops); + ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); + if (ret < 0) goto cleanup_table; - } return ret; @@ -86,7 +99,7 @@ static int __init iptable_raw_init(void) static void __exit iptable_raw_fini(void) { - xt_hook_unlink(&packet_raw, rawtable_ops); + nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); unregister_pernet_subsys(&iptable_raw_net_ops); } diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index cce2f64e6f21..7d6f2502446c 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c @@ -32,7 +32,6 @@ static const struct xt_table security_table = { .valid_hooks = SECURITY_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV4, - .priority = NF_IP_PRI_SECURITY, }; static unsigned int @@ -53,7 +52,29 @@ iptable_security_hook(unsigned int hook, struct sk_buff *skb, return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security); } -static struct nf_hook_ops *sectbl_ops __read_mostly; +static struct nf_hook_ops ipt_ops[] __read_mostly = { + { + .hook = iptable_security_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_LOCAL_IN, + .priority = NF_IP_PRI_SECURITY, + }, + { + .hook = iptable_security_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_FORWARD, + .priority = NF_IP_PRI_SECURITY, + }, + { + .hook = iptable_security_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP_PRI_SECURITY, + }, +}; static int __net_init iptable_security_net_init(struct net *net) { @@ -89,11 +110,9 @@ static int __init iptable_security_init(void) if (ret < 0) return ret; - sectbl_ops = xt_hook_link(&security_table, iptable_security_hook); - if (IS_ERR(sectbl_ops)) { - ret = PTR_ERR(sectbl_ops); + ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); + if (ret < 0) goto cleanup_table; - } return ret; @@ -104,7 +123,7 @@ cleanup_table: static void __exit iptable_security_fini(void) { - xt_hook_unlink(&security_table, sectbl_ops); + nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); unregister_pernet_subsys(&iptable_security_net_ops); } diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 36b72cafc227..cf46f3f78899 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -26,7 +26,6 @@ static const struct xt_table packet_filter = { .valid_hooks = FILTER_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV6, - .priority = NF_IP6_PRI_FILTER, }; /* The work comes in here from netfilter.c. */ @@ -40,7 +39,29 @@ ip6table_filter_hook(unsigned int hook, struct sk_buff *skb, return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter); } -static struct nf_hook_ops *filter_ops __read_mostly; +static struct nf_hook_ops ip6t_ops[] __read_mostly = { + { + .hook = ip6table_filter_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_LOCAL_IN, + .priority = NF_IP6_PRI_FILTER, + }, + { + .hook = ip6table_filter_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_FORWARD, + .priority = NF_IP6_PRI_FILTER, + }, + { + .hook = ip6table_filter_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP6_PRI_FILTER, + }, +}; /* Default to forward because I got too much mail already. */ static int forward = NF_ACCEPT; @@ -89,11 +110,9 @@ static int __init ip6table_filter_init(void) return ret; /* Register hooks */ - filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook); - if (IS_ERR(filter_ops)) { - ret = PTR_ERR(filter_ops); + ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); + if (ret < 0) goto cleanup_table; - } return ret; @@ -104,7 +123,7 @@ static int __init ip6table_filter_init(void) static void __exit ip6table_filter_fini(void) { - xt_hook_unlink(&packet_filter, filter_ops); + nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); unregister_pernet_subsys(&ip6table_filter_net_ops); } diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 7844e557c0ec..142a18439b37 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -26,7 +26,6 @@ static const struct xt_table packet_mangler = { .valid_hooks = MANGLE_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV6, - .priority = NF_IP6_PRI_MANGLE, }; static unsigned int @@ -85,7 +84,44 @@ ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb, dev_net(in)->ipv6.ip6table_mangle); } -static struct nf_hook_ops *mangle_ops __read_mostly; +static struct nf_hook_ops ip6t_ops[] __read_mostly = { + { + .hook = ip6table_mangle_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_PRE_ROUTING, + .priority = NF_IP6_PRI_MANGLE, + }, + { + .hook = ip6table_mangle_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_LOCAL_IN, + .priority = NF_IP6_PRI_MANGLE, + }, + { + .hook = ip6table_mangle_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_FORWARD, + .priority = NF_IP6_PRI_MANGLE, + }, + { + .hook = ip6table_mangle_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP6_PRI_MANGLE, + }, + { + .hook = ip6table_mangle_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_POST_ROUTING, + .priority = NF_IP6_PRI_MANGLE, + }, +}; + static int __net_init ip6table_mangle_net_init(struct net *net) { struct ip6t_replace *repl; @@ -120,11 +156,9 @@ static int __init ip6table_mangle_init(void) return ret; /* Register hooks */ - mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook); - if (IS_ERR(mangle_ops)) { - ret = PTR_ERR(mangle_ops); + ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); + if (ret < 0) goto cleanup_table; - } return ret; @@ -135,7 +169,7 @@ static int __init ip6table_mangle_init(void) static void __exit ip6table_mangle_fini(void) { - xt_hook_unlink(&packet_mangler, mangle_ops); + nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); unregister_pernet_subsys(&ip6table_mangle_net_ops); } diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index aef31a29de9e..0e2bdea59f2f 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -13,7 +13,6 @@ static const struct xt_table packet_raw = { .valid_hooks = RAW_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV6, - .priority = NF_IP6_PRI_FIRST, }; /* The work comes in here from netfilter.c. */ @@ -27,7 +26,22 @@ ip6table_raw_hook(unsigned int hook, struct sk_buff *skb, return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw); } -static struct nf_hook_ops *rawtable_ops __read_mostly; +static struct nf_hook_ops ip6t_ops[] __read_mostly = { + { + .hook = ip6table_raw_hook, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_PRE_ROUTING, + .priority = NF_IP6_PRI_FIRST, + .owner = THIS_MODULE, + }, + { + .hook = ip6table_raw_hook, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP6_PRI_FIRST, + .owner = THIS_MODULE, + }, +}; static int __net_init ip6table_raw_net_init(struct net *net) { @@ -63,11 +77,9 @@ static int __init ip6table_raw_init(void) return ret; /* Register hooks */ - rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook); - if (IS_ERR(rawtable_ops)) { - ret = PTR_ERR(rawtable_ops); + ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); + if (ret < 0) goto cleanup_table; - } return ret; @@ -78,7 +90,7 @@ static int __init ip6table_raw_init(void) static void __exit ip6table_raw_fini(void) { - xt_hook_unlink(&packet_raw, rawtable_ops); + nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); unregister_pernet_subsys(&ip6table_raw_net_ops); } diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 0824d865aa9b..7f4134b9b0ee 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c @@ -31,7 +31,6 @@ static const struct xt_table security_table = { .valid_hooks = SECURITY_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV6, - .priority = NF_IP6_PRI_SECURITY, }; static unsigned int @@ -45,7 +44,29 @@ ip6table_security_hook(unsigned int hook, struct sk_buff *skb, return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security); } -static struct nf_hook_ops *sectbl_ops __read_mostly; +static struct nf_hook_ops ip6t_ops[] __read_mostly = { + { + .hook = ip6table_security_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_LOCAL_IN, + .priority = NF_IP6_PRI_SECURITY, + }, + { + .hook = ip6table_security_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_FORWARD, + .priority = NF_IP6_PRI_SECURITY, + }, + { + .hook = ip6table_security_hook, + .owner = THIS_MODULE, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP6_PRI_SECURITY, + }, +}; static int __net_init ip6table_security_net_init(struct net *net) { @@ -81,11 +102,9 @@ static int __init ip6table_security_init(void) if (ret < 0) return ret; - sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook); - if (IS_ERR(sectbl_ops)) { - ret = PTR_ERR(sectbl_ops); + ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); + if (ret < 0) goto cleanup_table; - } return ret; @@ -96,7 +115,7 @@ cleanup_table: static void __exit ip6table_security_fini(void) { - xt_hook_unlink(&security_table, sectbl_ops); + nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); unregister_pernet_subsys(&ip6table_security_net_ops); } diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 0a12cedfe9e3..e9417c22e4b6 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -1097,60 +1097,6 @@ static const struct file_operations xt_target_ops = { #endif /* CONFIG_PROC_FS */ -/** - * xt_hook_link - 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. - */ -struct nf_hook_ops *xt_hook_link(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) - return ERR_PTR(-ENOMEM); - - for (i = 0, hooknum = 0; i < num_hooks && hook_mask != 0; - hook_mask >>= 1, ++hooknum) { - if (!(hook_mask & 1)) - continue; - ops[i].hook = fn; - ops[i].owner = table->me; - ops[i].pf = table->af; - ops[i].hooknum = hooknum; - ops[i].priority = table->priority; - ++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); - int xt_proto_init(struct net *net, u_int8_t af) { #ifdef CONFIG_PROC_FS |