Merge branch 'master' of git://1984.lsi.us.es/nf-next
This commit is contained in:
commit
d3a5ea6e21
16 changed files with 599 additions and 265 deletions
|
@ -7,6 +7,8 @@ enum cntl_msg_types {
|
|||
IPCTNL_MSG_CT_GET,
|
||||
IPCTNL_MSG_CT_DELETE,
|
||||
IPCTNL_MSG_CT_GET_CTRZERO,
|
||||
IPCTNL_MSG_CT_GET_STATS_CPU,
|
||||
IPCTNL_MSG_CT_GET_STATS,
|
||||
|
||||
IPCTNL_MSG_MAX
|
||||
};
|
||||
|
@ -15,6 +17,7 @@ enum ctnl_exp_msg_types {
|
|||
IPCTNL_MSG_EXP_NEW,
|
||||
IPCTNL_MSG_EXP_GET,
|
||||
IPCTNL_MSG_EXP_DELETE,
|
||||
IPCTNL_MSG_EXP_GET_STATS_CPU,
|
||||
|
||||
IPCTNL_MSG_EXP_MAX
|
||||
};
|
||||
|
@ -203,4 +206,39 @@ enum ctattr_secctx {
|
|||
};
|
||||
#define CTA_SECCTX_MAX (__CTA_SECCTX_MAX - 1)
|
||||
|
||||
enum ctattr_stats_cpu {
|
||||
CTA_STATS_UNSPEC,
|
||||
CTA_STATS_SEARCHED,
|
||||
CTA_STATS_FOUND,
|
||||
CTA_STATS_NEW,
|
||||
CTA_STATS_INVALID,
|
||||
CTA_STATS_IGNORE,
|
||||
CTA_STATS_DELETE,
|
||||
CTA_STATS_DELETE_LIST,
|
||||
CTA_STATS_INSERT,
|
||||
CTA_STATS_INSERT_FAILED,
|
||||
CTA_STATS_DROP,
|
||||
CTA_STATS_EARLY_DROP,
|
||||
CTA_STATS_ERROR,
|
||||
CTA_STATS_SEARCH_RESTART,
|
||||
__CTA_STATS_MAX,
|
||||
};
|
||||
#define CTA_STATS_MAX (__CTA_STATS_MAX - 1)
|
||||
|
||||
enum ctattr_stats_global {
|
||||
CTA_STATS_GLOBAL_UNSPEC,
|
||||
CTA_STATS_GLOBAL_ENTRIES,
|
||||
__CTA_STATS_GLOBAL_MAX,
|
||||
};
|
||||
#define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1)
|
||||
|
||||
enum ctattr_expect_stats {
|
||||
CTA_STATS_EXP_UNSPEC,
|
||||
CTA_STATS_EXP_NEW,
|
||||
CTA_STATS_EXP_CREATE,
|
||||
CTA_STATS_EXP_DELETE,
|
||||
__CTA_STATS_EXP_MAX,
|
||||
};
|
||||
#define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1)
|
||||
|
||||
#endif /* _IPCONNTRACK_NETLINK_H */
|
||||
|
|
|
@ -95,5 +95,6 @@ enum nfqnl_attr_config {
|
|||
/* Flags for NFQA_CFG_FLAGS */
|
||||
#define NFQA_CFG_F_FAIL_OPEN (1 << 0)
|
||||
#define NFQA_CFG_F_CONNTRACK (1 << 1)
|
||||
#define NFQA_CFG_F_MAX (1 << 2)
|
||||
|
||||
#endif /* _NFNETLINK_QUEUE_H */
|
||||
|
|
|
@ -97,7 +97,10 @@ struct nf_conntrack_l4proto {
|
|||
#endif
|
||||
int *net_id;
|
||||
/* Init l4proto pernet data */
|
||||
int (*init_net)(struct net *net);
|
||||
int (*init_net)(struct net *net, u_int16_t proto);
|
||||
|
||||
/* Return the per-net protocol part. */
|
||||
struct nf_proto_net *(*get_net_proto)(struct net *net);
|
||||
|
||||
/* Protocol name */
|
||||
const char *name;
|
||||
|
@ -124,6 +127,14 @@ extern int nf_conntrack_l4proto_register(struct net *net,
|
|||
extern void nf_conntrack_l4proto_unregister(struct net *net,
|
||||
struct nf_conntrack_l4proto *proto);
|
||||
|
||||
static inline void nf_ct_kfree_compat_sysctl_table(struct nf_proto_net *pn)
|
||||
{
|
||||
#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
|
||||
kfree(pn->ctl_compat_table);
|
||||
pn->ctl_compat_table = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Generic netlink helpers */
|
||||
extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
|
||||
const struct nf_conntrack_tuple *tuple);
|
||||
|
|
|
@ -337,34 +337,62 @@ static struct ctl_table icmp_compat_sysctl_table[] = {
|
|||
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
static int icmp_init_net(struct net *net)
|
||||
static int icmp_kmemdup_sysctl_table(struct nf_proto_net *pn,
|
||||
struct nf_icmp_net *in)
|
||||
{
|
||||
struct nf_icmp_net *in = icmp_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)in;
|
||||
in->timeout = nf_ct_icmp_timeout;
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
pn->ctl_table = kmemdup(icmp_sysctl_table,
|
||||
sizeof(icmp_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
if (!pn->ctl_table)
|
||||
return -ENOMEM;
|
||||
|
||||
pn->ctl_table[0].data = &in->timeout;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icmp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn,
|
||||
struct nf_icmp_net *in)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
|
||||
pn->ctl_compat_table = kmemdup(icmp_compat_sysctl_table,
|
||||
sizeof(icmp_compat_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
if (!pn->ctl_compat_table) {
|
||||
kfree(pn->ctl_table);
|
||||
pn->ctl_table = NULL;
|
||||
if (!pn->ctl_compat_table)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pn->ctl_compat_table[0].data = &in->timeout;
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icmp_init_net(struct net *net, u_int16_t proto)
|
||||
{
|
||||
int ret;
|
||||
struct nf_icmp_net *in = icmp_pernet(net);
|
||||
struct nf_proto_net *pn = &in->pn;
|
||||
|
||||
in->timeout = nf_ct_icmp_timeout;
|
||||
|
||||
ret = icmp_kmemdup_compat_sysctl_table(pn, in);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = icmp_kmemdup_sysctl_table(pn, in);
|
||||
if (ret < 0)
|
||||
nf_ct_kfree_compat_sysctl_table(pn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct nf_proto_net *icmp_get_net_proto(struct net *net)
|
||||
{
|
||||
return &net->ct.nf_ct_proto.icmp.pn;
|
||||
}
|
||||
|
||||
struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly =
|
||||
{
|
||||
.l3proto = PF_INET,
|
||||
|
@ -395,4 +423,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly =
|
|||
},
|
||||
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
|
||||
.init_net = icmp_init_net,
|
||||
.get_net_proto = icmp_get_net_proto,
|
||||
};
|
||||
|
|
|
@ -333,22 +333,36 @@ static struct ctl_table icmpv6_sysctl_table[] = {
|
|||
};
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
static int icmpv6_init_net(struct net *net)
|
||||
static int icmpv6_kmemdup_sysctl_table(struct nf_proto_net *pn,
|
||||
struct nf_icmp_net *in)
|
||||
{
|
||||
struct nf_icmp_net *in = icmpv6_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)in;
|
||||
in->timeout = nf_ct_icmpv6_timeout;
|
||||
#ifdef CONFIG_SYSCTL
|
||||
pn->ctl_table = kmemdup(icmpv6_sysctl_table,
|
||||
sizeof(icmpv6_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
if (!pn->ctl_table)
|
||||
return -ENOMEM;
|
||||
|
||||
pn->ctl_table[0].data = &in->timeout;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icmpv6_init_net(struct net *net, u_int16_t proto)
|
||||
{
|
||||
struct nf_icmp_net *in = icmpv6_pernet(net);
|
||||
struct nf_proto_net *pn = &in->pn;
|
||||
|
||||
in->timeout = nf_ct_icmpv6_timeout;
|
||||
|
||||
return icmpv6_kmemdup_sysctl_table(pn, in);
|
||||
}
|
||||
|
||||
static struct nf_proto_net *icmpv6_get_net_proto(struct net *net)
|
||||
{
|
||||
return &net->ct.nf_ct_proto.icmpv6.pn;
|
||||
}
|
||||
|
||||
struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
|
||||
{
|
||||
.l3proto = PF_INET6,
|
||||
|
@ -377,4 +391,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
|
|||
},
|
||||
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
|
||||
.init_net = icmpv6_init_net,
|
||||
.get_net_proto = icmpv6_get_net_proto,
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* (C) 2001 by Jay Schulist <jschlst@samba.org>
|
||||
* (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2003 by Patrick Mchardy <kaber@trash.net>
|
||||
* (C) 2005-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
* (C) 2005-2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* Initial connection tracking via netlink development funded and
|
||||
* generally made possible by Network Robots, Inc. (www.networkrobots.com)
|
||||
|
@ -1627,6 +1627,155 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_ct_stat_cpu_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
|
||||
__u16 cpu, const struct ip_conntrack_stat *st)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = pid ? NLM_F_MULTI : 0, event;
|
||||
|
||||
event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET_STATS_CPU);
|
||||
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = AF_UNSPEC;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = htons(cpu);
|
||||
|
||||
if (nla_put_be32(skb, CTA_STATS_SEARCHED, htonl(st->searched)) ||
|
||||
nla_put_be32(skb, CTA_STATS_FOUND, htonl(st->found)) ||
|
||||
nla_put_be32(skb, CTA_STATS_NEW, htonl(st->new)) ||
|
||||
nla_put_be32(skb, CTA_STATS_INVALID, htonl(st->invalid)) ||
|
||||
nla_put_be32(skb, CTA_STATS_IGNORE, htonl(st->ignore)) ||
|
||||
nla_put_be32(skb, CTA_STATS_DELETE, htonl(st->delete)) ||
|
||||
nla_put_be32(skb, CTA_STATS_DELETE_LIST, htonl(st->delete_list)) ||
|
||||
nla_put_be32(skb, CTA_STATS_INSERT, htonl(st->insert)) ||
|
||||
nla_put_be32(skb, CTA_STATS_INSERT_FAILED,
|
||||
htonl(st->insert_failed)) ||
|
||||
nla_put_be32(skb, CTA_STATS_DROP, htonl(st->drop)) ||
|
||||
nla_put_be32(skb, CTA_STATS_EARLY_DROP, htonl(st->early_drop)) ||
|
||||
nla_put_be32(skb, CTA_STATS_ERROR, htonl(st->error)) ||
|
||||
nla_put_be32(skb, CTA_STATS_SEARCH_RESTART,
|
||||
htonl(st->search_restart)))
|
||||
goto nla_put_failure;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
return skb->len;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_failure:
|
||||
nlmsg_cancel(skb, nlh);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_ct_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
int cpu;
|
||||
struct net *net = sock_net(skb->sk);
|
||||
|
||||
if (cb->args[0] == nr_cpu_ids)
|
||||
return 0;
|
||||
|
||||
for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) {
|
||||
const struct ip_conntrack_stat *st;
|
||||
|
||||
if (!cpu_possible(cpu))
|
||||
continue;
|
||||
|
||||
st = per_cpu_ptr(net->ct.stat, cpu);
|
||||
if (ctnetlink_ct_stat_cpu_fill_info(skb,
|
||||
NETLINK_CB(cb->skb).pid,
|
||||
cb->nlh->nlmsg_seq,
|
||||
cpu, st) < 0)
|
||||
break;
|
||||
}
|
||||
cb->args[0] = cpu;
|
||||
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_stat_ct_cpu(struct sock *ctnl, struct sk_buff *skb,
|
||||
const struct nlmsghdr *nlh,
|
||||
const struct nlattr * const cda[])
|
||||
{
|
||||
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
||||
struct netlink_dump_control c = {
|
||||
.dump = ctnetlink_ct_stat_cpu_dump,
|
||||
};
|
||||
return netlink_dump_start(ctnl, skb, nlh, &c);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,
|
||||
struct net *net)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = pid ? NLM_F_MULTI : 0, event;
|
||||
unsigned int nr_conntracks = atomic_read(&net->ct.count);
|
||||
|
||||
event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET_STATS);
|
||||
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = AF_UNSPEC;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
if (nla_put_be32(skb, CTA_STATS_GLOBAL_ENTRIES, htonl(nr_conntracks)))
|
||||
goto nla_put_failure;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
return skb->len;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_failure:
|
||||
nlmsg_cancel(skb, nlh);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_stat_ct(struct sock *ctnl, struct sk_buff *skb,
|
||||
const struct nlmsghdr *nlh,
|
||||
const struct nlattr * const cda[])
|
||||
{
|
||||
struct sk_buff *skb2;
|
||||
int err;
|
||||
|
||||
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (skb2 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
err = ctnetlink_stat_ct_fill_info(skb2, NETLINK_CB(skb).pid,
|
||||
nlh->nlmsg_seq,
|
||||
NFNL_MSG_TYPE(nlh->nlmsg_type),
|
||||
sock_net(skb->sk));
|
||||
if (err <= 0)
|
||||
goto free;
|
||||
|
||||
err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
|
||||
free:
|
||||
kfree_skb(skb2);
|
||||
out:
|
||||
/* this avoids a loop in nfnetlink. */
|
||||
return err == -EAGAIN ? -ENOBUFS : err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
|
||||
static size_t
|
||||
ctnetlink_nfqueue_build_size(const struct nf_conn *ct)
|
||||
|
@ -2440,6 +2589,79 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_exp_stat_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int cpu,
|
||||
const struct ip_conntrack_stat *st)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = pid ? NLM_F_MULTI : 0, event;
|
||||
|
||||
event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_EXP_GET_STATS_CPU);
|
||||
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = AF_UNSPEC;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = htons(cpu);
|
||||
|
||||
if (nla_put_be32(skb, CTA_STATS_EXP_NEW, htonl(st->expect_new)) ||
|
||||
nla_put_be32(skb, CTA_STATS_EXP_CREATE, htonl(st->expect_create)) ||
|
||||
nla_put_be32(skb, CTA_STATS_EXP_DELETE, htonl(st->expect_delete)))
|
||||
goto nla_put_failure;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
return skb->len;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_failure:
|
||||
nlmsg_cancel(skb, nlh);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_exp_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
int cpu;
|
||||
struct net *net = sock_net(skb->sk);
|
||||
|
||||
if (cb->args[0] == nr_cpu_ids)
|
||||
return 0;
|
||||
|
||||
for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) {
|
||||
const struct ip_conntrack_stat *st;
|
||||
|
||||
if (!cpu_possible(cpu))
|
||||
continue;
|
||||
|
||||
st = per_cpu_ptr(net->ct.stat, cpu);
|
||||
if (ctnetlink_exp_stat_fill_info(skb, NETLINK_CB(cb->skb).pid,
|
||||
cb->nlh->nlmsg_seq,
|
||||
cpu, st) < 0)
|
||||
break;
|
||||
}
|
||||
cb->args[0] = cpu;
|
||||
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_stat_exp_cpu(struct sock *ctnl, struct sk_buff *skb,
|
||||
const struct nlmsghdr *nlh,
|
||||
const struct nlattr * const cda[])
|
||||
{
|
||||
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
||||
struct netlink_dump_control c = {
|
||||
.dump = ctnetlink_exp_stat_cpu_dump,
|
||||
};
|
||||
return netlink_dump_start(ctnl, skb, nlh, &c);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
static struct nf_ct_event_notifier ctnl_notifier = {
|
||||
.fcn = ctnetlink_conntrack_event,
|
||||
|
@ -2463,6 +2685,8 @@ static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
|
|||
[IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack,
|
||||
.attr_count = CTA_MAX,
|
||||
.policy = ct_nla_policy },
|
||||
[IPCTNL_MSG_CT_GET_STATS_CPU] = { .call = ctnetlink_stat_ct_cpu },
|
||||
[IPCTNL_MSG_CT_GET_STATS] = { .call = ctnetlink_stat_ct },
|
||||
};
|
||||
|
||||
static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
|
||||
|
@ -2475,6 +2699,7 @@ static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
|
|||
[IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect,
|
||||
.attr_count = CTA_EXPECT_MAX,
|
||||
.policy = exp_nla_policy },
|
||||
[IPCTNL_MSG_EXP_GET_STATS_CPU] = { .call = ctnetlink_stat_exp_cpu },
|
||||
};
|
||||
|
||||
static const struct nfnetlink_subsystem ctnl_subsys = {
|
||||
|
|
|
@ -39,16 +39,13 @@ static int
|
|||
nf_ct_register_sysctl(struct net *net,
|
||||
struct ctl_table_header **header,
|
||||
const char *path,
|
||||
struct ctl_table *table,
|
||||
unsigned int *users)
|
||||
struct ctl_table *table)
|
||||
{
|
||||
if (*header == NULL) {
|
||||
*header = register_net_sysctl(net, path, table);
|
||||
if (*header == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (users != NULL)
|
||||
(*users)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -56,9 +53,9 @@ nf_ct_register_sysctl(struct net *net,
|
|||
static void
|
||||
nf_ct_unregister_sysctl(struct ctl_table_header **header,
|
||||
struct ctl_table **table,
|
||||
unsigned int *users)
|
||||
unsigned int users)
|
||||
{
|
||||
if (users != NULL && --*users > 0)
|
||||
if (users > 0)
|
||||
return;
|
||||
|
||||
unregister_net_sysctl_table(*header);
|
||||
|
@ -191,8 +188,7 @@ static int nf_ct_l3proto_register_sysctl(struct net *net,
|
|||
err = nf_ct_register_sysctl(net,
|
||||
&in->ctl_table_header,
|
||||
l3proto->ctl_table_path,
|
||||
in->ctl_table,
|
||||
NULL);
|
||||
in->ctl_table);
|
||||
if (err < 0) {
|
||||
kfree(in->ctl_table);
|
||||
in->ctl_table = NULL;
|
||||
|
@ -213,7 +209,7 @@ static void nf_ct_l3proto_unregister_sysctl(struct net *net,
|
|||
if (in->ctl_table_header != NULL)
|
||||
nf_ct_unregister_sysctl(&in->ctl_table_header,
|
||||
&in->ctl_table,
|
||||
NULL);
|
||||
0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -253,18 +249,23 @@ int nf_conntrack_l3proto_register(struct net *net,
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
if (net == &init_net)
|
||||
ret = nf_conntrack_l3proto_register_net(proto);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (proto->init_net) {
|
||||
ret = proto->init_net(net);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return nf_ct_l3proto_register_sysctl(net, proto);
|
||||
|
||||
ret = nf_ct_l3proto_register_sysctl(net, proto);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (net == &init_net) {
|
||||
ret = nf_conntrack_l3proto_register_net(proto);
|
||||
if (ret < 0)
|
||||
nf_ct_l3proto_unregister_sysctl(net, proto);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_register);
|
||||
|
||||
|
@ -302,93 +303,77 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister);
|
|||
static struct nf_proto_net *nf_ct_l4proto_net(struct net *net,
|
||||
struct nf_conntrack_l4proto *l4proto)
|
||||
{
|
||||
switch (l4proto->l4proto) {
|
||||
case IPPROTO_TCP:
|
||||
return (struct nf_proto_net *)&net->ct.nf_ct_proto.tcp;
|
||||
case IPPROTO_UDP:
|
||||
return (struct nf_proto_net *)&net->ct.nf_ct_proto.udp;
|
||||
case IPPROTO_ICMP:
|
||||
return (struct nf_proto_net *)&net->ct.nf_ct_proto.icmp;
|
||||
case IPPROTO_ICMPV6:
|
||||
return (struct nf_proto_net *)&net->ct.nf_ct_proto.icmpv6;
|
||||
case 255: /* l4proto_generic */
|
||||
return (struct nf_proto_net *)&net->ct.nf_ct_proto.generic;
|
||||
default:
|
||||
if (l4proto->net_id)
|
||||
return net_generic(net, *l4proto->net_id);
|
||||
else
|
||||
return NULL;
|
||||
if (l4proto->get_net_proto) {
|
||||
/* statically built-in protocols use static per-net */
|
||||
return l4proto->get_net_proto(net);
|
||||
} else if (l4proto->net_id) {
|
||||
/* ... and loadable protocols use dynamic per-net */
|
||||
return net_generic(net, *l4proto->net_id);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int nf_ct_l4proto_register_sysctl(struct net *net,
|
||||
struct nf_proto_net *pn,
|
||||
struct nf_conntrack_l4proto *l4proto)
|
||||
{
|
||||
int err = 0;
|
||||
struct nf_proto_net *pn = nf_ct_l4proto_net(net, l4proto);
|
||||
if (pn == NULL)
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
if (pn->ctl_table != NULL) {
|
||||
err = nf_ct_register_sysctl(net,
|
||||
&pn->ctl_table_header,
|
||||
"net/netfilter",
|
||||
pn->ctl_table,
|
||||
&pn->users);
|
||||
pn->ctl_table);
|
||||
if (err < 0) {
|
||||
if (!pn->users) {
|
||||
kfree(pn->ctl_table);
|
||||
pn->ctl_table = NULL;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
|
||||
if (l4proto->l3proto != AF_INET6 && pn->ctl_compat_table != NULL) {
|
||||
if (err < 0) {
|
||||
nf_ct_kfree_compat_sysctl_table(pn);
|
||||
goto out;
|
||||
}
|
||||
err = nf_ct_register_sysctl(net,
|
||||
&pn->ctl_compat_header,
|
||||
"net/ipv4/netfilter",
|
||||
pn->ctl_compat_table,
|
||||
NULL);
|
||||
pn->ctl_compat_table);
|
||||
if (err == 0)
|
||||
goto out;
|
||||
|
||||
kfree(pn->ctl_compat_table);
|
||||
pn->ctl_compat_table = NULL;
|
||||
nf_ct_kfree_compat_sysctl_table(pn);
|
||||
nf_ct_unregister_sysctl(&pn->ctl_table_header,
|
||||
&pn->ctl_table,
|
||||
&pn->users);
|
||||
pn->users);
|
||||
}
|
||||
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
|
||||
out:
|
||||
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
return err;
|
||||
}
|
||||
|
||||
static
|
||||
void nf_ct_l4proto_unregister_sysctl(struct net *net,
|
||||
struct nf_proto_net *pn,
|
||||
struct nf_conntrack_l4proto *l4proto)
|
||||
{
|
||||
struct nf_proto_net *pn = nf_ct_l4proto_net(net, l4proto);
|
||||
if (pn == NULL)
|
||||
return;
|
||||
#ifdef CONFIG_SYSCTL
|
||||
if (pn->ctl_table_header != NULL)
|
||||
nf_ct_unregister_sysctl(&pn->ctl_table_header,
|
||||
&pn->ctl_table,
|
||||
&pn->users);
|
||||
pn->users);
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
|
||||
if (l4proto->l3proto != AF_INET6 && pn->ctl_compat_header != NULL)
|
||||
nf_ct_unregister_sysctl(&pn->ctl_compat_header,
|
||||
&pn->ctl_compat_table,
|
||||
NULL);
|
||||
0);
|
||||
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
|
||||
#else
|
||||
pn->users--;
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
}
|
||||
|
||||
|
@ -454,19 +439,33 @@ int nf_conntrack_l4proto_register(struct net *net,
|
|||
struct nf_conntrack_l4proto *l4proto)
|
||||
{
|
||||
int ret = 0;
|
||||
if (net == &init_net)
|
||||
struct nf_proto_net *pn = NULL;
|
||||
|
||||
if (l4proto->init_net) {
|
||||
ret = l4proto->init_net(net, l4proto->l3proto);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
pn = nf_ct_l4proto_net(net, l4proto);
|
||||
if (pn == NULL)
|
||||
goto out;
|
||||
|
||||
ret = nf_ct_l4proto_register_sysctl(net, pn, l4proto);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (net == &init_net) {
|
||||
ret = nf_conntrack_l4proto_register_net(l4proto);
|
||||
if (ret < 0) {
|
||||
nf_ct_l4proto_unregister_sysctl(net, pn, l4proto);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (l4proto->init_net)
|
||||
ret = l4proto->init_net(net);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return nf_ct_l4proto_register_sysctl(net, l4proto);
|
||||
pn->users++;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register);
|
||||
|
||||
|
@ -490,10 +489,18 @@ nf_conntrack_l4proto_unregister_net(struct nf_conntrack_l4proto *l4proto)
|
|||
void nf_conntrack_l4proto_unregister(struct net *net,
|
||||
struct nf_conntrack_l4proto *l4proto)
|
||||
{
|
||||
struct nf_proto_net *pn = NULL;
|
||||
|
||||
if (net == &init_net)
|
||||
nf_conntrack_l4proto_unregister_net(l4proto);
|
||||
|
||||
nf_ct_l4proto_unregister_sysctl(net, l4proto);
|
||||
pn = nf_ct_l4proto_net(net, l4proto);
|
||||
if (pn == NULL)
|
||||
return;
|
||||
|
||||
pn->users--;
|
||||
nf_ct_l4proto_unregister_sysctl(net, pn, l4proto);
|
||||
|
||||
/* Remove all contrack entries for this protocol */
|
||||
rtnl_lock();
|
||||
nf_ct_iterate_cleanup(net, kill_l4proto, l4proto);
|
||||
|
@ -505,10 +512,15 @@ int nf_conntrack_proto_init(struct net *net)
|
|||
{
|
||||
unsigned int i;
|
||||
int err;
|
||||
err = nf_conntrack_l4proto_generic.init_net(net);
|
||||
struct nf_proto_net *pn = nf_ct_l4proto_net(net,
|
||||
&nf_conntrack_l4proto_generic);
|
||||
|
||||
err = nf_conntrack_l4proto_generic.init_net(net,
|
||||
nf_conntrack_l4proto_generic.l3proto);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = nf_ct_l4proto_register_sysctl(net,
|
||||
pn,
|
||||
&nf_conntrack_l4proto_generic);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -518,13 +530,20 @@ int nf_conntrack_proto_init(struct net *net)
|
|||
rcu_assign_pointer(nf_ct_l3protos[i],
|
||||
&nf_conntrack_l3proto_generic);
|
||||
}
|
||||
|
||||
pn->users++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nf_conntrack_proto_fini(struct net *net)
|
||||
{
|
||||
unsigned int i;
|
||||
struct nf_proto_net *pn = nf_ct_l4proto_net(net,
|
||||
&nf_conntrack_l4proto_generic);
|
||||
|
||||
pn->users--;
|
||||
nf_ct_l4proto_unregister_sysctl(net,
|
||||
pn,
|
||||
&nf_conntrack_l4proto_generic);
|
||||
if (net == &init_net) {
|
||||
/* free l3proto protocol tables */
|
||||
|
|
|
@ -387,7 +387,7 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] =
|
|||
/* this module per-net specifics */
|
||||
static int dccp_net_id __read_mostly;
|
||||
struct dccp_net {
|
||||
struct nf_proto_net np;
|
||||
struct nf_proto_net pn;
|
||||
int dccp_loose;
|
||||
unsigned int dccp_timeout[CT_DCCP_MAX + 1];
|
||||
};
|
||||
|
@ -815,16 +815,37 @@ static struct ctl_table dccp_sysctl_table[] = {
|
|||
};
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
static int dccp_init_net(struct net *net)
|
||||
static int dccp_kmemdup_sysctl_table(struct nf_proto_net *pn,
|
||||
struct dccp_net *dn)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
if (pn->ctl_table)
|
||||
return 0;
|
||||
|
||||
pn->ctl_table = kmemdup(dccp_sysctl_table,
|
||||
sizeof(dccp_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
if (!pn->ctl_table)
|
||||
return -ENOMEM;
|
||||
|
||||
pn->ctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST];
|
||||
pn->ctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND];
|
||||
pn->ctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN];
|
||||
pn->ctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN];
|
||||
pn->ctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ];
|
||||
pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
|
||||
pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
|
||||
pn->ctl_table[7].data = &dn->dccp_loose;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dccp_init_net(struct net *net, u_int16_t proto)
|
||||
{
|
||||
struct dccp_net *dn = dccp_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)dn;
|
||||
struct nf_proto_net *pn = &dn->pn;
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
if (!pn->ctl_table) {
|
||||
#else
|
||||
if (!pn->users++) {
|
||||
#endif
|
||||
if (!pn->users) {
|
||||
/* default values */
|
||||
dn->dccp_loose = 1;
|
||||
dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL;
|
||||
|
@ -834,24 +855,9 @@ static int dccp_init_net(struct net *net)
|
|||
dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ;
|
||||
dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ;
|
||||
dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL;
|
||||
#ifdef CONFIG_SYSCTL
|
||||
pn->ctl_table = kmemdup(dccp_sysctl_table,
|
||||
sizeof(dccp_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
if (!pn->ctl_table)
|
||||
return -ENOMEM;
|
||||
|
||||
pn->ctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST];
|
||||
pn->ctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND];
|
||||
pn->ctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN];
|
||||
pn->ctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN];
|
||||
pn->ctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ];
|
||||
pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
|
||||
pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
|
||||
pn->ctl_table[7].data = &dn->dccp_loose;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
|
||||
return dccp_kmemdup_sysctl_table(pn, dn);
|
||||
}
|
||||
|
||||
static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
|
||||
|
|
|
@ -135,34 +135,62 @@ static struct ctl_table generic_compat_sysctl_table[] = {
|
|||
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
static int generic_init_net(struct net *net)
|
||||
static int generic_kmemdup_sysctl_table(struct nf_proto_net *pn,
|
||||
struct nf_generic_net *gn)
|
||||
{
|
||||
struct nf_generic_net *gn = generic_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)gn;
|
||||
gn->timeout = nf_ct_generic_timeout;
|
||||
#ifdef CONFIG_SYSCTL
|
||||
pn->ctl_table = kmemdup(generic_sysctl_table,
|
||||
sizeof(generic_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
if (!pn->ctl_table)
|
||||
return -ENOMEM;
|
||||
pn->ctl_table[0].data = &gn->timeout;
|
||||
|
||||
pn->ctl_table[0].data = &gn->timeout;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int generic_kmemdup_compat_sysctl_table(struct nf_proto_net *pn,
|
||||
struct nf_generic_net *gn)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
|
||||
pn->ctl_compat_table = kmemdup(generic_compat_sysctl_table,
|
||||
sizeof(generic_compat_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
if (!pn->ctl_compat_table) {
|
||||
kfree(pn->ctl_table);
|
||||
pn->ctl_table = NULL;
|
||||
if (!pn->ctl_compat_table)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pn->ctl_compat_table[0].data = &gn->timeout;
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int generic_init_net(struct net *net, u_int16_t proto)
|
||||
{
|
||||
int ret;
|
||||
struct nf_generic_net *gn = generic_pernet(net);
|
||||
struct nf_proto_net *pn = &gn->pn;
|
||||
|
||||
gn->timeout = nf_ct_generic_timeout;
|
||||
|
||||
ret = generic_kmemdup_compat_sysctl_table(pn, gn);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = generic_kmemdup_sysctl_table(pn, gn);
|
||||
if (ret < 0)
|
||||
nf_ct_kfree_compat_sysctl_table(pn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct nf_proto_net *generic_get_net_proto(struct net *net)
|
||||
{
|
||||
return &net->ct.nf_ct_proto.generic.pn;
|
||||
}
|
||||
|
||||
struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
|
||||
{
|
||||
.l3proto = PF_UNSPEC,
|
||||
|
@ -184,4 +212,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
|
|||
},
|
||||
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
|
||||
.init_net = generic_init_net,
|
||||
.get_net_proto = generic_get_net_proto,
|
||||
};
|
||||
|
|
|
@ -348,7 +348,7 @@ gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = {
|
|||
};
|
||||
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
|
||||
|
||||
static int gre_init_net(struct net *net)
|
||||
static int gre_init_net(struct net *net, u_int16_t proto)
|
||||
{
|
||||
struct netns_proto_gre *net_gre = gre_pernet(net);
|
||||
int i;
|
||||
|
|
|
@ -707,23 +707,10 @@ static struct ctl_table sctp_compat_sysctl_table[] = {
|
|||
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
|
||||
#endif
|
||||
|
||||
static void sctp_init_net_data(struct sctp_net *sn)
|
||||
{
|
||||
int i;
|
||||
#ifdef CONFIG_SYSCTL
|
||||
if (!sn->pn.ctl_table) {
|
||||
#else
|
||||
if (!sn->pn.users++) {
|
||||
#endif
|
||||
for (i = 0; i < SCTP_CONNTRACK_MAX; i++)
|
||||
sn->timeouts[i] = sctp_timeouts[i];
|
||||
}
|
||||
}
|
||||
|
||||
static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn)
|
||||
static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn,
|
||||
struct sctp_net *sn)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
struct sctp_net *sn = (struct sctp_net *)pn;
|
||||
if (pn->ctl_table)
|
||||
return 0;
|
||||
|
||||
|
@ -744,11 +731,11 @@ static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sctp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn)
|
||||
static int sctp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn,
|
||||
struct sctp_net *sn)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
|
||||
struct sctp_net *sn = (struct sctp_net *)pn;
|
||||
pn->ctl_compat_table = kmemdup(sctp_compat_sysctl_table,
|
||||
sizeof(sctp_compat_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
|
@ -767,41 +754,33 @@ static int sctp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sctpv4_init_net(struct net *net)
|
||||
static int sctp_init_net(struct net *net, u_int16_t proto)
|
||||
{
|
||||
int ret;
|
||||
struct sctp_net *sn = sctp_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)sn;
|
||||
struct nf_proto_net *pn = &sn->pn;
|
||||
|
||||
sctp_init_net_data(sn);
|
||||
if (!pn->users) {
|
||||
int i;
|
||||
|
||||
ret = sctp_kmemdup_compat_sysctl_table(pn);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = sctp_kmemdup_sysctl_table(pn);
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
|
||||
if (ret < 0) {
|
||||
|
||||
kfree(pn->ctl_compat_table);
|
||||
pn->ctl_compat_table = NULL;
|
||||
for (i = 0; i < SCTP_CONNTRACK_MAX; i++)
|
||||
sn->timeouts[i] = sctp_timeouts[i];
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (proto == AF_INET) {
|
||||
ret = sctp_kmemdup_compat_sysctl_table(pn, sn);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = sctp_kmemdup_sysctl_table(pn, sn);
|
||||
if (ret < 0)
|
||||
nf_ct_kfree_compat_sysctl_table(pn);
|
||||
} else
|
||||
ret = sctp_kmemdup_sysctl_table(pn, sn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sctpv6_init_net(struct net *net)
|
||||
{
|
||||
struct sctp_net *sn = sctp_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)sn;
|
||||
|
||||
sctp_init_net_data(sn);
|
||||
return sctp_kmemdup_sysctl_table(pn);
|
||||
}
|
||||
|
||||
static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
|
||||
.l3proto = PF_INET,
|
||||
.l4proto = IPPROTO_SCTP,
|
||||
|
@ -833,7 +812,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
|
|||
},
|
||||
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
|
||||
.net_id = &sctp_net_id,
|
||||
.init_net = sctpv4_init_net,
|
||||
.init_net = sctp_init_net,
|
||||
};
|
||||
|
||||
static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
|
||||
|
@ -867,7 +846,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
|
|||
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
|
||||
#endif
|
||||
.net_id = &sctp_net_id,
|
||||
.init_net = sctpv6_init_net,
|
||||
.init_net = sctp_init_net,
|
||||
};
|
||||
|
||||
static int sctp_net_init(struct net *net)
|
||||
|
|
|
@ -821,7 +821,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl,
|
|||
|
||||
static unsigned int *tcp_get_timeouts(struct net *net)
|
||||
{
|
||||
return tcp_timeouts;
|
||||
return tcp_pernet(net)->timeouts;
|
||||
}
|
||||
|
||||
/* Returns verdict for packet, or -1 for invalid. */
|
||||
|
@ -1533,11 +1533,10 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
|
|||
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn)
|
||||
static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn,
|
||||
struct nf_tcp_net *tn)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
struct nf_tcp_net *tn = (struct nf_tcp_net *)pn;
|
||||
|
||||
if (pn->ctl_table)
|
||||
return 0;
|
||||
|
||||
|
@ -1564,11 +1563,11 @@ static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tcp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn)
|
||||
static int tcp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn,
|
||||
struct nf_tcp_net *tn)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
|
||||
struct nf_tcp_net *tn = (struct nf_tcp_net *)pn;
|
||||
pn->ctl_compat_table = kmemdup(tcp_compat_sysctl_table,
|
||||
sizeof(tcp_compat_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
|
@ -1593,18 +1592,15 @@ static int tcp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tcpv4_init_net(struct net *net)
|
||||
static int tcp_init_net(struct net *net, u_int16_t proto)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
struct nf_tcp_net *tn = tcp_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)tn;
|
||||
struct nf_proto_net *pn = &tn->pn;
|
||||
|
||||
if (!pn->users) {
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
if (!pn->ctl_table) {
|
||||
#else
|
||||
if (!pn->users++) {
|
||||
#endif
|
||||
for (i = 0; i < TCP_CONNTRACK_TIMEOUT_MAX; i++)
|
||||
tn->timeouts[i] = tcp_timeouts[i];
|
||||
|
||||
|
@ -1613,43 +1609,23 @@ static int tcpv4_init_net(struct net *net)
|
|||
tn->tcp_max_retrans = nf_ct_tcp_max_retrans;
|
||||
}
|
||||
|
||||
ret = tcp_kmemdup_compat_sysctl_table(pn);
|
||||
if (proto == AF_INET) {
|
||||
ret = tcp_kmemdup_compat_sysctl_table(pn, tn);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = tcp_kmemdup_sysctl_table(pn, tn);
|
||||
if (ret < 0)
|
||||
nf_ct_kfree_compat_sysctl_table(pn);
|
||||
} else
|
||||
ret = tcp_kmemdup_sysctl_table(pn, tn);
|
||||
|
||||
ret = tcp_kmemdup_sysctl_table(pn);
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
|
||||
if (ret < 0) {
|
||||
kfree(pn->ctl_compat_table);
|
||||
pn->ctl_compat_table = NULL;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tcpv6_init_net(struct net *net)
|
||||
static struct nf_proto_net *tcp_get_net_proto(struct net *net)
|
||||
{
|
||||
int i;
|
||||
struct nf_tcp_net *tn = tcp_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)tn;
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
if (!pn->ctl_table) {
|
||||
#else
|
||||
if (!pn->users++) {
|
||||
#endif
|
||||
for (i = 0; i < TCP_CONNTRACK_TIMEOUT_MAX; i++)
|
||||
tn->timeouts[i] = tcp_timeouts[i];
|
||||
tn->tcp_loose = nf_ct_tcp_loose;
|
||||
tn->tcp_be_liberal = nf_ct_tcp_be_liberal;
|
||||
tn->tcp_max_retrans = nf_ct_tcp_max_retrans;
|
||||
}
|
||||
|
||||
return tcp_kmemdup_sysctl_table(pn);
|
||||
return &net->ct.nf_ct_proto.tcp.pn;
|
||||
}
|
||||
|
||||
struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly =
|
||||
|
@ -1684,7 +1660,8 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly =
|
|||
.nla_policy = tcp_timeout_nla_policy,
|
||||
},
|
||||
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
|
||||
.init_net = tcpv4_init_net,
|
||||
.init_net = tcp_init_net,
|
||||
.get_net_proto = tcp_get_net_proto,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4);
|
||||
|
||||
|
@ -1720,6 +1697,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly =
|
|||
.nla_policy = tcp_timeout_nla_policy,
|
||||
},
|
||||
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
|
||||
.init_net = tcpv6_init_net,
|
||||
.init_net = tcp_init_net,
|
||||
.get_net_proto = tcp_get_net_proto,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp6);
|
||||
|
|
|
@ -235,10 +235,10 @@ static struct ctl_table udp_compat_sysctl_table[] = {
|
|||
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn)
|
||||
static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn,
|
||||
struct nf_udp_net *un)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
struct nf_udp_net *un = (struct nf_udp_net *)pn;
|
||||
if (pn->ctl_table)
|
||||
return 0;
|
||||
pn->ctl_table = kmemdup(udp_sysctl_table,
|
||||
|
@ -252,11 +252,11 @@ static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn)
|
||||
static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn,
|
||||
struct nf_udp_net *un)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
|
||||
struct nf_udp_net *un = (struct nf_udp_net *)pn;
|
||||
pn->ctl_compat_table = kmemdup(udp_compat_sysctl_table,
|
||||
sizeof(udp_compat_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
|
@ -270,50 +270,36 @@ static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void udp_init_net_data(struct nf_udp_net *un)
|
||||
{
|
||||
int i;
|
||||
#ifdef CONFIG_SYSCTL
|
||||
if (!un->pn.ctl_table) {
|
||||
#else
|
||||
if (!un->pn.users++) {
|
||||
#endif
|
||||
for (i = 0; i < UDP_CT_MAX; i++)
|
||||
un->timeouts[i] = udp_timeouts[i];
|
||||
}
|
||||
}
|
||||
|
||||
static int udpv4_init_net(struct net *net)
|
||||
static int udp_init_net(struct net *net, u_int16_t proto)
|
||||
{
|
||||
int ret;
|
||||
struct nf_udp_net *un = udp_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)un;
|
||||
struct nf_proto_net *pn = &un->pn;
|
||||
|
||||
udp_init_net_data(un);
|
||||
if (!pn->users) {
|
||||
int i;
|
||||
|
||||
ret = udp_kmemdup_compat_sysctl_table(pn);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = udp_kmemdup_sysctl_table(pn);
|
||||
#ifdef CONFIG_SYSCTL
|
||||
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
|
||||
if (ret < 0) {
|
||||
kfree(pn->ctl_compat_table);
|
||||
pn->ctl_compat_table = NULL;
|
||||
for (i = 0; i < UDP_CT_MAX; i++)
|
||||
un->timeouts[i] = udp_timeouts[i];
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (proto == AF_INET) {
|
||||
ret = udp_kmemdup_compat_sysctl_table(pn, un);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = udp_kmemdup_sysctl_table(pn, un);
|
||||
if (ret < 0)
|
||||
nf_ct_kfree_compat_sysctl_table(pn);
|
||||
} else
|
||||
ret = udp_kmemdup_sysctl_table(pn, un);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int udpv6_init_net(struct net *net)
|
||||
static struct nf_proto_net *udp_get_net_proto(struct net *net)
|
||||
{
|
||||
struct nf_udp_net *un = udp_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)un;
|
||||
|
||||
udp_init_net_data(un);
|
||||
return udp_kmemdup_sysctl_table(pn);
|
||||
return &net->ct.nf_ct_proto.udp.pn;
|
||||
}
|
||||
|
||||
struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
|
||||
|
@ -343,7 +329,8 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
|
|||
.nla_policy = udp_timeout_nla_policy,
|
||||
},
|
||||
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
|
||||
.init_net = udpv4_init_net,
|
||||
.init_net = udp_init_net,
|
||||
.get_net_proto = udp_get_net_proto,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4);
|
||||
|
||||
|
@ -374,6 +361,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =
|
|||
.nla_policy = udp_timeout_nla_policy,
|
||||
},
|
||||
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
|
||||
.init_net = udpv6_init_net,
|
||||
.init_net = udp_init_net,
|
||||
.get_net_proto = udp_get_net_proto,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6);
|
||||
|
|
|
@ -234,29 +234,38 @@ static struct ctl_table udplite_sysctl_table[] = {
|
|||
};
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
static int udplite_init_net(struct net *net)
|
||||
static int udplite_kmemdup_sysctl_table(struct nf_proto_net *pn,
|
||||
struct udplite_net *un)
|
||||
{
|
||||
int i;
|
||||
struct udplite_net *un = udplite_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)un;
|
||||
#ifdef CONFIG_SYSCTL
|
||||
if (!pn->ctl_table) {
|
||||
#else
|
||||
if (!pn->users++) {
|
||||
if (pn->ctl_table)
|
||||
return 0;
|
||||
|
||||
pn->ctl_table = kmemdup(udplite_sysctl_table,
|
||||
sizeof(udplite_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
if (!pn->ctl_table)
|
||||
return -ENOMEM;
|
||||
|
||||
pn->ctl_table[0].data = &un->timeouts[UDPLITE_CT_UNREPLIED];
|
||||
pn->ctl_table[1].data = &un->timeouts[UDPLITE_CT_REPLIED];
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int udplite_init_net(struct net *net, u_int16_t proto)
|
||||
{
|
||||
struct udplite_net *un = udplite_pernet(net);
|
||||
struct nf_proto_net *pn = &un->pn;
|
||||
|
||||
if (!pn->users) {
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < UDPLITE_CT_MAX; i++)
|
||||
un->timeouts[i] = udplite_timeouts[i];
|
||||
#ifdef CONFIG_SYSCTL
|
||||
pn->ctl_table = kmemdup(udplite_sysctl_table,
|
||||
sizeof(udplite_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
if (!pn->ctl_table)
|
||||
return -ENOMEM;
|
||||
pn->ctl_table[0].data = &un->timeouts[UDPLITE_CT_UNREPLIED];
|
||||
pn->ctl_table[1].data = &un->timeouts[UDPLITE_CT_REPLIED];
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
|
||||
return udplite_kmemdup_sysctl_table(pn, un);
|
||||
}
|
||||
|
||||
static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
|
||||
|
|
|
@ -195,9 +195,11 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||
lockdep_is_held(&nfnl_mutex)) != ss ||
|
||||
nfnetlink_find_client(type, ss) != nc)
|
||||
err = -EAGAIN;
|
||||
else
|
||||
else if (nc->call)
|
||||
err = nc->call(net->nfnl, skb, nlh,
|
||||
(const struct nlattr **)cda);
|
||||
else
|
||||
err = -EINVAL;
|
||||
nfnl_unlock();
|
||||
}
|
||||
if (err == -EAGAIN)
|
||||
|
|
|
@ -910,6 +910,11 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
|||
flags = ntohl(nla_get_be32(nfqa[NFQA_CFG_FLAGS]));
|
||||
mask = ntohl(nla_get_be32(nfqa[NFQA_CFG_MASK]));
|
||||
|
||||
if (flags >= NFQA_CFG_F_MAX) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_out_unlock;
|
||||
}
|
||||
|
||||
spin_lock_bh(&queue->lock);
|
||||
queue->flags &= ~mask;
|
||||
queue->flags |= flags & mask;
|
||||
|
|
Loading…
Reference in a new issue