Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Pablo Neira Ayuso says: ==================== Netfilter updates for net-next The following patchset contains Netfilter updates for net-next: 1) Use nfnetlink_unicast() instead of netlink_unicast() in nft_compat. 2) Remove call to nf_ct_l4proto_find() in flowtable offload timeout fixup. 3) CLUSTERIP registers ARP hook on demand, from Florian. 4) Use clusterip_net to store pernet warning, also from Florian. 5) Remove struct netns_xt, from Florian Westphal. 6) Enable ebtables hooks in initns on demand, from Florian. 7) Allow to filter conntrack netlink dump per status bits, from Florian Westphal. 8) Register x_tables hooks in initns on demand, from Florian. 9) Remove queue_handler from per-netns structure, again from Florian. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -238,9 +238,6 @@ struct xt_table {
|
|||||||
u_int8_t af; /* address/protocol family */
|
u_int8_t af; /* address/protocol family */
|
||||||
int priority; /* hook order */
|
int priority; /* hook order */
|
||||||
|
|
||||||
/* called when table is needed in the given netns */
|
|
||||||
int (*table_init)(struct net *net);
|
|
||||||
|
|
||||||
/* A unique name... */
|
/* A unique name... */
|
||||||
const char name[XT_TABLE_MAXNAMELEN];
|
const char name[XT_TABLE_MAXNAMELEN];
|
||||||
};
|
};
|
||||||
@@ -452,6 +449,9 @@ xt_get_per_cpu_counter(struct xt_counters *cnt, unsigned int cpu)
|
|||||||
|
|
||||||
struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, nf_hookfn *);
|
struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, nf_hookfn *);
|
||||||
|
|
||||||
|
int xt_register_template(const struct xt_table *t, int(*table_init)(struct net *net));
|
||||||
|
void xt_unregister_template(const struct xt_table *t);
|
||||||
|
|
||||||
#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
|
#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
|
||||||
#include <net/compat.h>
|
#include <net/compat.h>
|
||||||
|
|
||||||
|
|||||||
@@ -127,4 +127,6 @@ static inline bool ebt_invalid_target(int target)
|
|||||||
return (target < -NUM_STANDARD_TARGETS || target >= 0);
|
return (target < -NUM_STANDARD_TARGETS || target >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ebt_register_template(const struct ebt_table *t, int(*table_init)(struct net *net));
|
||||||
|
void ebt_unregister_template(const struct ebt_table *t);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include <net/netns/ieee802154_6lowpan.h>
|
#include <net/netns/ieee802154_6lowpan.h>
|
||||||
#include <net/netns/sctp.h>
|
#include <net/netns/sctp.h>
|
||||||
#include <net/netns/netfilter.h>
|
#include <net/netns/netfilter.h>
|
||||||
#include <net/netns/x_tables.h>
|
|
||||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||||
#include <net/netns/conntrack.h>
|
#include <net/netns/conntrack.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -133,7 +132,6 @@ struct net {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_NETFILTER
|
#ifdef CONFIG_NETFILTER
|
||||||
struct netns_nf nf;
|
struct netns_nf nf;
|
||||||
struct netns_xt xt;
|
|
||||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||||
struct netns_ct ct;
|
struct netns_ct ct;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ struct nf_queue_handler {
|
|||||||
void (*nf_hook_drop)(struct net *net);
|
void (*nf_hook_drop)(struct net *net);
|
||||||
};
|
};
|
||||||
|
|
||||||
void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh);
|
void nf_register_queue_handler(const struct nf_queue_handler *qh);
|
||||||
void nf_unregister_queue_handler(struct net *net);
|
void nf_unregister_queue_handler(void);
|
||||||
void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
|
void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
|
||||||
|
|
||||||
void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
|
void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ struct netns_nf {
|
|||||||
#if defined CONFIG_PROC_FS
|
#if defined CONFIG_PROC_FS
|
||||||
struct proc_dir_entry *proc_netfilter;
|
struct proc_dir_entry *proc_netfilter;
|
||||||
#endif
|
#endif
|
||||||
const struct nf_queue_handler __rcu *queue_handler;
|
|
||||||
const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO];
|
const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO];
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
struct ctl_table_header *nf_log_dir_header;
|
struct ctl_table_header *nf_log_dir_header;
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
#ifndef __NETNS_X_TABLES_H
|
|
||||||
#define __NETNS_X_TABLES_H
|
|
||||||
|
|
||||||
#include <linux/list.h>
|
|
||||||
#include <linux/netfilter_defs.h>
|
|
||||||
|
|
||||||
struct netns_xt {
|
|
||||||
bool notrack_deprecated_warning;
|
|
||||||
bool clusterip_deprecated_warning;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
@@ -56,6 +56,7 @@ enum ctattr_type {
|
|||||||
CTA_LABELS_MASK,
|
CTA_LABELS_MASK,
|
||||||
CTA_SYNPROXY,
|
CTA_SYNPROXY,
|
||||||
CTA_FILTER,
|
CTA_FILTER,
|
||||||
|
CTA_STATUS_MASK,
|
||||||
__CTA_MAX
|
__CTA_MAX
|
||||||
};
|
};
|
||||||
#define CTA_MAX (__CTA_MAX - 1)
|
#define CTA_MAX (__CTA_MAX - 1)
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ static const struct nf_hook_ops ebt_ops_broute = {
|
|||||||
.priority = NF_BR_PRI_FIRST,
|
.priority = NF_BR_PRI_FIRST,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __net_init broute_net_init(struct net *net)
|
static int broute_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
return ebt_register_table(net, &broute_table, &ebt_ops_broute);
|
return ebt_register_table(net, &broute_table, &ebt_ops_broute);
|
||||||
}
|
}
|
||||||
@@ -114,19 +114,30 @@ static void __net_exit broute_net_exit(struct net *net)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct pernet_operations broute_net_ops = {
|
static struct pernet_operations broute_net_ops = {
|
||||||
.init = broute_net_init,
|
|
||||||
.exit = broute_net_exit,
|
.exit = broute_net_exit,
|
||||||
.pre_exit = broute_net_pre_exit,
|
.pre_exit = broute_net_pre_exit,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init ebtable_broute_init(void)
|
static int __init ebtable_broute_init(void)
|
||||||
{
|
{
|
||||||
return register_pernet_subsys(&broute_net_ops);
|
int ret = ebt_register_template(&broute_table, broute_table_init);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = register_pernet_subsys(&broute_net_ops);
|
||||||
|
if (ret) {
|
||||||
|
ebt_unregister_template(&broute_table);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ebtable_broute_fini(void)
|
static void __exit ebtable_broute_fini(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&broute_net_ops);
|
unregister_pernet_subsys(&broute_net_ops);
|
||||||
|
ebt_unregister_template(&broute_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(ebtable_broute_init);
|
module_init(ebtable_broute_init);
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ static const struct nf_hook_ops ebt_ops_filter[] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __net_init frame_filter_net_init(struct net *net)
|
static int frame_filter_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
return ebt_register_table(net, &frame_filter, ebt_ops_filter);
|
return ebt_register_table(net, &frame_filter, ebt_ops_filter);
|
||||||
}
|
}
|
||||||
@@ -102,19 +102,30 @@ static void __net_exit frame_filter_net_exit(struct net *net)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct pernet_operations frame_filter_net_ops = {
|
static struct pernet_operations frame_filter_net_ops = {
|
||||||
.init = frame_filter_net_init,
|
|
||||||
.exit = frame_filter_net_exit,
|
.exit = frame_filter_net_exit,
|
||||||
.pre_exit = frame_filter_net_pre_exit,
|
.pre_exit = frame_filter_net_pre_exit,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init ebtable_filter_init(void)
|
static int __init ebtable_filter_init(void)
|
||||||
{
|
{
|
||||||
return register_pernet_subsys(&frame_filter_net_ops);
|
int ret = ebt_register_template(&frame_filter, frame_filter_table_init);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = register_pernet_subsys(&frame_filter_net_ops);
|
||||||
|
if (ret) {
|
||||||
|
ebt_unregister_template(&frame_filter);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ebtable_filter_fini(void)
|
static void __exit ebtable_filter_fini(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&frame_filter_net_ops);
|
unregister_pernet_subsys(&frame_filter_net_ops);
|
||||||
|
ebt_unregister_template(&frame_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(ebtable_filter_init);
|
module_init(ebtable_filter_init);
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ static const struct nf_hook_ops ebt_ops_nat[] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __net_init frame_nat_net_init(struct net *net)
|
static int frame_nat_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
return ebt_register_table(net, &frame_nat, ebt_ops_nat);
|
return ebt_register_table(net, &frame_nat, ebt_ops_nat);
|
||||||
}
|
}
|
||||||
@@ -101,19 +101,30 @@ static void __net_exit frame_nat_net_exit(struct net *net)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct pernet_operations frame_nat_net_ops = {
|
static struct pernet_operations frame_nat_net_ops = {
|
||||||
.init = frame_nat_net_init,
|
|
||||||
.exit = frame_nat_net_exit,
|
.exit = frame_nat_net_exit,
|
||||||
.pre_exit = frame_nat_net_pre_exit,
|
.pre_exit = frame_nat_net_pre_exit,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init ebtable_nat_init(void)
|
static int __init ebtable_nat_init(void)
|
||||||
{
|
{
|
||||||
return register_pernet_subsys(&frame_nat_net_ops);
|
int ret = ebt_register_template(&frame_nat, frame_nat_table_init);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = register_pernet_subsys(&frame_nat_net_ops);
|
||||||
|
if (ret) {
|
||||||
|
ebt_unregister_template(&frame_nat);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ebtable_nat_fini(void)
|
static void __exit ebtable_nat_fini(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&frame_nat_net_ops);
|
unregister_pernet_subsys(&frame_nat_net_ops);
|
||||||
|
ebt_unregister_template(&frame_nat);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(ebtable_nat_init);
|
module_init(ebtable_nat_init);
|
||||||
|
|||||||
@@ -44,7 +44,16 @@ struct ebt_pernet {
|
|||||||
struct list_head tables;
|
struct list_head tables;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ebt_template {
|
||||||
|
struct list_head list;
|
||||||
|
char name[EBT_TABLE_MAXNAMELEN];
|
||||||
|
struct module *owner;
|
||||||
|
/* called when table is needed in the given netns */
|
||||||
|
int (*table_init)(struct net *net);
|
||||||
|
};
|
||||||
|
|
||||||
static unsigned int ebt_pernet_id __read_mostly;
|
static unsigned int ebt_pernet_id __read_mostly;
|
||||||
|
static LIST_HEAD(template_tables);
|
||||||
static DEFINE_MUTEX(ebt_mutex);
|
static DEFINE_MUTEX(ebt_mutex);
|
||||||
|
|
||||||
#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
|
#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
|
||||||
@@ -309,30 +318,57 @@ letscontinue:
|
|||||||
|
|
||||||
/* If it succeeds, returns element and locks mutex */
|
/* If it succeeds, returns element and locks mutex */
|
||||||
static inline void *
|
static inline void *
|
||||||
find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
|
find_inlist_lock_noload(struct net *net, const char *name, int *error,
|
||||||
struct mutex *mutex)
|
struct mutex *mutex)
|
||||||
{
|
{
|
||||||
struct {
|
struct ebt_pernet *ebt_net = net_generic(net, ebt_pernet_id);
|
||||||
struct list_head list;
|
struct ebt_template *tmpl;
|
||||||
char name[EBT_FUNCTION_MAXNAMELEN];
|
struct ebt_table *table;
|
||||||
} *e;
|
|
||||||
|
|
||||||
mutex_lock(mutex);
|
mutex_lock(mutex);
|
||||||
list_for_each_entry(e, head, list) {
|
list_for_each_entry(table, &ebt_net->tables, list) {
|
||||||
if (strcmp(e->name, name) == 0)
|
if (strcmp(table->name, name) == 0)
|
||||||
return e;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(tmpl, &template_tables, list) {
|
||||||
|
if (strcmp(name, tmpl->name) == 0) {
|
||||||
|
struct module *owner = tmpl->owner;
|
||||||
|
|
||||||
|
if (!try_module_get(owner))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
mutex_unlock(mutex);
|
||||||
|
|
||||||
|
*error = tmpl->table_init(net);
|
||||||
|
if (*error) {
|
||||||
|
module_put(owner);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(mutex);
|
||||||
|
module_put(owner);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(table, &ebt_net->tables, list) {
|
||||||
|
if (strcmp(table->name, name) == 0)
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
*error = -ENOENT;
|
*error = -ENOENT;
|
||||||
mutex_unlock(mutex);
|
mutex_unlock(mutex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
|
find_inlist_lock(struct net *net, const char *name, const char *prefix,
|
||||||
int *error, struct mutex *mutex)
|
int *error, struct mutex *mutex)
|
||||||
{
|
{
|
||||||
return try_then_request_module(
|
return try_then_request_module(
|
||||||
find_inlist_lock_noload(head, name, error, mutex),
|
find_inlist_lock_noload(net, name, error, mutex),
|
||||||
"%s%s", prefix, name);
|
"%s%s", prefix, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,10 +376,7 @@ static inline struct ebt_table *
|
|||||||
find_table_lock(struct net *net, const char *name, int *error,
|
find_table_lock(struct net *net, const char *name, int *error,
|
||||||
struct mutex *mutex)
|
struct mutex *mutex)
|
||||||
{
|
{
|
||||||
struct ebt_pernet *ebt_net = net_generic(net, ebt_pernet_id);
|
return find_inlist_lock(net, name, "ebtable_", error, mutex);
|
||||||
|
|
||||||
return find_inlist_lock(&ebt_net->tables, name,
|
|
||||||
"ebtable_", error, mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ebt_free_table_info(struct ebt_table_info *info)
|
static inline void ebt_free_table_info(struct ebt_table_info *info)
|
||||||
@@ -1258,6 +1291,54 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ebt_register_template(const struct ebt_table *t, int (*table_init)(struct net *net))
|
||||||
|
{
|
||||||
|
struct ebt_template *tmpl;
|
||||||
|
|
||||||
|
mutex_lock(&ebt_mutex);
|
||||||
|
list_for_each_entry(tmpl, &template_tables, list) {
|
||||||
|
if (WARN_ON_ONCE(strcmp(t->name, tmpl->name) == 0)) {
|
||||||
|
mutex_unlock(&ebt_mutex);
|
||||||
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
|
||||||
|
if (!tmpl) {
|
||||||
|
mutex_unlock(&ebt_mutex);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl->table_init = table_init;
|
||||||
|
strscpy(tmpl->name, t->name, sizeof(tmpl->name));
|
||||||
|
tmpl->owner = t->me;
|
||||||
|
list_add(&tmpl->list, &template_tables);
|
||||||
|
|
||||||
|
mutex_unlock(&ebt_mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ebt_register_template);
|
||||||
|
|
||||||
|
void ebt_unregister_template(const struct ebt_table *t)
|
||||||
|
{
|
||||||
|
struct ebt_template *tmpl;
|
||||||
|
|
||||||
|
mutex_lock(&ebt_mutex);
|
||||||
|
list_for_each_entry(tmpl, &template_tables, list) {
|
||||||
|
if (strcmp(t->name, tmpl->name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list_del(&tmpl->list);
|
||||||
|
mutex_unlock(&ebt_mutex);
|
||||||
|
kfree(tmpl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&ebt_mutex);
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ebt_unregister_template);
|
||||||
|
|
||||||
static struct ebt_table *__ebt_find_table(struct net *net, const char *name)
|
static struct ebt_table *__ebt_find_table(struct net *net, const char *name)
|
||||||
{
|
{
|
||||||
struct ebt_pernet *ebt_net = net_generic(net, ebt_pernet_id);
|
struct ebt_pernet *ebt_net = net_generic(net, ebt_pernet_id);
|
||||||
|
|||||||
@@ -18,15 +18,12 @@ MODULE_DESCRIPTION("arptables filter table");
|
|||||||
#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
|
#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
|
||||||
(1 << NF_ARP_FORWARD))
|
(1 << NF_ARP_FORWARD))
|
||||||
|
|
||||||
static int __net_init arptable_filter_table_init(struct net *net);
|
|
||||||
|
|
||||||
static const struct xt_table packet_filter = {
|
static const struct xt_table packet_filter = {
|
||||||
.name = "filter",
|
.name = "filter",
|
||||||
.valid_hooks = FILTER_VALID_HOOKS,
|
.valid_hooks = FILTER_VALID_HOOKS,
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_ARP,
|
.af = NFPROTO_ARP,
|
||||||
.priority = NF_IP_PRI_FILTER,
|
.priority = NF_IP_PRI_FILTER,
|
||||||
.table_init = arptable_filter_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The work comes in here from netfilter.c */
|
/* The work comes in here from netfilter.c */
|
||||||
@@ -39,7 +36,7 @@ arptable_filter_hook(void *priv, struct sk_buff *skb,
|
|||||||
|
|
||||||
static struct nf_hook_ops *arpfilter_ops __read_mostly;
|
static struct nf_hook_ops *arpfilter_ops __read_mostly;
|
||||||
|
|
||||||
static int __net_init arptable_filter_table_init(struct net *net)
|
static int arptable_filter_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct arpt_replace *repl;
|
struct arpt_replace *repl;
|
||||||
int err;
|
int err;
|
||||||
@@ -69,30 +66,32 @@ static struct pernet_operations arptable_filter_net_ops = {
|
|||||||
|
|
||||||
static int __init arptable_filter_init(void)
|
static int __init arptable_filter_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = xt_register_template(&packet_filter,
|
||||||
|
arptable_filter_table_init);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
arpfilter_ops = xt_hook_ops_alloc(&packet_filter, arptable_filter_hook);
|
arpfilter_ops = xt_hook_ops_alloc(&packet_filter, arptable_filter_hook);
|
||||||
if (IS_ERR(arpfilter_ops))
|
if (IS_ERR(arpfilter_ops)) {
|
||||||
|
xt_unregister_template(&packet_filter);
|
||||||
return PTR_ERR(arpfilter_ops);
|
return PTR_ERR(arpfilter_ops);
|
||||||
|
}
|
||||||
|
|
||||||
ret = register_pernet_subsys(&arptable_filter_net_ops);
|
ret = register_pernet_subsys(&arptable_filter_net_ops);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
xt_unregister_template(&packet_filter);
|
||||||
kfree(arpfilter_ops);
|
kfree(arpfilter_ops);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = arptable_filter_table_init(&init_net);
|
|
||||||
if (ret) {
|
|
||||||
unregister_pernet_subsys(&arptable_filter_net_ops);
|
|
||||||
kfree(arpfilter_ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit arptable_filter_fini(void)
|
static void __exit arptable_filter_fini(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&arptable_filter_net_ops);
|
unregister_pernet_subsys(&arptable_filter_net_ops);
|
||||||
|
xt_unregister_template(&packet_filter);
|
||||||
kfree(arpfilter_ops);
|
kfree(arpfilter_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,11 +66,22 @@ struct clusterip_net {
|
|||||||
/* lock protects the configs list */
|
/* lock protects the configs list */
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
|
||||||
|
bool clusterip_deprecated_warning;
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
struct proc_dir_entry *procdir;
|
struct proc_dir_entry *procdir;
|
||||||
/* mutex protects the config->pde*/
|
/* mutex protects the config->pde*/
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
#endif
|
#endif
|
||||||
|
unsigned int hook_users;
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned int clusterip_arp_mangle(void *priv, struct sk_buff *skb, const struct nf_hook_state *state);
|
||||||
|
|
||||||
|
static const struct nf_hook_ops cip_arp_ops = {
|
||||||
|
.hook = clusterip_arp_mangle,
|
||||||
|
.pf = NFPROTO_ARP,
|
||||||
|
.hooknum = NF_ARP_OUT,
|
||||||
|
.priority = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int clusterip_net_id __read_mostly;
|
static unsigned int clusterip_net_id __read_mostly;
|
||||||
@@ -458,6 +469,7 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
|||||||
static int clusterip_tg_check(const struct xt_tgchk_param *par)
|
static int clusterip_tg_check(const struct xt_tgchk_param *par)
|
||||||
{
|
{
|
||||||
struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
|
struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
|
||||||
|
struct clusterip_net *cn = clusterip_pernet(par->net);
|
||||||
const struct ipt_entry *e = par->entryinfo;
|
const struct ipt_entry *e = par->entryinfo;
|
||||||
struct clusterip_config *config;
|
struct clusterip_config *config;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
@@ -467,6 +479,9 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cn->hook_users == UINT_MAX)
|
||||||
|
return -EOVERFLOW;
|
||||||
|
|
||||||
if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP &&
|
if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP &&
|
||||||
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
|
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
|
||||||
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
|
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
|
||||||
@@ -517,10 +532,23 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!par->net->xt.clusterip_deprecated_warning) {
|
if (cn->hook_users == 0) {
|
||||||
|
ret = nf_register_net_hook(par->net, &cip_arp_ops);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
clusterip_config_entry_put(config);
|
||||||
|
clusterip_config_put(config);
|
||||||
|
nf_ct_netns_put(par->net, par->family);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cn->hook_users++;
|
||||||
|
|
||||||
|
if (!cn->clusterip_deprecated_warning) {
|
||||||
pr_info("ipt_CLUSTERIP is deprecated and it will removed soon, "
|
pr_info("ipt_CLUSTERIP is deprecated and it will removed soon, "
|
||||||
"use xt_cluster instead\n");
|
"use xt_cluster instead\n");
|
||||||
par->net->xt.clusterip_deprecated_warning = true;
|
cn->clusterip_deprecated_warning = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cipinfo->config = config;
|
cipinfo->config = config;
|
||||||
@@ -531,6 +559,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
|
|||||||
static void clusterip_tg_destroy(const struct xt_tgdtor_param *par)
|
static void clusterip_tg_destroy(const struct xt_tgdtor_param *par)
|
||||||
{
|
{
|
||||||
const struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
|
const struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
|
||||||
|
struct clusterip_net *cn = clusterip_pernet(par->net);
|
||||||
|
|
||||||
/* if no more entries are referencing the config, remove it
|
/* if no more entries are referencing the config, remove it
|
||||||
* from the list and destroy the proc entry */
|
* from the list and destroy the proc entry */
|
||||||
@@ -539,6 +568,10 @@ static void clusterip_tg_destroy(const struct xt_tgdtor_param *par)
|
|||||||
clusterip_config_put(cipinfo->config);
|
clusterip_config_put(cipinfo->config);
|
||||||
|
|
||||||
nf_ct_netns_put(par->net, par->family);
|
nf_ct_netns_put(par->net, par->family);
|
||||||
|
cn->hook_users--;
|
||||||
|
|
||||||
|
if (cn->hook_users == 0)
|
||||||
|
nf_unregister_net_hook(par->net, &cip_arp_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
|
#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
|
||||||
@@ -602,9 +635,8 @@ static void arp_print(struct arp_payload *payload)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
arp_mangle(void *priv,
|
clusterip_arp_mangle(void *priv, struct sk_buff *skb,
|
||||||
struct sk_buff *skb,
|
const struct nf_hook_state *state)
|
||||||
const struct nf_hook_state *state)
|
|
||||||
{
|
{
|
||||||
struct arphdr *arp = arp_hdr(skb);
|
struct arphdr *arp = arp_hdr(skb);
|
||||||
struct arp_payload *payload;
|
struct arp_payload *payload;
|
||||||
@@ -654,13 +686,6 @@ arp_mangle(void *priv,
|
|||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct nf_hook_ops cip_arp_ops = {
|
|
||||||
.hook = arp_mangle,
|
|
||||||
.pf = NFPROTO_ARP,
|
|
||||||
.hooknum = NF_ARP_OUT,
|
|
||||||
.priority = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* PROC DIR HANDLING
|
* PROC DIR HANDLING
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
@@ -817,20 +842,14 @@ static const struct proc_ops clusterip_proc_ops = {
|
|||||||
static int clusterip_net_init(struct net *net)
|
static int clusterip_net_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct clusterip_net *cn = clusterip_pernet(net);
|
struct clusterip_net *cn = clusterip_pernet(net);
|
||||||
int ret;
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&cn->configs);
|
INIT_LIST_HEAD(&cn->configs);
|
||||||
|
|
||||||
spin_lock_init(&cn->lock);
|
spin_lock_init(&cn->lock);
|
||||||
|
|
||||||
ret = nf_register_net_hook(net, &cip_arp_ops);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
cn->procdir = proc_mkdir("ipt_CLUSTERIP", net->proc_net);
|
cn->procdir = proc_mkdir("ipt_CLUSTERIP", net->proc_net);
|
||||||
if (!cn->procdir) {
|
if (!cn->procdir) {
|
||||||
nf_unregister_net_hook(net, &cip_arp_ops);
|
|
||||||
pr_err("Unable to proc dir entry\n");
|
pr_err("Unable to proc dir entry\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
@@ -850,7 +869,6 @@ static void clusterip_net_exit(struct net *net)
|
|||||||
cn->procdir = NULL;
|
cn->procdir = NULL;
|
||||||
mutex_unlock(&cn->mutex);
|
mutex_unlock(&cn->mutex);
|
||||||
#endif
|
#endif
|
||||||
nf_unregister_net_hook(net, &cip_arp_ops);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pernet_operations clusterip_net_ops = {
|
static struct pernet_operations clusterip_net_ops = {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ MODULE_DESCRIPTION("iptables filter table");
|
|||||||
#define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \
|
#define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \
|
||||||
(1 << NF_INET_FORWARD) | \
|
(1 << NF_INET_FORWARD) | \
|
||||||
(1 << NF_INET_LOCAL_OUT))
|
(1 << NF_INET_LOCAL_OUT))
|
||||||
static int __net_init iptable_filter_table_init(struct net *net);
|
|
||||||
|
|
||||||
static const struct xt_table packet_filter = {
|
static const struct xt_table packet_filter = {
|
||||||
.name = "filter",
|
.name = "filter",
|
||||||
@@ -27,7 +26,6 @@ static const struct xt_table packet_filter = {
|
|||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV4,
|
.af = NFPROTO_IPV4,
|
||||||
.priority = NF_IP_PRI_FILTER,
|
.priority = NF_IP_PRI_FILTER,
|
||||||
.table_init = iptable_filter_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
@@ -43,7 +41,7 @@ static struct nf_hook_ops *filter_ops __read_mostly;
|
|||||||
static bool forward __read_mostly = true;
|
static bool forward __read_mostly = true;
|
||||||
module_param(forward, bool, 0000);
|
module_param(forward, bool, 0000);
|
||||||
|
|
||||||
static int __net_init iptable_filter_table_init(struct net *net)
|
static int iptable_filter_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct ipt_replace *repl;
|
struct ipt_replace *repl;
|
||||||
int err;
|
int err;
|
||||||
@@ -62,7 +60,7 @@ static int __net_init iptable_filter_table_init(struct net *net)
|
|||||||
|
|
||||||
static int __net_init iptable_filter_net_init(struct net *net)
|
static int __net_init iptable_filter_net_init(struct net *net)
|
||||||
{
|
{
|
||||||
if (net == &init_net || !forward)
|
if (!forward)
|
||||||
return iptable_filter_table_init(net);
|
return iptable_filter_table_init(net);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -86,22 +84,32 @@ static struct pernet_operations iptable_filter_net_ops = {
|
|||||||
|
|
||||||
static int __init iptable_filter_init(void)
|
static int __init iptable_filter_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = xt_register_template(&packet_filter,
|
||||||
|
iptable_filter_table_init);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
filter_ops = xt_hook_ops_alloc(&packet_filter, iptable_filter_hook);
|
filter_ops = xt_hook_ops_alloc(&packet_filter, iptable_filter_hook);
|
||||||
if (IS_ERR(filter_ops))
|
if (IS_ERR(filter_ops)) {
|
||||||
|
xt_unregister_template(&packet_filter);
|
||||||
return PTR_ERR(filter_ops);
|
return PTR_ERR(filter_ops);
|
||||||
|
}
|
||||||
|
|
||||||
ret = register_pernet_subsys(&iptable_filter_net_ops);
|
ret = register_pernet_subsys(&iptable_filter_net_ops);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
xt_unregister_template(&packet_filter);
|
||||||
kfree(filter_ops);
|
kfree(filter_ops);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit iptable_filter_fini(void)
|
static void __exit iptable_filter_fini(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&iptable_filter_net_ops);
|
unregister_pernet_subsys(&iptable_filter_net_ops);
|
||||||
|
xt_unregister_template(&packet_filter);
|
||||||
kfree(filter_ops);
|
kfree(filter_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,15 +25,12 @@ MODULE_DESCRIPTION("iptables mangle table");
|
|||||||
(1 << NF_INET_LOCAL_OUT) | \
|
(1 << NF_INET_LOCAL_OUT) | \
|
||||||
(1 << NF_INET_POST_ROUTING))
|
(1 << NF_INET_POST_ROUTING))
|
||||||
|
|
||||||
static int __net_init iptable_mangle_table_init(struct net *net);
|
|
||||||
|
|
||||||
static const struct xt_table packet_mangler = {
|
static const struct xt_table packet_mangler = {
|
||||||
.name = "mangle",
|
.name = "mangle",
|
||||||
.valid_hooks = MANGLE_VALID_HOOKS,
|
.valid_hooks = MANGLE_VALID_HOOKS,
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV4,
|
.af = NFPROTO_IPV4,
|
||||||
.priority = NF_IP_PRI_MANGLE,
|
.priority = NF_IP_PRI_MANGLE,
|
||||||
.table_init = iptable_mangle_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
@@ -83,7 +80,7 @@ iptable_mangle_hook(void *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct nf_hook_ops *mangle_ops __read_mostly;
|
static struct nf_hook_ops *mangle_ops __read_mostly;
|
||||||
static int __net_init iptable_mangle_table_init(struct net *net)
|
static int iptable_mangle_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct ipt_replace *repl;
|
struct ipt_replace *repl;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -113,32 +110,30 @@ static struct pernet_operations iptable_mangle_net_ops = {
|
|||||||
|
|
||||||
static int __init iptable_mangle_init(void)
|
static int __init iptable_mangle_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = xt_register_template(&packet_mangler,
|
||||||
|
iptable_mangle_table_init);
|
||||||
|
|
||||||
mangle_ops = xt_hook_ops_alloc(&packet_mangler, iptable_mangle_hook);
|
mangle_ops = xt_hook_ops_alloc(&packet_mangler, iptable_mangle_hook);
|
||||||
if (IS_ERR(mangle_ops)) {
|
if (IS_ERR(mangle_ops)) {
|
||||||
|
xt_unregister_template(&packet_mangler);
|
||||||
ret = PTR_ERR(mangle_ops);
|
ret = PTR_ERR(mangle_ops);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = register_pernet_subsys(&iptable_mangle_net_ops);
|
ret = register_pernet_subsys(&iptable_mangle_net_ops);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
xt_unregister_template(&packet_mangler);
|
||||||
kfree(mangle_ops);
|
kfree(mangle_ops);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iptable_mangle_table_init(&init_net);
|
|
||||||
if (ret) {
|
|
||||||
unregister_pernet_subsys(&iptable_mangle_net_ops);
|
|
||||||
kfree(mangle_ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit iptable_mangle_fini(void)
|
static void __exit iptable_mangle_fini(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&iptable_mangle_net_ops);
|
unregister_pernet_subsys(&iptable_mangle_net_ops);
|
||||||
|
xt_unregister_template(&packet_mangler);
|
||||||
kfree(mangle_ops);
|
kfree(mangle_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ struct iptable_nat_pernet {
|
|||||||
struct nf_hook_ops *nf_nat_ops;
|
struct nf_hook_ops *nf_nat_ops;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __net_init iptable_nat_table_init(struct net *net);
|
|
||||||
|
|
||||||
static unsigned int iptable_nat_net_id __read_mostly;
|
static unsigned int iptable_nat_net_id __read_mostly;
|
||||||
|
|
||||||
static const struct xt_table nf_nat_ipv4_table = {
|
static const struct xt_table nf_nat_ipv4_table = {
|
||||||
@@ -29,7 +27,6 @@ static const struct xt_table nf_nat_ipv4_table = {
|
|||||||
(1 << NF_INET_LOCAL_IN),
|
(1 << NF_INET_LOCAL_IN),
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV4,
|
.af = NFPROTO_IPV4,
|
||||||
.table_init = iptable_nat_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int iptable_nat_do_chain(void *priv,
|
static unsigned int iptable_nat_do_chain(void *priv,
|
||||||
@@ -113,7 +110,7 @@ static void ipt_nat_unregister_lookups(struct net *net)
|
|||||||
kfree(ops);
|
kfree(ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __net_init iptable_nat_table_init(struct net *net)
|
static int iptable_nat_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct ipt_replace *repl;
|
struct ipt_replace *repl;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -155,20 +152,25 @@ static struct pernet_operations iptable_nat_net_ops = {
|
|||||||
|
|
||||||
static int __init iptable_nat_init(void)
|
static int __init iptable_nat_init(void)
|
||||||
{
|
{
|
||||||
int ret = register_pernet_subsys(&iptable_nat_net_ops);
|
int ret = xt_register_template(&nf_nat_ipv4_table,
|
||||||
|
iptable_nat_table_init);
|
||||||
|
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = iptable_nat_table_init(&init_net);
|
ret = register_pernet_subsys(&iptable_nat_net_ops);
|
||||||
if (ret)
|
if (ret < 0) {
|
||||||
unregister_pernet_subsys(&iptable_nat_net_ops);
|
xt_unregister_template(&nf_nat_ipv4_table);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit iptable_nat_exit(void)
|
static void __exit iptable_nat_exit(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&iptable_nat_net_ops);
|
unregister_pernet_subsys(&iptable_nat_net_ops);
|
||||||
|
xt_unregister_template(&nf_nat_ipv4_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(iptable_nat_init);
|
module_init(iptable_nat_init);
|
||||||
|
|||||||
@@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
|
#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
|
||||||
|
|
||||||
static int __net_init iptable_raw_table_init(struct net *net);
|
|
||||||
|
|
||||||
static bool raw_before_defrag __read_mostly;
|
static bool raw_before_defrag __read_mostly;
|
||||||
MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
|
MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
|
||||||
module_param(raw_before_defrag, bool, 0000);
|
module_param(raw_before_defrag, bool, 0000);
|
||||||
@@ -24,7 +22,6 @@ static const struct xt_table packet_raw = {
|
|||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV4,
|
.af = NFPROTO_IPV4,
|
||||||
.priority = NF_IP_PRI_RAW,
|
.priority = NF_IP_PRI_RAW,
|
||||||
.table_init = iptable_raw_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct xt_table packet_raw_before_defrag = {
|
static const struct xt_table packet_raw_before_defrag = {
|
||||||
@@ -33,7 +30,6 @@ static const struct xt_table packet_raw_before_defrag = {
|
|||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV4,
|
.af = NFPROTO_IPV4,
|
||||||
.priority = NF_IP_PRI_RAW_BEFORE_DEFRAG,
|
.priority = NF_IP_PRI_RAW_BEFORE_DEFRAG,
|
||||||
.table_init = iptable_raw_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The work comes in here from netfilter.c. */
|
/* The work comes in here from netfilter.c. */
|
||||||
@@ -89,22 +85,24 @@ static int __init iptable_raw_init(void)
|
|||||||
pr_info("Enabling raw table before defrag\n");
|
pr_info("Enabling raw table before defrag\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = xt_register_template(table,
|
||||||
|
iptable_raw_table_init);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
rawtable_ops = xt_hook_ops_alloc(table, iptable_raw_hook);
|
rawtable_ops = xt_hook_ops_alloc(table, iptable_raw_hook);
|
||||||
if (IS_ERR(rawtable_ops))
|
if (IS_ERR(rawtable_ops)) {
|
||||||
|
xt_unregister_template(table);
|
||||||
return PTR_ERR(rawtable_ops);
|
return PTR_ERR(rawtable_ops);
|
||||||
|
}
|
||||||
|
|
||||||
ret = register_pernet_subsys(&iptable_raw_net_ops);
|
ret = register_pernet_subsys(&iptable_raw_net_ops);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
xt_unregister_template(table);
|
||||||
kfree(rawtable_ops);
|
kfree(rawtable_ops);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iptable_raw_table_init(&init_net);
|
|
||||||
if (ret) {
|
|
||||||
unregister_pernet_subsys(&iptable_raw_net_ops);
|
|
||||||
kfree(rawtable_ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +110,7 @@ static void __exit iptable_raw_fini(void)
|
|||||||
{
|
{
|
||||||
unregister_pernet_subsys(&iptable_raw_net_ops);
|
unregister_pernet_subsys(&iptable_raw_net_ops);
|
||||||
kfree(rawtable_ops);
|
kfree(rawtable_ops);
|
||||||
|
xt_unregister_template(&packet_raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(iptable_raw_init);
|
module_init(iptable_raw_init);
|
||||||
|
|||||||
@@ -25,15 +25,12 @@ MODULE_DESCRIPTION("iptables security table, for MAC rules");
|
|||||||
(1 << NF_INET_FORWARD) | \
|
(1 << NF_INET_FORWARD) | \
|
||||||
(1 << NF_INET_LOCAL_OUT)
|
(1 << NF_INET_LOCAL_OUT)
|
||||||
|
|
||||||
static int __net_init iptable_security_table_init(struct net *net);
|
|
||||||
|
|
||||||
static const struct xt_table security_table = {
|
static const struct xt_table security_table = {
|
||||||
.name = "security",
|
.name = "security",
|
||||||
.valid_hooks = SECURITY_VALID_HOOKS,
|
.valid_hooks = SECURITY_VALID_HOOKS,
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV4,
|
.af = NFPROTO_IPV4,
|
||||||
.priority = NF_IP_PRI_SECURITY,
|
.priority = NF_IP_PRI_SECURITY,
|
||||||
.table_init = iptable_security_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
@@ -45,7 +42,7 @@ iptable_security_hook(void *priv, struct sk_buff *skb,
|
|||||||
|
|
||||||
static struct nf_hook_ops *sectbl_ops __read_mostly;
|
static struct nf_hook_ops *sectbl_ops __read_mostly;
|
||||||
|
|
||||||
static int __net_init iptable_security_table_init(struct net *net)
|
static int iptable_security_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct ipt_replace *repl;
|
struct ipt_replace *repl;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -75,24 +72,25 @@ static struct pernet_operations iptable_security_net_ops = {
|
|||||||
|
|
||||||
static int __init iptable_security_init(void)
|
static int __init iptable_security_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = xt_register_template(&security_table,
|
||||||
|
iptable_security_table_init);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
sectbl_ops = xt_hook_ops_alloc(&security_table, iptable_security_hook);
|
sectbl_ops = xt_hook_ops_alloc(&security_table, iptable_security_hook);
|
||||||
if (IS_ERR(sectbl_ops))
|
if (IS_ERR(sectbl_ops)) {
|
||||||
|
xt_unregister_template(&security_table);
|
||||||
return PTR_ERR(sectbl_ops);
|
return PTR_ERR(sectbl_ops);
|
||||||
|
}
|
||||||
|
|
||||||
ret = register_pernet_subsys(&iptable_security_net_ops);
|
ret = register_pernet_subsys(&iptable_security_net_ops);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
xt_unregister_template(&security_table);
|
||||||
kfree(sectbl_ops);
|
kfree(sectbl_ops);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iptable_security_table_init(&init_net);
|
|
||||||
if (ret) {
|
|
||||||
unregister_pernet_subsys(&iptable_security_net_ops);
|
|
||||||
kfree(sectbl_ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +98,7 @@ static void __exit iptable_security_fini(void)
|
|||||||
{
|
{
|
||||||
unregister_pernet_subsys(&iptable_security_net_ops);
|
unregister_pernet_subsys(&iptable_security_net_ops);
|
||||||
kfree(sectbl_ops);
|
kfree(sectbl_ops);
|
||||||
|
xt_unregister_template(&security_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(iptable_security_init);
|
module_init(iptable_security_init);
|
||||||
|
|||||||
@@ -19,15 +19,12 @@ MODULE_DESCRIPTION("ip6tables filter table");
|
|||||||
(1 << NF_INET_FORWARD) | \
|
(1 << NF_INET_FORWARD) | \
|
||||||
(1 << NF_INET_LOCAL_OUT))
|
(1 << NF_INET_LOCAL_OUT))
|
||||||
|
|
||||||
static int __net_init ip6table_filter_table_init(struct net *net);
|
|
||||||
|
|
||||||
static const struct xt_table packet_filter = {
|
static const struct xt_table packet_filter = {
|
||||||
.name = "filter",
|
.name = "filter",
|
||||||
.valid_hooks = FILTER_VALID_HOOKS,
|
.valid_hooks = FILTER_VALID_HOOKS,
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV6,
|
.af = NFPROTO_IPV6,
|
||||||
.priority = NF_IP6_PRI_FILTER,
|
.priority = NF_IP6_PRI_FILTER,
|
||||||
.table_init = ip6table_filter_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The work comes in here from netfilter.c. */
|
/* The work comes in here from netfilter.c. */
|
||||||
@@ -44,7 +41,7 @@ static struct nf_hook_ops *filter_ops __read_mostly;
|
|||||||
static bool forward = true;
|
static bool forward = true;
|
||||||
module_param(forward, bool, 0000);
|
module_param(forward, bool, 0000);
|
||||||
|
|
||||||
static int __net_init ip6table_filter_table_init(struct net *net)
|
static int ip6table_filter_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct ip6t_replace *repl;
|
struct ip6t_replace *repl;
|
||||||
int err;
|
int err;
|
||||||
@@ -63,7 +60,7 @@ static int __net_init ip6table_filter_table_init(struct net *net)
|
|||||||
|
|
||||||
static int __net_init ip6table_filter_net_init(struct net *net)
|
static int __net_init ip6table_filter_net_init(struct net *net)
|
||||||
{
|
{
|
||||||
if (net == &init_net || !forward)
|
if (!forward)
|
||||||
return ip6table_filter_table_init(net);
|
return ip6table_filter_table_init(net);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -87,15 +84,24 @@ static struct pernet_operations ip6table_filter_net_ops = {
|
|||||||
|
|
||||||
static int __init ip6table_filter_init(void)
|
static int __init ip6table_filter_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = xt_register_template(&packet_filter,
|
||||||
|
ip6table_filter_table_init);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
filter_ops = xt_hook_ops_alloc(&packet_filter, ip6table_filter_hook);
|
filter_ops = xt_hook_ops_alloc(&packet_filter, ip6table_filter_hook);
|
||||||
if (IS_ERR(filter_ops))
|
if (IS_ERR(filter_ops)) {
|
||||||
|
xt_unregister_template(&packet_filter);
|
||||||
return PTR_ERR(filter_ops);
|
return PTR_ERR(filter_ops);
|
||||||
|
}
|
||||||
|
|
||||||
ret = register_pernet_subsys(&ip6table_filter_net_ops);
|
ret = register_pernet_subsys(&ip6table_filter_net_ops);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
xt_unregister_template(&packet_filter);
|
||||||
kfree(filter_ops);
|
kfree(filter_ops);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -103,6 +109,7 @@ static int __init ip6table_filter_init(void)
|
|||||||
static void __exit ip6table_filter_fini(void)
|
static void __exit ip6table_filter_fini(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&ip6table_filter_net_ops);
|
unregister_pernet_subsys(&ip6table_filter_net_ops);
|
||||||
|
xt_unregister_template(&packet_filter);
|
||||||
kfree(filter_ops);
|
kfree(filter_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,15 +20,12 @@ MODULE_DESCRIPTION("ip6tables mangle table");
|
|||||||
(1 << NF_INET_LOCAL_OUT) | \
|
(1 << NF_INET_LOCAL_OUT) | \
|
||||||
(1 << NF_INET_POST_ROUTING))
|
(1 << NF_INET_POST_ROUTING))
|
||||||
|
|
||||||
static int __net_init ip6table_mangle_table_init(struct net *net);
|
|
||||||
|
|
||||||
static const struct xt_table packet_mangler = {
|
static const struct xt_table packet_mangler = {
|
||||||
.name = "mangle",
|
.name = "mangle",
|
||||||
.valid_hooks = MANGLE_VALID_HOOKS,
|
.valid_hooks = MANGLE_VALID_HOOKS,
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV6,
|
.af = NFPROTO_IPV6,
|
||||||
.priority = NF_IP6_PRI_MANGLE,
|
.priority = NF_IP6_PRI_MANGLE,
|
||||||
.table_init = ip6table_mangle_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
@@ -76,7 +73,7 @@ ip6table_mangle_hook(void *priv, struct sk_buff *skb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct nf_hook_ops *mangle_ops __read_mostly;
|
static struct nf_hook_ops *mangle_ops __read_mostly;
|
||||||
static int __net_init ip6table_mangle_table_init(struct net *net)
|
static int ip6table_mangle_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct ip6t_replace *repl;
|
struct ip6t_replace *repl;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -106,29 +103,32 @@ static struct pernet_operations ip6table_mangle_net_ops = {
|
|||||||
|
|
||||||
static int __init ip6table_mangle_init(void)
|
static int __init ip6table_mangle_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = xt_register_template(&packet_mangler,
|
||||||
|
ip6table_mangle_table_init);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
mangle_ops = xt_hook_ops_alloc(&packet_mangler, ip6table_mangle_hook);
|
mangle_ops = xt_hook_ops_alloc(&packet_mangler, ip6table_mangle_hook);
|
||||||
if (IS_ERR(mangle_ops))
|
if (IS_ERR(mangle_ops)) {
|
||||||
|
xt_unregister_template(&packet_mangler);
|
||||||
return PTR_ERR(mangle_ops);
|
return PTR_ERR(mangle_ops);
|
||||||
|
}
|
||||||
|
|
||||||
ret = register_pernet_subsys(&ip6table_mangle_net_ops);
|
ret = register_pernet_subsys(&ip6table_mangle_net_ops);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
xt_unregister_template(&packet_mangler);
|
||||||
kfree(mangle_ops);
|
kfree(mangle_ops);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ip6table_mangle_table_init(&init_net);
|
|
||||||
if (ret) {
|
|
||||||
unregister_pernet_subsys(&ip6table_mangle_net_ops);
|
|
||||||
kfree(mangle_ops);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ip6table_mangle_fini(void)
|
static void __exit ip6table_mangle_fini(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&ip6table_mangle_net_ops);
|
unregister_pernet_subsys(&ip6table_mangle_net_ops);
|
||||||
|
xt_unregister_template(&packet_mangler);
|
||||||
kfree(mangle_ops);
|
kfree(mangle_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ struct ip6table_nat_pernet {
|
|||||||
struct nf_hook_ops *nf_nat_ops;
|
struct nf_hook_ops *nf_nat_ops;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __net_init ip6table_nat_table_init(struct net *net);
|
|
||||||
|
|
||||||
static unsigned int ip6table_nat_net_id __read_mostly;
|
static unsigned int ip6table_nat_net_id __read_mostly;
|
||||||
|
|
||||||
static const struct xt_table nf_nat_ipv6_table = {
|
static const struct xt_table nf_nat_ipv6_table = {
|
||||||
@@ -31,7 +29,6 @@ static const struct xt_table nf_nat_ipv6_table = {
|
|||||||
(1 << NF_INET_LOCAL_IN),
|
(1 << NF_INET_LOCAL_IN),
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV6,
|
.af = NFPROTO_IPV6,
|
||||||
.table_init = ip6table_nat_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int ip6table_nat_do_chain(void *priv,
|
static unsigned int ip6table_nat_do_chain(void *priv,
|
||||||
@@ -115,7 +112,7 @@ static void ip6t_nat_unregister_lookups(struct net *net)
|
|||||||
kfree(ops);
|
kfree(ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __net_init ip6table_nat_table_init(struct net *net)
|
static int ip6table_nat_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct ip6t_replace *repl;
|
struct ip6t_replace *repl;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -157,20 +154,23 @@ static struct pernet_operations ip6table_nat_net_ops = {
|
|||||||
|
|
||||||
static int __init ip6table_nat_init(void)
|
static int __init ip6table_nat_init(void)
|
||||||
{
|
{
|
||||||
int ret = register_pernet_subsys(&ip6table_nat_net_ops);
|
int ret = xt_register_template(&nf_nat_ipv6_table,
|
||||||
|
ip6table_nat_table_init);
|
||||||
|
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = ip6table_nat_table_init(&init_net);
|
ret = register_pernet_subsys(&ip6table_nat_net_ops);
|
||||||
if (ret)
|
if (ret)
|
||||||
unregister_pernet_subsys(&ip6table_nat_net_ops);
|
xt_unregister_template(&nf_nat_ipv6_table);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ip6table_nat_exit(void)
|
static void __exit ip6table_nat_exit(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&ip6table_nat_net_ops);
|
unregister_pernet_subsys(&ip6table_nat_net_ops);
|
||||||
|
xt_unregister_template(&nf_nat_ipv6_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(ip6table_nat_init);
|
module_init(ip6table_nat_init);
|
||||||
|
|||||||
@@ -11,8 +11,6 @@
|
|||||||
|
|
||||||
#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
|
#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
|
||||||
|
|
||||||
static int __net_init ip6table_raw_table_init(struct net *net);
|
|
||||||
|
|
||||||
static bool raw_before_defrag __read_mostly;
|
static bool raw_before_defrag __read_mostly;
|
||||||
MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
|
MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
|
||||||
module_param(raw_before_defrag, bool, 0000);
|
module_param(raw_before_defrag, bool, 0000);
|
||||||
@@ -23,7 +21,6 @@ static const struct xt_table packet_raw = {
|
|||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV6,
|
.af = NFPROTO_IPV6,
|
||||||
.priority = NF_IP6_PRI_RAW,
|
.priority = NF_IP6_PRI_RAW,
|
||||||
.table_init = ip6table_raw_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct xt_table packet_raw_before_defrag = {
|
static const struct xt_table packet_raw_before_defrag = {
|
||||||
@@ -32,7 +29,6 @@ static const struct xt_table packet_raw_before_defrag = {
|
|||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV6,
|
.af = NFPROTO_IPV6,
|
||||||
.priority = NF_IP6_PRI_RAW_BEFORE_DEFRAG,
|
.priority = NF_IP6_PRI_RAW_BEFORE_DEFRAG,
|
||||||
.table_init = ip6table_raw_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The work comes in here from netfilter.c. */
|
/* The work comes in here from netfilter.c. */
|
||||||
@@ -45,7 +41,7 @@ ip6table_raw_hook(void *priv, struct sk_buff *skb,
|
|||||||
|
|
||||||
static struct nf_hook_ops *rawtable_ops __read_mostly;
|
static struct nf_hook_ops *rawtable_ops __read_mostly;
|
||||||
|
|
||||||
static int __net_init ip6table_raw_table_init(struct net *net)
|
static int ip6table_raw_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct ip6t_replace *repl;
|
struct ip6t_replace *repl;
|
||||||
const struct xt_table *table = &packet_raw;
|
const struct xt_table *table = &packet_raw;
|
||||||
@@ -79,37 +75,39 @@ static struct pernet_operations ip6table_raw_net_ops = {
|
|||||||
|
|
||||||
static int __init ip6table_raw_init(void)
|
static int __init ip6table_raw_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
const struct xt_table *table = &packet_raw;
|
const struct xt_table *table = &packet_raw;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (raw_before_defrag) {
|
if (raw_before_defrag) {
|
||||||
table = &packet_raw_before_defrag;
|
table = &packet_raw_before_defrag;
|
||||||
|
|
||||||
pr_info("Enabling raw table before defrag\n");
|
pr_info("Enabling raw table before defrag\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = xt_register_template(table, ip6table_raw_table_init);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* Register hooks */
|
/* Register hooks */
|
||||||
rawtable_ops = xt_hook_ops_alloc(table, ip6table_raw_hook);
|
rawtable_ops = xt_hook_ops_alloc(table, ip6table_raw_hook);
|
||||||
if (IS_ERR(rawtable_ops))
|
if (IS_ERR(rawtable_ops)) {
|
||||||
|
xt_unregister_template(table);
|
||||||
return PTR_ERR(rawtable_ops);
|
return PTR_ERR(rawtable_ops);
|
||||||
|
}
|
||||||
|
|
||||||
ret = register_pernet_subsys(&ip6table_raw_net_ops);
|
ret = register_pernet_subsys(&ip6table_raw_net_ops);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
kfree(rawtable_ops);
|
kfree(rawtable_ops);
|
||||||
|
xt_unregister_template(table);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ip6table_raw_table_init(&init_net);
|
|
||||||
if (ret) {
|
|
||||||
unregister_pernet_subsys(&ip6table_raw_net_ops);
|
|
||||||
kfree(rawtable_ops);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ip6table_raw_fini(void)
|
static void __exit ip6table_raw_fini(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&ip6table_raw_net_ops);
|
unregister_pernet_subsys(&ip6table_raw_net_ops);
|
||||||
|
xt_unregister_template(&packet_raw);
|
||||||
kfree(rawtable_ops);
|
kfree(rawtable_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,15 +24,12 @@ MODULE_DESCRIPTION("ip6tables security table, for MAC rules");
|
|||||||
(1 << NF_INET_FORWARD) | \
|
(1 << NF_INET_FORWARD) | \
|
||||||
(1 << NF_INET_LOCAL_OUT)
|
(1 << NF_INET_LOCAL_OUT)
|
||||||
|
|
||||||
static int __net_init ip6table_security_table_init(struct net *net);
|
|
||||||
|
|
||||||
static const struct xt_table security_table = {
|
static const struct xt_table security_table = {
|
||||||
.name = "security",
|
.name = "security",
|
||||||
.valid_hooks = SECURITY_VALID_HOOKS,
|
.valid_hooks = SECURITY_VALID_HOOKS,
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
.af = NFPROTO_IPV6,
|
.af = NFPROTO_IPV6,
|
||||||
.priority = NF_IP6_PRI_SECURITY,
|
.priority = NF_IP6_PRI_SECURITY,
|
||||||
.table_init = ip6table_security_table_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
@@ -44,7 +41,7 @@ ip6table_security_hook(void *priv, struct sk_buff *skb,
|
|||||||
|
|
||||||
static struct nf_hook_ops *sectbl_ops __read_mostly;
|
static struct nf_hook_ops *sectbl_ops __read_mostly;
|
||||||
|
|
||||||
static int __net_init ip6table_security_table_init(struct net *net)
|
static int ip6table_security_table_init(struct net *net)
|
||||||
{
|
{
|
||||||
struct ip6t_replace *repl;
|
struct ip6t_replace *repl;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -74,29 +71,32 @@ static struct pernet_operations ip6table_security_net_ops = {
|
|||||||
|
|
||||||
static int __init ip6table_security_init(void)
|
static int __init ip6table_security_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = xt_register_template(&security_table,
|
||||||
|
ip6table_security_table_init);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
sectbl_ops = xt_hook_ops_alloc(&security_table, ip6table_security_hook);
|
sectbl_ops = xt_hook_ops_alloc(&security_table, ip6table_security_hook);
|
||||||
if (IS_ERR(sectbl_ops))
|
if (IS_ERR(sectbl_ops)) {
|
||||||
|
xt_unregister_template(&security_table);
|
||||||
return PTR_ERR(sectbl_ops);
|
return PTR_ERR(sectbl_ops);
|
||||||
|
}
|
||||||
|
|
||||||
ret = register_pernet_subsys(&ip6table_security_net_ops);
|
ret = register_pernet_subsys(&ip6table_security_net_ops);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
kfree(sectbl_ops);
|
kfree(sectbl_ops);
|
||||||
|
xt_unregister_template(&security_table);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ip6table_security_table_init(&init_net);
|
|
||||||
if (ret) {
|
|
||||||
unregister_pernet_subsys(&ip6table_security_net_ops);
|
|
||||||
kfree(sectbl_ops);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit ip6table_security_fini(void)
|
static void __exit ip6table_security_fini(void)
|
||||||
{
|
{
|
||||||
unregister_pernet_subsys(&ip6table_security_net_ops);
|
unregister_pernet_subsys(&ip6table_security_net_ops);
|
||||||
|
xt_unregister_template(&security_table);
|
||||||
kfree(sectbl_ops);
|
kfree(sectbl_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -852,6 +852,11 @@ static int ctnetlink_done(struct netlink_callback *cb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ctnetlink_filter_u32 {
|
||||||
|
u32 val;
|
||||||
|
u32 mask;
|
||||||
|
};
|
||||||
|
|
||||||
struct ctnetlink_filter {
|
struct ctnetlink_filter {
|
||||||
u8 family;
|
u8 family;
|
||||||
|
|
||||||
@@ -862,10 +867,8 @@ struct ctnetlink_filter {
|
|||||||
struct nf_conntrack_tuple reply;
|
struct nf_conntrack_tuple reply;
|
||||||
struct nf_conntrack_zone zone;
|
struct nf_conntrack_zone zone;
|
||||||
|
|
||||||
struct {
|
struct ctnetlink_filter_u32 mark;
|
||||||
u_int32_t val;
|
struct ctnetlink_filter_u32 status;
|
||||||
u_int32_t mask;
|
|
||||||
} mark;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = {
|
static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = {
|
||||||
@@ -907,6 +910,46 @@ static int ctnetlink_parse_tuple_filter(const struct nlattr * const cda[],
|
|||||||
struct nf_conntrack_zone *zone,
|
struct nf_conntrack_zone *zone,
|
||||||
u_int32_t flags);
|
u_int32_t flags);
|
||||||
|
|
||||||
|
static int ctnetlink_filter_parse_mark(struct ctnetlink_filter_u32 *mark,
|
||||||
|
const struct nlattr * const cda[])
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_NF_CONNTRACK_MARK
|
||||||
|
if (cda[CTA_MARK]) {
|
||||||
|
mark->val = ntohl(nla_get_be32(cda[CTA_MARK]));
|
||||||
|
|
||||||
|
if (cda[CTA_MARK_MASK])
|
||||||
|
mark->mask = ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
|
||||||
|
else
|
||||||
|
mark->mask = 0xffffffff;
|
||||||
|
} else if (cda[CTA_MARK_MASK]) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ctnetlink_filter_parse_status(struct ctnetlink_filter_u32 *status,
|
||||||
|
const struct nlattr * const cda[])
|
||||||
|
{
|
||||||
|
if (cda[CTA_STATUS]) {
|
||||||
|
status->val = ntohl(nla_get_be32(cda[CTA_STATUS]));
|
||||||
|
if (cda[CTA_STATUS_MASK])
|
||||||
|
status->mask = ntohl(nla_get_be32(cda[CTA_STATUS_MASK]));
|
||||||
|
else
|
||||||
|
status->mask = status->val;
|
||||||
|
|
||||||
|
/* status->val == 0? always true, else always false. */
|
||||||
|
if (status->mask == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
} else if (cda[CTA_STATUS_MASK]) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CTA_STATUS is NLA_U32, if this fires UAPI needs to be extended */
|
||||||
|
BUILD_BUG_ON(__IPS_MAX_BIT >= 32);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct ctnetlink_filter *
|
static struct ctnetlink_filter *
|
||||||
ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
|
ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
|
||||||
{
|
{
|
||||||
@@ -924,18 +967,14 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
|
|||||||
|
|
||||||
filter->family = family;
|
filter->family = family;
|
||||||
|
|
||||||
#ifdef CONFIG_NF_CONNTRACK_MARK
|
err = ctnetlink_filter_parse_mark(&filter->mark, cda);
|
||||||
if (cda[CTA_MARK]) {
|
if (err)
|
||||||
filter->mark.val = ntohl(nla_get_be32(cda[CTA_MARK]));
|
|
||||||
if (cda[CTA_MARK_MASK])
|
|
||||||
filter->mark.mask = ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
|
|
||||||
else
|
|
||||||
filter->mark.mask = 0xffffffff;
|
|
||||||
} else if (cda[CTA_MARK_MASK]) {
|
|
||||||
err = -EINVAL;
|
|
||||||
goto err_filter;
|
goto err_filter;
|
||||||
}
|
|
||||||
#endif
|
err = ctnetlink_filter_parse_status(&filter->status, cda);
|
||||||
|
if (err)
|
||||||
|
goto err_filter;
|
||||||
|
|
||||||
if (!cda[CTA_FILTER])
|
if (!cda[CTA_FILTER])
|
||||||
return filter;
|
return filter;
|
||||||
|
|
||||||
@@ -989,7 +1028,7 @@ err_filter:
|
|||||||
|
|
||||||
static bool ctnetlink_needs_filter(u8 family, const struct nlattr * const *cda)
|
static bool ctnetlink_needs_filter(u8 family, const struct nlattr * const *cda)
|
||||||
{
|
{
|
||||||
return family || cda[CTA_MARK] || cda[CTA_FILTER];
|
return family || cda[CTA_MARK] || cda[CTA_FILTER] || cda[CTA_STATUS];
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ctnetlink_start(struct netlink_callback *cb)
|
static int ctnetlink_start(struct netlink_callback *cb)
|
||||||
@@ -1082,6 +1121,7 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
|
|||||||
{
|
{
|
||||||
struct ctnetlink_filter *filter = data;
|
struct ctnetlink_filter *filter = data;
|
||||||
struct nf_conntrack_tuple *tuple;
|
struct nf_conntrack_tuple *tuple;
|
||||||
|
u32 status;
|
||||||
|
|
||||||
if (filter == NULL)
|
if (filter == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1113,6 +1153,9 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
|
|||||||
if ((ct->mark & filter->mark.mask) != filter->mark.val)
|
if ((ct->mark & filter->mark.mask) != filter->mark.val)
|
||||||
goto ignore_entry;
|
goto ignore_entry;
|
||||||
#endif
|
#endif
|
||||||
|
status = (u32)READ_ONCE(ct->status);
|
||||||
|
if ((status & filter->status.mask) != filter->status.val)
|
||||||
|
goto ignore_entry;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return 1;
|
return 1;
|
||||||
@@ -1495,6 +1538,7 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
|
|||||||
[CTA_LABELS_MASK] = { .type = NLA_BINARY,
|
[CTA_LABELS_MASK] = { .type = NLA_BINARY,
|
||||||
.len = NF_CT_LABELS_MAX_SIZE },
|
.len = NF_CT_LABELS_MAX_SIZE },
|
||||||
[CTA_FILTER] = { .type = NLA_NESTED },
|
[CTA_FILTER] = { .type = NLA_NESTED },
|
||||||
|
[CTA_STATUS_MASK] = { .type = NLA_U32 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data)
|
static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data)
|
||||||
|
|||||||
@@ -180,15 +180,10 @@ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
|
|||||||
|
|
||||||
static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
|
static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
|
||||||
{
|
{
|
||||||
const struct nf_conntrack_l4proto *l4proto;
|
|
||||||
struct net *net = nf_ct_net(ct);
|
struct net *net = nf_ct_net(ct);
|
||||||
int l4num = nf_ct_protonum(ct);
|
int l4num = nf_ct_protonum(ct);
|
||||||
unsigned int timeout;
|
unsigned int timeout;
|
||||||
|
|
||||||
l4proto = nf_ct_l4proto_find(l4num);
|
|
||||||
if (!l4proto)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (l4num == IPPROTO_TCP) {
|
if (l4num == IPPROTO_TCP) {
|
||||||
struct nf_tcp_net *tn = nf_tcp_pernet(net);
|
struct nf_tcp_net *tn = nf_tcp_pernet(net);
|
||||||
|
|
||||||
@@ -273,15 +268,10 @@ static const struct rhashtable_params nf_flow_offload_rhash_params = {
|
|||||||
|
|
||||||
unsigned long flow_offload_get_timeout(struct flow_offload *flow)
|
unsigned long flow_offload_get_timeout(struct flow_offload *flow)
|
||||||
{
|
{
|
||||||
const struct nf_conntrack_l4proto *l4proto;
|
|
||||||
unsigned long timeout = NF_FLOW_TIMEOUT;
|
unsigned long timeout = NF_FLOW_TIMEOUT;
|
||||||
struct net *net = nf_ct_net(flow->ct);
|
struct net *net = nf_ct_net(flow->ct);
|
||||||
int l4num = nf_ct_protonum(flow->ct);
|
int l4num = nf_ct_protonum(flow->ct);
|
||||||
|
|
||||||
l4proto = nf_ct_l4proto_find(l4num);
|
|
||||||
if (!l4proto)
|
|
||||||
return timeout;
|
|
||||||
|
|
||||||
if (l4num == IPPROTO_TCP) {
|
if (l4num == IPPROTO_TCP) {
|
||||||
struct nf_tcp_net *tn = nf_tcp_pernet(net);
|
struct nf_tcp_net *tn = nf_tcp_pernet(net);
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include "nf_internals.h"
|
#include "nf_internals.h"
|
||||||
|
|
||||||
|
static const struct nf_queue_handler __rcu *nf_queue_handler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hook for nfnetlink_queue to register its queue handler.
|
* Hook for nfnetlink_queue to register its queue handler.
|
||||||
* We do this so that most of the NFQUEUE code can be modular.
|
* We do this so that most of the NFQUEUE code can be modular.
|
||||||
@@ -29,20 +31,18 @@
|
|||||||
* receives, no matter what.
|
* receives, no matter what.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* return EBUSY when somebody else is registered, return EEXIST if the
|
void nf_register_queue_handler(const struct nf_queue_handler *qh)
|
||||||
* same handler is registered, return 0 in case of success. */
|
|
||||||
void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh)
|
|
||||||
{
|
{
|
||||||
/* should never happen, we only have one queueing backend in kernel */
|
/* should never happen, we only have one queueing backend in kernel */
|
||||||
WARN_ON(rcu_access_pointer(net->nf.queue_handler));
|
WARN_ON(rcu_access_pointer(nf_queue_handler));
|
||||||
rcu_assign_pointer(net->nf.queue_handler, qh);
|
rcu_assign_pointer(nf_queue_handler, qh);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nf_register_queue_handler);
|
EXPORT_SYMBOL(nf_register_queue_handler);
|
||||||
|
|
||||||
/* The caller must flush their queue before this */
|
/* The caller must flush their queue before this */
|
||||||
void nf_unregister_queue_handler(struct net *net)
|
void nf_unregister_queue_handler(void)
|
||||||
{
|
{
|
||||||
RCU_INIT_POINTER(net->nf.queue_handler, NULL);
|
RCU_INIT_POINTER(nf_queue_handler, NULL);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nf_unregister_queue_handler);
|
EXPORT_SYMBOL(nf_unregister_queue_handler);
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ void nf_queue_nf_hook_drop(struct net *net)
|
|||||||
const struct nf_queue_handler *qh;
|
const struct nf_queue_handler *qh;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
qh = rcu_dereference(net->nf.queue_handler);
|
qh = rcu_dereference(nf_queue_handler);
|
||||||
if (qh)
|
if (qh)
|
||||||
qh->nf_hook_drop(net);
|
qh->nf_hook_drop(net);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
@@ -149,12 +149,11 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
|
|||||||
{
|
{
|
||||||
struct nf_queue_entry *entry = NULL;
|
struct nf_queue_entry *entry = NULL;
|
||||||
const struct nf_queue_handler *qh;
|
const struct nf_queue_handler *qh;
|
||||||
struct net *net = state->net;
|
|
||||||
unsigned int route_key_size;
|
unsigned int route_key_size;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* QUEUE == DROP if no one is waiting, to be safe. */
|
/* QUEUE == DROP if no one is waiting, to be safe. */
|
||||||
qh = rcu_dereference(net->nf.queue_handler);
|
qh = rcu_dereference(nf_queue_handler);
|
||||||
if (!qh)
|
if (!qh)
|
||||||
return -ESRCH;
|
return -ESRCH;
|
||||||
|
|
||||||
|
|||||||
@@ -951,6 +951,16 @@ static void nfqnl_nf_hook_drop(struct net *net)
|
|||||||
struct nfnl_queue_net *q = nfnl_queue_pernet(net);
|
struct nfnl_queue_net *q = nfnl_queue_pernet(net);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* This function is also called on net namespace error unwind,
|
||||||
|
* when pernet_ops->init() failed and ->exit() functions of the
|
||||||
|
* previous pernet_ops gets called.
|
||||||
|
*
|
||||||
|
* This may result in a call to nfqnl_nf_hook_drop() before
|
||||||
|
* struct nfnl_queue_net was allocated.
|
||||||
|
*/
|
||||||
|
if (!q)
|
||||||
|
return;
|
||||||
|
|
||||||
for (i = 0; i < INSTANCE_BUCKETS; i++) {
|
for (i = 0; i < INSTANCE_BUCKETS; i++) {
|
||||||
struct nfqnl_instance *inst;
|
struct nfqnl_instance *inst;
|
||||||
struct hlist_head *head = &q->instance_table[i];
|
struct hlist_head *head = &q->instance_table[i];
|
||||||
@@ -1502,7 +1512,6 @@ static int __net_init nfnl_queue_net_init(struct net *net)
|
|||||||
&nfqnl_seq_ops, sizeof(struct iter_state)))
|
&nfqnl_seq_ops, sizeof(struct iter_state)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
#endif
|
#endif
|
||||||
nf_register_queue_handler(net, &nfqh);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1511,7 +1520,6 @@ static void __net_exit nfnl_queue_net_exit(struct net *net)
|
|||||||
struct nfnl_queue_net *q = nfnl_queue_pernet(net);
|
struct nfnl_queue_net *q = nfnl_queue_pernet(net);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
nf_unregister_queue_handler(net);
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter);
|
remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter);
|
||||||
#endif
|
#endif
|
||||||
@@ -1555,6 +1563,8 @@ static int __init nfnetlink_queue_init(void)
|
|||||||
goto cleanup_netlink_subsys;
|
goto cleanup_netlink_subsys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nf_register_queue_handler(&nfqh);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
cleanup_netlink_subsys:
|
cleanup_netlink_subsys:
|
||||||
@@ -1568,6 +1578,7 @@ out:
|
|||||||
|
|
||||||
static void __exit nfnetlink_queue_fini(void)
|
static void __exit nfnetlink_queue_fini(void)
|
||||||
{
|
{
|
||||||
|
nf_unregister_queue_handler();
|
||||||
unregister_netdevice_notifier(&nfqnl_dev_notifier);
|
unregister_netdevice_notifier(&nfqnl_dev_notifier);
|
||||||
nfnetlink_subsys_unregister(&nfqnl_subsys);
|
nfnetlink_subsys_unregister(&nfqnl_subsys);
|
||||||
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
||||||
|
|||||||
@@ -683,14 +683,12 @@ static int nfnl_compat_get_rcu(struct sk_buff *skb,
|
|||||||
goto out_put;
|
goto out_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
ret = nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (ret > 0)
|
|
||||||
ret = 0;
|
|
||||||
out_put:
|
out_put:
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
module_put(THIS_MODULE);
|
module_put(THIS_MODULE);
|
||||||
return ret == -EAGAIN ? -ENOBUFS : ret;
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct nla_policy nfnl_compat_policy_get[NFTA_COMPAT_MAX+1] = {
|
static const struct nla_policy nfnl_compat_policy_get[NFTA_COMPAT_MAX+1] = {
|
||||||
|
|||||||
@@ -39,6 +39,20 @@ MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
|
|||||||
#define XT_PCPU_BLOCK_SIZE 4096
|
#define XT_PCPU_BLOCK_SIZE 4096
|
||||||
#define XT_MAX_TABLE_SIZE (512 * 1024 * 1024)
|
#define XT_MAX_TABLE_SIZE (512 * 1024 * 1024)
|
||||||
|
|
||||||
|
struct xt_template {
|
||||||
|
struct list_head list;
|
||||||
|
|
||||||
|
/* called when table is needed in the given netns */
|
||||||
|
int (*table_init)(struct net *net);
|
||||||
|
|
||||||
|
struct module *me;
|
||||||
|
|
||||||
|
/* A unique name... */
|
||||||
|
char name[XT_TABLE_MAXNAMELEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct list_head xt_templates[NFPROTO_NUMPROTO];
|
||||||
|
|
||||||
struct xt_pernet {
|
struct xt_pernet {
|
||||||
struct list_head tables[NFPROTO_NUMPROTO];
|
struct list_head tables[NFPROTO_NUMPROTO];
|
||||||
};
|
};
|
||||||
@@ -1221,48 +1235,43 @@ struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
|
|||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
struct xt_pernet *xt_net = net_generic(net, xt_pernet_id);
|
struct xt_pernet *xt_net = net_generic(net, xt_pernet_id);
|
||||||
struct xt_table *t, *found = NULL;
|
struct module *owner = NULL;
|
||||||
|
struct xt_template *tmpl;
|
||||||
|
struct xt_table *t;
|
||||||
|
|
||||||
mutex_lock(&xt[af].mutex);
|
mutex_lock(&xt[af].mutex);
|
||||||
list_for_each_entry(t, &xt_net->tables[af], list)
|
list_for_each_entry(t, &xt_net->tables[af], list)
|
||||||
if (strcmp(t->name, name) == 0 && try_module_get(t->me))
|
if (strcmp(t->name, name) == 0 && try_module_get(t->me))
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
if (net == &init_net)
|
/* Table doesn't exist in this netns, check larval list */
|
||||||
goto out;
|
list_for_each_entry(tmpl, &xt_templates[af], list) {
|
||||||
|
|
||||||
/* Table doesn't exist in this netns, re-try init */
|
|
||||||
xt_net = net_generic(&init_net, xt_pernet_id);
|
|
||||||
list_for_each_entry(t, &xt_net->tables[af], list) {
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (strcmp(t->name, name))
|
if (strcmp(tmpl->name, name))
|
||||||
continue;
|
continue;
|
||||||
if (!try_module_get(t->me))
|
if (!try_module_get(tmpl->me))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
owner = tmpl->me;
|
||||||
|
|
||||||
mutex_unlock(&xt[af].mutex);
|
mutex_unlock(&xt[af].mutex);
|
||||||
err = t->table_init(net);
|
err = tmpl->table_init(net);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
module_put(t->me);
|
module_put(owner);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
found = t;
|
|
||||||
|
|
||||||
mutex_lock(&xt[af].mutex);
|
mutex_lock(&xt[af].mutex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
xt_net = net_generic(net, xt_pernet_id);
|
|
||||||
/* and once again: */
|
/* and once again: */
|
||||||
list_for_each_entry(t, &xt_net->tables[af], list)
|
list_for_each_entry(t, &xt_net->tables[af], list)
|
||||||
if (strcmp(t->name, name) == 0)
|
if (strcmp(t->name, name) == 0)
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
module_put(found->me);
|
module_put(owner);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&xt[af].mutex);
|
mutex_unlock(&xt[af].mutex);
|
||||||
return ERR_PTR(-ENOENT);
|
return ERR_PTR(-ENOENT);
|
||||||
@@ -1749,6 +1758,58 @@ xt_hook_ops_alloc(const struct xt_table *table, nf_hookfn *fn)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(xt_hook_ops_alloc);
|
EXPORT_SYMBOL_GPL(xt_hook_ops_alloc);
|
||||||
|
|
||||||
|
int xt_register_template(const struct xt_table *table,
|
||||||
|
int (*table_init)(struct net *net))
|
||||||
|
{
|
||||||
|
int ret = -EEXIST, af = table->af;
|
||||||
|
struct xt_template *t;
|
||||||
|
|
||||||
|
mutex_lock(&xt[af].mutex);
|
||||||
|
|
||||||
|
list_for_each_entry(t, &xt_templates[af], list) {
|
||||||
|
if (WARN_ON_ONCE(strcmp(table->name, t->name) == 0))
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = -ENOMEM;
|
||||||
|
t = kzalloc(sizeof(*t), GFP_KERNEL);
|
||||||
|
if (!t)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(sizeof(t->name) != sizeof(table->name));
|
||||||
|
|
||||||
|
strscpy(t->name, table->name, sizeof(t->name));
|
||||||
|
t->table_init = table_init;
|
||||||
|
t->me = table->me;
|
||||||
|
list_add(&t->list, &xt_templates[af]);
|
||||||
|
ret = 0;
|
||||||
|
out_unlock:
|
||||||
|
mutex_unlock(&xt[af].mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(xt_register_template);
|
||||||
|
|
||||||
|
void xt_unregister_template(const struct xt_table *table)
|
||||||
|
{
|
||||||
|
struct xt_template *t;
|
||||||
|
int af = table->af;
|
||||||
|
|
||||||
|
mutex_lock(&xt[af].mutex);
|
||||||
|
list_for_each_entry(t, &xt_templates[af], list) {
|
||||||
|
if (strcmp(table->name, t->name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list_del(&t->list);
|
||||||
|
mutex_unlock(&xt[af].mutex);
|
||||||
|
kfree(t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&xt[af].mutex);
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(xt_unregister_template);
|
||||||
|
|
||||||
int xt_proto_init(struct net *net, u_int8_t af)
|
int xt_proto_init(struct net *net, u_int8_t af)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
@@ -1937,6 +1998,7 @@ static int __init xt_init(void)
|
|||||||
#endif
|
#endif
|
||||||
INIT_LIST_HEAD(&xt[i].target);
|
INIT_LIST_HEAD(&xt[i].target);
|
||||||
INIT_LIST_HEAD(&xt[i].match);
|
INIT_LIST_HEAD(&xt[i].match);
|
||||||
|
INIT_LIST_HEAD(&xt_templates[i]);
|
||||||
}
|
}
|
||||||
rv = register_pernet_subsys(&xt_net_ops);
|
rv = register_pernet_subsys(&xt_net_ops);
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
|
|||||||
@@ -351,21 +351,10 @@ notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
|||||||
return XT_CONTINUE;
|
return XT_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int notrack_chk(const struct xt_tgchk_param *par)
|
|
||||||
{
|
|
||||||
if (!par->net->xt.notrack_deprecated_warning) {
|
|
||||||
pr_info("netfilter: NOTRACK target is deprecated, "
|
|
||||||
"use CT instead or upgrade iptables\n");
|
|
||||||
par->net->xt.notrack_deprecated_warning = true;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct xt_target notrack_tg_reg __read_mostly = {
|
static struct xt_target notrack_tg_reg __read_mostly = {
|
||||||
.name = "NOTRACK",
|
.name = "NOTRACK",
|
||||||
.revision = 0,
|
.revision = 0,
|
||||||
.family = NFPROTO_UNSPEC,
|
.family = NFPROTO_UNSPEC,
|
||||||
.checkentry = notrack_chk,
|
|
||||||
.target = notrack_tg,
|
.target = notrack_tg,
|
||||||
.table = "raw",
|
.table = "raw",
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
|
|||||||
Reference in New Issue
Block a user