Commit 49d485a3 authored by Gao feng's avatar Gao feng Committed by Pablo Neira Ayuso

netfilter: nf_ct_sctp: add namespace support

This patch adds namespace support for SCTP protocol tracker.
Acked-by: default avatarEric W. Biederman <ebiederm@xmission.com>
Signed-off-by: default avatarGao feng <gaofeng@cn.fujitsu.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent a7c439d3
...@@ -127,6 +127,17 @@ static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = { ...@@ -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, static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct nf_conntrack_tuple *tuple) struct nf_conntrack_tuple *tuple)
{ {
...@@ -281,7 +292,7 @@ static int sctp_new_state(enum ip_conntrack_dir dir, ...@@ -281,7 +292,7 @@ static int sctp_new_state(enum ip_conntrack_dir dir,
static unsigned int *sctp_get_timeouts(struct net *net) 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. */ /* Returns verdict for packet, or -NF_ACCEPT for invalid. */
...@@ -604,49 +615,42 @@ static struct ctl_table_header *sctp_sysctl_header; ...@@ -604,49 +615,42 @@ static struct ctl_table_header *sctp_sysctl_header;
static struct ctl_table sctp_sysctl_table[] = { static struct ctl_table sctp_sysctl_table[] = {
{ {
.procname = "nf_conntrack_sctp_timeout_closed", .procname = "nf_conntrack_sctp_timeout_closed",
.data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "nf_conntrack_sctp_timeout_cookie_wait", .procname = "nf_conntrack_sctp_timeout_cookie_wait",
.data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "nf_conntrack_sctp_timeout_cookie_echoed", .procname = "nf_conntrack_sctp_timeout_cookie_echoed",
.data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "nf_conntrack_sctp_timeout_established", .procname = "nf_conntrack_sctp_timeout_established",
.data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "nf_conntrack_sctp_timeout_shutdown_sent", .procname = "nf_conntrack_sctp_timeout_shutdown_sent",
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "nf_conntrack_sctp_timeout_shutdown_recd", .procname = "nf_conntrack_sctp_timeout_shutdown_recd",
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent", .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent",
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
...@@ -658,49 +662,42 @@ static struct ctl_table sctp_sysctl_table[] = { ...@@ -658,49 +662,42 @@ static struct ctl_table sctp_sysctl_table[] = {
static struct ctl_table sctp_compat_sysctl_table[] = { static struct ctl_table sctp_compat_sysctl_table[] = {
{ {
.procname = "ip_conntrack_sctp_timeout_closed", .procname = "ip_conntrack_sctp_timeout_closed",
.data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "ip_conntrack_sctp_timeout_cookie_wait", .procname = "ip_conntrack_sctp_timeout_cookie_wait",
.data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "ip_conntrack_sctp_timeout_cookie_echoed", .procname = "ip_conntrack_sctp_timeout_cookie_echoed",
.data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "ip_conntrack_sctp_timeout_established", .procname = "ip_conntrack_sctp_timeout_established",
.data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "ip_conntrack_sctp_timeout_shutdown_sent", .procname = "ip_conntrack_sctp_timeout_shutdown_sent",
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "ip_conntrack_sctp_timeout_shutdown_recd", .procname = "ip_conntrack_sctp_timeout_shutdown_recd",
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent", .procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
.data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
...@@ -710,6 +707,101 @@ static struct ctl_table sctp_compat_sysctl_table[] = { ...@@ -710,6 +707,101 @@ static struct ctl_table sctp_compat_sysctl_table[] = {
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
#endif #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 = { static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
.l3proto = PF_INET, .l3proto = PF_INET,
.l4proto = IPPROTO_SCTP, .l4proto = IPPROTO_SCTP,
...@@ -748,6 +840,8 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { ...@@ -748,6 +840,8 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
.ctl_compat_table = sctp_compat_sysctl_table, .ctl_compat_table = sctp_compat_sysctl_table,
#endif #endif
#endif #endif
.net_id = &sctp_net_id,
.init_net = sctpv4_init_net,
}; };
static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { 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 = { ...@@ -785,35 +879,58 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
.ctl_table_header = &sctp_sysctl_header, .ctl_table_header = &sctp_sysctl_header,
.ctl_table = sctp_sysctl_table, .ctl_table = sctp_sysctl_table,
#endif #endif
.net_id = &sctp_net_id,
.init_net = sctpv6_init_net,
}; };
static int __init nf_conntrack_proto_sctp_init(void) static int sctp_net_init(struct net *net)
{ {
int ret; int ret = 0;
ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_sctp4); ret = nf_conntrack_l4proto_register(net,
if (ret) { &nf_conntrack_l4proto_sctp4);
pr_err("nf_conntrack_l4proto_sctp4: protocol register failed\n"); if (ret < 0) {
pr_err("nf_conntrack_l4proto_sctp4 :protocol register failed.\n");
goto out; goto out;
} }
ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_sctp6); ret = nf_conntrack_l4proto_register(net,
if (ret) { &nf_conntrack_l4proto_sctp6);
pr_err("nf_conntrack_l4proto_sctp6: protocol register failed\n"); if (ret < 0) {
pr_err("nf_conntrack_l4proto_sctp6 :protocol register failed.\n");
goto cleanup_sctp4; goto cleanup_sctp4;
} }
return 0;
cleanup_sctp4:
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_sctp4);
out:
return ret; return ret;
}
cleanup_sctp4: static void sctp_net_exit(struct net *net)
nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_sctp4); {
out: nf_conntrack_l4proto_unregister(net,
return ret; &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)
{
return register_pernet_subsys(&sctp_net_ops);
} }
static void __exit nf_conntrack_proto_sctp_fini(void) static void __exit nf_conntrack_proto_sctp_fini(void)
{ {
nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_sctp6); unregister_pernet_subsys(&sctp_net_ops);
nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_sctp4);
} }
module_init(nf_conntrack_proto_sctp_init); module_init(nf_conntrack_proto_sctp_init);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment