netfilter: nf_ct_sctp: add namespace support
This patch adds namespace support for SCTP protocol tracker. Acked-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Родитель
a7c439d396
Коммит
49d485a30f
|
@ -127,6 +127,17 @@ static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
|
|||
}
|
||||
};
|
||||
|
||||
static int sctp_net_id __read_mostly;
|
||||
struct sctp_net {
|
||||
struct nf_proto_net pn;
|
||||
unsigned int timeouts[SCTP_CONNTRACK_MAX];
|
||||
};
|
||||
|
||||
static inline struct sctp_net *sctp_pernet(struct net *net)
|
||||
{
|
||||
return net_generic(net, sctp_net_id);
|
||||
}
|
||||
|
||||
static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
|
||||
struct nf_conntrack_tuple *tuple)
|
||||
{
|
||||
|
@ -281,7 +292,7 @@ static int sctp_new_state(enum ip_conntrack_dir dir,
|
|||
|
||||
static unsigned int *sctp_get_timeouts(struct net *net)
|
||||
{
|
||||
return sctp_timeouts;
|
||||
return sctp_pernet(net)->timeouts;
|
||||
}
|
||||
|
||||
/* Returns verdict for packet, or -NF_ACCEPT for invalid. */
|
||||
|
@ -604,49 +615,42 @@ static struct ctl_table_header *sctp_sysctl_header;
|
|||
static struct ctl_table sctp_sysctl_table[] = {
|
||||
{
|
||||
.procname = "nf_conntrack_sctp_timeout_closed",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "nf_conntrack_sctp_timeout_cookie_wait",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "nf_conntrack_sctp_timeout_cookie_echoed",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "nf_conntrack_sctp_timeout_established",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "nf_conntrack_sctp_timeout_shutdown_sent",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "nf_conntrack_sctp_timeout_shutdown_recd",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
|
@ -658,49 +662,42 @@ static struct ctl_table sctp_sysctl_table[] = {
|
|||
static struct ctl_table sctp_compat_sysctl_table[] = {
|
||||
{
|
||||
.procname = "ip_conntrack_sctp_timeout_closed",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "ip_conntrack_sctp_timeout_cookie_wait",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "ip_conntrack_sctp_timeout_cookie_echoed",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "ip_conntrack_sctp_timeout_established",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "ip_conntrack_sctp_timeout_shutdown_sent",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "ip_conntrack_sctp_timeout_shutdown_recd",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
},
|
||||
{
|
||||
.procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
|
||||
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_jiffies,
|
||||
|
@ -710,6 +707,101 @@ 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)
|
||||
{
|
||||
#ifdef CONFIG_SYSCTL
|
||||
struct sctp_net *sn = (struct sctp_net *)pn;
|
||||
if (pn->ctl_table)
|
||||
return 0;
|
||||
|
||||
pn->ctl_table = kmemdup(sctp_sysctl_table,
|
||||
sizeof(sctp_sysctl_table),
|
||||
GFP_KERNEL);
|
||||
if (!pn->ctl_table)
|
||||
return -ENOMEM;
|
||||
|
||||
pn->ctl_table[0].data = &sn->timeouts[SCTP_CONNTRACK_CLOSED];
|
||||
pn->ctl_table[1].data = &sn->timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
|
||||
pn->ctl_table[2].data = &sn->timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
|
||||
pn->ctl_table[3].data = &sn->timeouts[SCTP_CONNTRACK_ESTABLISHED];
|
||||
pn->ctl_table[4].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
|
||||
pn->ctl_table[5].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
|
||||
pn->ctl_table[6].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sctp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn)
|
||||
{
|
||||
#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);
|
||||
if (!pn->ctl_compat_table)
|
||||
return -ENOMEM;
|
||||
|
||||
pn->ctl_compat_table[0].data = &sn->timeouts[SCTP_CONNTRACK_CLOSED];
|
||||
pn->ctl_compat_table[1].data = &sn->timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
|
||||
pn->ctl_compat_table[2].data = &sn->timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
|
||||
pn->ctl_compat_table[3].data = &sn->timeouts[SCTP_CONNTRACK_ESTABLISHED];
|
||||
pn->ctl_compat_table[4].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
|
||||
pn->ctl_compat_table[5].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
|
||||
pn->ctl_compat_table[6].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sctpv4_init_net(struct net *net)
|
||||
{
|
||||
int ret;
|
||||
struct sctp_net *sn = sctp_pernet(net);
|
||||
struct nf_proto_net *pn = (struct nf_proto_net *)sn;
|
||||
|
||||
sctp_init_net_data(sn);
|
||||
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
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,
|
||||
|
@ -748,6 +840,8 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
|
|||
.ctl_compat_table = sctp_compat_sysctl_table,
|
||||
#endif
|
||||
#endif
|
||||
.net_id = &sctp_net_id,
|
||||
.init_net = sctpv4_init_net,
|
||||
};
|
||||
|
||||
static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
|
||||
|
@ -785,35 +879,58 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
|
|||
.ctl_table_header = &sctp_sysctl_header,
|
||||
.ctl_table = sctp_sysctl_table,
|
||||
#endif
|
||||
.net_id = &sctp_net_id,
|
||||
.init_net = sctpv6_init_net,
|
||||
};
|
||||
|
||||
static int sctp_net_init(struct net *net)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = nf_conntrack_l4proto_register(net,
|
||||
&nf_conntrack_l4proto_sctp4);
|
||||
if (ret < 0) {
|
||||
pr_err("nf_conntrack_l4proto_sctp4 :protocol register failed.\n");
|
||||
goto out;
|
||||
}
|
||||
ret = nf_conntrack_l4proto_register(net,
|
||||
&nf_conntrack_l4proto_sctp6);
|
||||
if (ret < 0) {
|
||||
pr_err("nf_conntrack_l4proto_sctp6 :protocol register failed.\n");
|
||||
goto cleanup_sctp4;
|
||||
}
|
||||
return 0;
|
||||
|
||||
cleanup_sctp4:
|
||||
nf_conntrack_l4proto_unregister(net,
|
||||
&nf_conntrack_l4proto_sctp4);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sctp_net_exit(struct net *net)
|
||||
{
|
||||
nf_conntrack_l4proto_unregister(net,
|
||||
&nf_conntrack_l4proto_sctp6);
|
||||
nf_conntrack_l4proto_unregister(net,
|
||||
&nf_conntrack_l4proto_sctp4);
|
||||
}
|
||||
|
||||
static struct pernet_operations sctp_net_ops = {
|
||||
.init = sctp_net_init,
|
||||
.exit = sctp_net_exit,
|
||||
.id = &sctp_net_id,
|
||||
.size = sizeof(struct sctp_net),
|
||||
};
|
||||
|
||||
static int __init nf_conntrack_proto_sctp_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_sctp4);
|
||||
if (ret) {
|
||||
pr_err("nf_conntrack_l4proto_sctp4: protocol register failed\n");
|
||||
goto out;
|
||||
}
|
||||
ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_sctp6);
|
||||
if (ret) {
|
||||
pr_err("nf_conntrack_l4proto_sctp6: protocol register failed\n");
|
||||
goto cleanup_sctp4;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
cleanup_sctp4:
|
||||
nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_sctp4);
|
||||
out:
|
||||
return ret;
|
||||
return register_pernet_subsys(&sctp_net_ops);
|
||||
}
|
||||
|
||||
static void __exit nf_conntrack_proto_sctp_fini(void)
|
||||
{
|
||||
nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_sctp6);
|
||||
nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_sctp4);
|
||||
unregister_pernet_subsys(&sctp_net_ops);
|
||||
}
|
||||
|
||||
module_init(nf_conntrack_proto_sctp_init);
|
||||
|
|
Загрузка…
Ссылка в новой задаче