aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/Kbuild1
-rw-r--r--include/linux/netfilter/nfnetlink.h3
-rw-r--r--include/linux/netfilter/nfnetlink_cttimeout.h114
-rw-r--r--include/net/netfilter/nf_conntrack_l4proto.h11
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c47
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c47
-rw-r--r--net/netfilter/Kconfig11
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/nf_conntrack_proto_dccp.c70
-rw-r--r--net/netfilter/nf_conntrack_proto_generic.c48
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c55
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c69
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c127
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c64
-rw-r--r--net/netfilter/nf_conntrack_proto_udplite.c66
-rw-r--r--net/netfilter/nfnetlink_cttimeout.c398
16 files changed, 1131 insertions, 1 deletions
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index aaa72aaa21de..1697036336b6 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -10,6 +10,7 @@ header-y += nfnetlink.h
10header-y += nfnetlink_acct.h 10header-y += nfnetlink_acct.h
11header-y += nfnetlink_compat.h 11header-y += nfnetlink_compat.h
12header-y += nfnetlink_conntrack.h 12header-y += nfnetlink_conntrack.h
13header-y += nfnetlink_cttimeout.h
13header-y += nfnetlink_log.h 14header-y += nfnetlink_log.h
14header-y += nfnetlink_queue.h 15header-y += nfnetlink_queue.h
15header-y += x_tables.h 16header-y += x_tables.h
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index b64454c2f79f..6fd1f0d07e64 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -49,7 +49,8 @@ struct nfgenmsg {
49#define NFNL_SUBSYS_OSF 5 49#define NFNL_SUBSYS_OSF 5
50#define NFNL_SUBSYS_IPSET 6 50#define NFNL_SUBSYS_IPSET 6
51#define NFNL_SUBSYS_ACCT 7 51#define NFNL_SUBSYS_ACCT 7
52#define NFNL_SUBSYS_COUNT 8 52#define NFNL_SUBSYS_CTNETLINK_TIMEOUT 8
53#define NFNL_SUBSYS_COUNT 9
53 54
54#ifdef __KERNEL__ 55#ifdef __KERNEL__
55 56
diff --git a/include/linux/netfilter/nfnetlink_cttimeout.h b/include/linux/netfilter/nfnetlink_cttimeout.h
new file mode 100644
index 000000000000..a2810a7c5e30
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink_cttimeout.h
@@ -0,0 +1,114 @@
1#ifndef _CTTIMEOUT_NETLINK_H
2#define _CTTIMEOUT_NETLINK_H
3#include <linux/netfilter/nfnetlink.h>
4
5enum ctnl_timeout_msg_types {
6 IPCTNL_MSG_TIMEOUT_NEW,
7 IPCTNL_MSG_TIMEOUT_GET,
8 IPCTNL_MSG_TIMEOUT_DELETE,
9
10 IPCTNL_MSG_TIMEOUT_MAX
11};
12
13enum ctattr_timeout {
14 CTA_TIMEOUT_UNSPEC,
15 CTA_TIMEOUT_NAME,
16 CTA_TIMEOUT_L3PROTO,
17 CTA_TIMEOUT_L4PROTO,
18 CTA_TIMEOUT_DATA,
19 CTA_TIMEOUT_USE,
20 __CTA_TIMEOUT_MAX
21};
22#define CTA_TIMEOUT_MAX (__CTA_TIMEOUT_MAX - 1)
23
24enum ctattr_timeout_generic {
25 CTA_TIMEOUT_GENERIC_UNSPEC,
26 CTA_TIMEOUT_GENERIC_TIMEOUT,
27 __CTA_TIMEOUT_GENERIC_MAX
28};
29#define CTA_TIMEOUT_GENERIC_MAX (__CTA_TIMEOUT_GENERIC_MAX - 1)
30
31enum ctattr_timeout_tcp {
32 CTA_TIMEOUT_TCP_UNSPEC,
33 CTA_TIMEOUT_TCP_SYN_SENT,
34 CTA_TIMEOUT_TCP_SYN_RECV,
35 CTA_TIMEOUT_TCP_ESTABLISHED,
36 CTA_TIMEOUT_TCP_FIN_WAIT,
37 CTA_TIMEOUT_TCP_CLOSE_WAIT,
38 CTA_TIMEOUT_TCP_LAST_ACK,
39 CTA_TIMEOUT_TCP_TIME_WAIT,
40 CTA_TIMEOUT_TCP_CLOSE,
41 CTA_TIMEOUT_TCP_SYN_SENT2,
42 CTA_TIMEOUT_TCP_RETRANS,
43 CTA_TIMEOUT_TCP_UNACK,
44 __CTA_TIMEOUT_TCP_MAX
45};
46#define CTA_TIMEOUT_TCP_MAX (__CTA_TIMEOUT_TCP_MAX - 1)
47
48enum ctattr_timeout_udp {
49 CTA_TIMEOUT_UDP_UNSPEC,
50 CTA_TIMEOUT_UDP_UNREPLIED,
51 CTA_TIMEOUT_UDP_REPLIED,
52 __CTA_TIMEOUT_UDP_MAX
53};
54#define CTA_TIMEOUT_UDP_MAX (__CTA_TIMEOUT_UDP_MAX - 1)
55
56enum ctattr_timeout_udplite {
57 CTA_TIMEOUT_UDPLITE_UNSPEC,
58 CTA_TIMEOUT_UDPLITE_UNREPLIED,
59 CTA_TIMEOUT_UDPLITE_REPLIED,
60 __CTA_TIMEOUT_UDPLITE_MAX
61};
62#define CTA_TIMEOUT_UDPLITE_MAX (__CTA_TIMEOUT_UDPLITE_MAX - 1)
63
64enum ctattr_timeout_icmp {
65 CTA_TIMEOUT_ICMP_UNSPEC,
66 CTA_TIMEOUT_ICMP_TIMEOUT,
67 __CTA_TIMEOUT_ICMP_MAX
68};
69#define CTA_TIMEOUT_ICMP_MAX (__CTA_TIMEOUT_ICMP_MAX - 1)
70
71enum ctattr_timeout_dccp {
72 CTA_TIMEOUT_DCCP_UNSPEC,
73 CTA_TIMEOUT_DCCP_REQUEST,
74 CTA_TIMEOUT_DCCP_RESPOND,
75 CTA_TIMEOUT_DCCP_PARTOPEN,
76 CTA_TIMEOUT_DCCP_OPEN,
77 CTA_TIMEOUT_DCCP_CLOSEREQ,
78 CTA_TIMEOUT_DCCP_CLOSING,
79 CTA_TIMEOUT_DCCP_TIMEWAIT,
80 __CTA_TIMEOUT_DCCP_MAX
81};
82#define CTA_TIMEOUT_DCCP_MAX (__CTA_TIMEOUT_DCCP_MAX - 1)
83
84enum ctattr_timeout_sctp {
85 CTA_TIMEOUT_SCTP_UNSPEC,
86 CTA_TIMEOUT_SCTP_CLOSED,
87 CTA_TIMEOUT_SCTP_COOKIE_WAIT,
88 CTA_TIMEOUT_SCTP_COOKIE_ECHOED,
89 CTA_TIMEOUT_SCTP_ESTABLISHED,
90 CTA_TIMEOUT_SCTP_SHUTDOWN_SENT,
91 CTA_TIMEOUT_SCTP_SHUTDOWN_RECD,
92 CTA_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT,
93 __CTA_TIMEOUT_SCTP_MAX
94};
95#define CTA_TIMEOUT_SCTP_MAX (__CTA_TIMEOUT_SCTP_MAX - 1)
96
97enum ctattr_timeout_icmpv6 {
98 CTA_TIMEOUT_ICMPV6_UNSPEC,
99 CTA_TIMEOUT_ICMPV6_TIMEOUT,
100 __CTA_TIMEOUT_ICMPV6_MAX
101};
102#define CTA_TIMEOUT_ICMPV6_MAX (__CTA_TIMEOUT_ICMPV6_MAX - 1)
103
104enum ctattr_timeout_gre {
105 CTA_TIMEOUT_GRE_UNSPEC,
106 CTA_TIMEOUT_GRE_UNREPLIED,
107 CTA_TIMEOUT_GRE_REPLIED,
108 __CTA_TIMEOUT_GRE_MAX
109};
110#define CTA_TIMEOUT_GRE_MAX (__CTA_TIMEOUT_GRE_MAX - 1)
111
112#define CTNL_TIMEOUT_NAME_MAX 32
113
114#endif
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index c48b67405aa0..90c67c7db7e9 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -83,6 +83,17 @@ struct nf_conntrack_l4proto {
83 83
84 size_t nla_size; 84 size_t nla_size;
85 85
86#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
87 struct {
88 size_t obj_size;
89 int (*nlattr_to_obj)(struct nlattr *tb[], void *data);
90 int (*obj_to_nlattr)(struct sk_buff *skb, const void *data);
91
92 unsigned int nlattr_max;
93 const struct nla_policy *nla_policy;
94 } ctnl_timeout;
95#endif
96
86#ifdef CONFIG_SYSCTL 97#ifdef CONFIG_SYSCTL
87 struct ctl_table_header **ctl_table_header; 98 struct ctl_table_header **ctl_table_header;
88 struct ctl_table *ctl_table; 99 struct ctl_table *ctl_table;
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 6b801124b31f..7cbe9cb261c2 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -269,6 +269,44 @@ static int icmp_nlattr_tuple_size(void)
269} 269}
270#endif 270#endif
271 271
272#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
273
274#include <linux/netfilter/nfnetlink.h>
275#include <linux/netfilter/nfnetlink_cttimeout.h>
276
277static int icmp_timeout_nlattr_to_obj(struct nlattr *tb[], void *data)
278{
279 unsigned int *timeout = data;
280
281 if (tb[CTA_TIMEOUT_ICMP_TIMEOUT]) {
282 *timeout =
283 ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMP_TIMEOUT])) * HZ;
284 } else {
285 /* Set default ICMP timeout. */
286 *timeout = nf_ct_icmp_timeout;
287 }
288 return 0;
289}
290
291static int
292icmp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
293{
294 const unsigned int *timeout = data;
295
296 NLA_PUT_BE32(skb, CTA_TIMEOUT_ICMP_TIMEOUT, htonl(*timeout / HZ));
297
298 return 0;
299
300nla_put_failure:
301 return -ENOSPC;
302}
303
304static const struct nla_policy
305icmp_timeout_nla_policy[CTA_TIMEOUT_ICMP_MAX+1] = {
306 [CTA_TIMEOUT_ICMP_TIMEOUT] = { .type = NLA_U32 },
307};
308#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
309
272#ifdef CONFIG_SYSCTL 310#ifdef CONFIG_SYSCTL
273static struct ctl_table_header *icmp_sysctl_header; 311static struct ctl_table_header *icmp_sysctl_header;
274static struct ctl_table icmp_sysctl_table[] = { 312static struct ctl_table icmp_sysctl_table[] = {
@@ -315,6 +353,15 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly =
315 .nlattr_to_tuple = icmp_nlattr_to_tuple, 353 .nlattr_to_tuple = icmp_nlattr_to_tuple,
316 .nla_policy = icmp_nla_policy, 354 .nla_policy = icmp_nla_policy,
317#endif 355#endif
356#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
357 .ctnl_timeout = {
358 .nlattr_to_obj = icmp_timeout_nlattr_to_obj,
359 .obj_to_nlattr = icmp_timeout_obj_to_nlattr,
360 .nlattr_max = CTA_TIMEOUT_ICMP_MAX,
361 .obj_size = sizeof(unsigned int),
362 .nla_policy = icmp_timeout_nla_policy,
363 },
364#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
318#ifdef CONFIG_SYSCTL 365#ifdef CONFIG_SYSCTL
319 .ctl_table_header = &icmp_sysctl_header, 366 .ctl_table_header = &icmp_sysctl_header,
320 .ctl_table = icmp_sysctl_table, 367 .ctl_table = icmp_sysctl_table,
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 2eb9751eb7a8..92cc9f2931ae 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -276,6 +276,44 @@ static int icmpv6_nlattr_tuple_size(void)
276} 276}
277#endif 277#endif
278 278
279#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
280
281#include <linux/netfilter/nfnetlink.h>
282#include <linux/netfilter/nfnetlink_cttimeout.h>
283
284static int icmpv6_timeout_nlattr_to_obj(struct nlattr *tb[], void *data)
285{
286 unsigned int *timeout = data;
287
288 if (tb[CTA_TIMEOUT_ICMPV6_TIMEOUT]) {
289 *timeout =
290 ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMPV6_TIMEOUT])) * HZ;
291 } else {
292 /* Set default ICMPv6 timeout. */
293 *timeout = nf_ct_icmpv6_timeout;
294 }
295 return 0;
296}
297
298static int
299icmpv6_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
300{
301 const unsigned int *timeout = data;
302
303 NLA_PUT_BE32(skb, CTA_TIMEOUT_ICMPV6_TIMEOUT, htonl(*timeout / HZ));
304
305 return 0;
306
307nla_put_failure:
308 return -ENOSPC;
309}
310
311static const struct nla_policy
312icmpv6_timeout_nla_policy[CTA_TIMEOUT_ICMPV6_MAX+1] = {
313 [CTA_TIMEOUT_ICMPV6_TIMEOUT] = { .type = NLA_U32 },
314};
315#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
316
279#ifdef CONFIG_SYSCTL 317#ifdef CONFIG_SYSCTL
280static struct ctl_table_header *icmpv6_sysctl_header; 318static struct ctl_table_header *icmpv6_sysctl_header;
281static struct ctl_table icmpv6_sysctl_table[] = { 319static struct ctl_table icmpv6_sysctl_table[] = {
@@ -308,6 +346,15 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
308 .nlattr_to_tuple = icmpv6_nlattr_to_tuple, 346 .nlattr_to_tuple = icmpv6_nlattr_to_tuple,
309 .nla_policy = icmpv6_nla_policy, 347 .nla_policy = icmpv6_nla_policy,
310#endif 348#endif
349#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
350 .ctnl_timeout = {
351 .nlattr_to_obj = icmpv6_timeout_nlattr_to_obj,
352 .obj_to_nlattr = icmpv6_timeout_obj_to_nlattr,
353 .nlattr_max = CTA_TIMEOUT_ICMP_MAX,
354 .obj_size = sizeof(unsigned int),
355 .nla_policy = icmpv6_timeout_nla_policy,
356 },
357#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
311#ifdef CONFIG_SYSCTL 358#ifdef CONFIG_SYSCTL
312 .ctl_table_header = &icmpv6_sysctl_header, 359 .ctl_table_header = &icmpv6_sysctl_header,
313 .ctl_table = icmpv6_sysctl_table, 360 .ctl_table = icmpv6_sysctl_table,
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index b895d8b13215..f3efb6570dd9 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -314,6 +314,17 @@ config NF_CT_NETLINK
314 help 314 help
315 This option enables support for a netlink-based userspace interface 315 This option enables support for a netlink-based userspace interface
316 316
317config NF_CT_NETLINK_TIMEOUT
318 tristate 'Connection tracking timeout tuning via Netlink'
319 select NETFILTER_NETLINK
320 depends on NETFILTER_ADVANCED
321 help
322 This option enables support for connection tracking timeout
323 fine-grain tuning. This allows you to attach specific timeout
324 policies to flows, instead of using the global timeout policy.
325
326 If unsure, say `N'.
327
317endif # NF_CONNTRACK 328endif # NF_CONNTRACK
318 329
319# transparent proxy support 330# transparent proxy support
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index a28c2a6563f8..cf7cdd630bdd 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
22 22
23# netlink interface for nf_conntrack 23# netlink interface for nf_conntrack
24obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o 24obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
25obj-$(CONFIG_NF_CT_NETLINK_TIMEOUT) += nfnetlink_cttimeout.o
25 26
26# connection tracking helpers 27# connection tracking helpers
27nf_conntrack_h323-objs := nf_conntrack_h323_main.o nf_conntrack_h323_asn1.o 28nf_conntrack_h323-objs := nf_conntrack_h323_main.o nf_conntrack_h323_asn1.o
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index 8ea33598a0a7..24fdce256cb0 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -706,8 +706,60 @@ static int dccp_nlattr_size(void)
706 return nla_total_size(0) /* CTA_PROTOINFO_DCCP */ 706 return nla_total_size(0) /* CTA_PROTOINFO_DCCP */
707 + nla_policy_len(dccp_nla_policy, CTA_PROTOINFO_DCCP_MAX + 1); 707 + nla_policy_len(dccp_nla_policy, CTA_PROTOINFO_DCCP_MAX + 1);
708} 708}
709
709#endif 710#endif
710 711
712#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
713
714#include <linux/netfilter/nfnetlink.h>
715#include <linux/netfilter/nfnetlink_cttimeout.h>
716
717static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[], void *data)
718{
719 struct dccp_net *dn = dccp_pernet(&init_net);
720 unsigned int *timeouts = data;
721 int i;
722
723 /* set default DCCP timeouts. */
724 for (i=0; i<CT_DCCP_MAX; i++)
725 timeouts[i] = dn->dccp_timeout[i];
726
727 /* there's a 1:1 mapping between attributes and protocol states. */
728 for (i=CTA_TIMEOUT_DCCP_UNSPEC+1; i<CTA_TIMEOUT_DCCP_MAX+1; i++) {
729 if (tb[i]) {
730 timeouts[i] = ntohl(nla_get_be32(tb[i])) * HZ;
731 }
732 }
733 return 0;
734}
735
736static int
737dccp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
738{
739 const unsigned int *timeouts = data;
740 int i;
741
742 for (i=CTA_TIMEOUT_DCCP_UNSPEC+1; i<CTA_TIMEOUT_DCCP_MAX+1; i++)
743 NLA_PUT_BE32(skb, i, htonl(timeouts[i] / HZ));
744
745 return 0;
746
747nla_put_failure:
748 return -ENOSPC;
749}
750
751static const struct nla_policy
752dccp_timeout_nla_policy[CTA_TIMEOUT_DCCP_MAX+1] = {
753 [CTA_TIMEOUT_DCCP_REQUEST] = { .type = NLA_U32 },
754 [CTA_TIMEOUT_DCCP_RESPOND] = { .type = NLA_U32 },
755 [CTA_TIMEOUT_DCCP_PARTOPEN] = { .type = NLA_U32 },
756 [CTA_TIMEOUT_DCCP_OPEN] = { .type = NLA_U32 },
757 [CTA_TIMEOUT_DCCP_CLOSEREQ] = { .type = NLA_U32 },
758 [CTA_TIMEOUT_DCCP_CLOSING] = { .type = NLA_U32 },
759 [CTA_TIMEOUT_DCCP_TIMEWAIT] = { .type = NLA_U32 },
760};
761#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
762
711#ifdef CONFIG_SYSCTL 763#ifdef CONFIG_SYSCTL
712/* template, data assigned later */ 764/* template, data assigned later */
713static struct ctl_table dccp_sysctl_table[] = { 765static struct ctl_table dccp_sysctl_table[] = {
@@ -784,6 +836,15 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
784 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 836 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
785 .nla_policy = nf_ct_port_nla_policy, 837 .nla_policy = nf_ct_port_nla_policy,
786#endif 838#endif
839#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
840 .ctnl_timeout = {
841 .nlattr_to_obj = dccp_timeout_nlattr_to_obj,
842 .obj_to_nlattr = dccp_timeout_obj_to_nlattr,
843 .nlattr_max = CTA_TIMEOUT_DCCP_MAX,
844 .obj_size = sizeof(unsigned int) * CT_DCCP_MAX,
845 .nla_policy = dccp_timeout_nla_policy,
846 },
847#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
787}; 848};
788 849
789static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { 850static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
@@ -807,6 +868,15 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
807 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 868 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
808 .nla_policy = nf_ct_port_nla_policy, 869 .nla_policy = nf_ct_port_nla_policy,
809#endif 870#endif
871#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
872 .ctnl_timeout = {
873 .nlattr_to_obj = dccp_timeout_nlattr_to_obj,
874 .obj_to_nlattr = dccp_timeout_obj_to_nlattr,
875 .nlattr_max = CTA_TIMEOUT_DCCP_MAX,
876 .obj_size = sizeof(unsigned int) * CT_DCCP_MAX,
877 .nla_policy = dccp_timeout_nla_policy,
878 },
879#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
810}; 880};
811 881
812static __net_init int dccp_net_init(struct net *net) 882static __net_init int dccp_net_init(struct net *net)
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 0e6c5451db80..835e24c58f0d 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -65,6 +65,45 @@ static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb,
65 return true; 65 return true;
66} 66}
67 67
68#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
69
70#include <linux/netfilter/nfnetlink.h>
71#include <linux/netfilter/nfnetlink_cttimeout.h>
72
73static int generic_timeout_nlattr_to_obj(struct nlattr *tb[], void *data)
74{
75 unsigned int *timeout = data;
76
77 if (tb[CTA_TIMEOUT_GENERIC_TIMEOUT])
78 *timeout =
79 ntohl(nla_get_be32(tb[CTA_TIMEOUT_GENERIC_TIMEOUT])) * HZ;
80 else {
81 /* Set default generic timeout. */
82 *timeout = nf_ct_generic_timeout;
83 }
84
85 return 0;
86}
87
88static int
89generic_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
90{
91 const unsigned int *timeout = data;
92
93 NLA_PUT_BE32(skb, CTA_TIMEOUT_GENERIC_TIMEOUT, htonl(*timeout / HZ));
94
95 return 0;
96
97nla_put_failure:
98 return -ENOSPC;
99}
100
101static const struct nla_policy
102generic_timeout_nla_policy[CTA_TIMEOUT_GENERIC_MAX+1] = {
103 [CTA_TIMEOUT_GENERIC_TIMEOUT] = { .type = NLA_U32 },
104};
105#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
106
68#ifdef CONFIG_SYSCTL 107#ifdef CONFIG_SYSCTL
69static struct ctl_table_header *generic_sysctl_header; 108static struct ctl_table_header *generic_sysctl_header;
70static struct ctl_table generic_sysctl_table[] = { 109static struct ctl_table generic_sysctl_table[] = {
@@ -102,6 +141,15 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
102 .packet = generic_packet, 141 .packet = generic_packet,
103 .get_timeouts = generic_get_timeouts, 142 .get_timeouts = generic_get_timeouts,
104 .new = generic_new, 143 .new = generic_new,
144#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
145 .ctnl_timeout = {
146 .nlattr_to_obj = generic_timeout_nlattr_to_obj,
147 .obj_to_nlattr = generic_timeout_obj_to_nlattr,
148 .nlattr_max = CTA_TIMEOUT_GENERIC_MAX,
149 .obj_size = sizeof(unsigned int),
150 .nla_policy = generic_timeout_nla_policy,
151 },
152#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
105#ifdef CONFIG_SYSCTL 153#ifdef CONFIG_SYSCTL
106 .ctl_table_header = &generic_sysctl_header, 154 .ctl_table_header = &generic_sysctl_header,
107 .ctl_table = generic_sysctl_table, 155 .ctl_table = generic_sysctl_table,
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 1bf01c95658b..659648c4b14a 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -292,6 +292,52 @@ static void gre_destroy(struct nf_conn *ct)
292 nf_ct_gre_keymap_destroy(master); 292 nf_ct_gre_keymap_destroy(master);
293} 293}
294 294
295#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
296
297#include <linux/netfilter/nfnetlink.h>
298#include <linux/netfilter/nfnetlink_cttimeout.h>
299
300static int gre_timeout_nlattr_to_obj(struct nlattr *tb[], void *data)
301{
302 unsigned int *timeouts = data;
303
304 /* set default timeouts for GRE. */
305 timeouts[GRE_CT_UNREPLIED] = gre_timeouts[GRE_CT_UNREPLIED];
306 timeouts[GRE_CT_REPLIED] = gre_timeouts[GRE_CT_REPLIED];
307
308 if (tb[CTA_TIMEOUT_GRE_UNREPLIED]) {
309 timeouts[GRE_CT_UNREPLIED] =
310 ntohl(nla_get_be32(tb[CTA_TIMEOUT_GRE_UNREPLIED])) * HZ;
311 }
312 if (tb[CTA_TIMEOUT_GRE_REPLIED]) {
313 timeouts[GRE_CT_REPLIED] =
314 ntohl(nla_get_be32(tb[CTA_TIMEOUT_GRE_REPLIED])) * HZ;
315 }
316 return 0;
317}
318
319static int
320gre_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
321{
322 const unsigned int *timeouts = data;
323
324 NLA_PUT_BE32(skb, CTA_TIMEOUT_GRE_UNREPLIED,
325 htonl(timeouts[GRE_CT_UNREPLIED] / HZ));
326 NLA_PUT_BE32(skb, CTA_TIMEOUT_GRE_REPLIED,
327 htonl(timeouts[GRE_CT_REPLIED] / HZ));
328 return 0;
329
330nla_put_failure:
331 return -ENOSPC;
332}
333
334static const struct nla_policy
335gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = {
336 [CTA_TIMEOUT_GRE_UNREPLIED] = { .type = NLA_U32 },
337 [CTA_TIMEOUT_GRE_REPLIED] = { .type = NLA_U32 },
338};
339#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
340
295/* protocol helper struct */ 341/* protocol helper struct */
296static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = { 342static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
297 .l3proto = AF_INET, 343 .l3proto = AF_INET,
@@ -312,6 +358,15 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
312 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 358 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
313 .nla_policy = nf_ct_port_nla_policy, 359 .nla_policy = nf_ct_port_nla_policy,
314#endif 360#endif
361#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
362 .ctnl_timeout = {
363 .nlattr_to_obj = gre_timeout_nlattr_to_obj,
364 .obj_to_nlattr = gre_timeout_obj_to_nlattr,
365 .nlattr_max = CTA_TIMEOUT_GRE_MAX,
366 .obj_size = sizeof(unsigned int) * GRE_CT_MAX,
367 .nla_policy = gre_timeout_nla_policy,
368 },
369#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
315}; 370};
316 371
317static int proto_gre_net_init(struct net *net) 372static int proto_gre_net_init(struct net *net)
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 2a0703371e24..72b5088592dc 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -549,6 +549,57 @@ static int sctp_nlattr_size(void)
549} 549}
550#endif 550#endif
551 551
552#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
553
554#include <linux/netfilter/nfnetlink.h>
555#include <linux/netfilter/nfnetlink_cttimeout.h>
556
557static int sctp_timeout_nlattr_to_obj(struct nlattr *tb[], void *data)
558{
559 unsigned int *timeouts = data;
560 int i;
561
562 /* set default SCTP timeouts. */
563 for (i=0; i<SCTP_CONNTRACK_MAX; i++)
564 timeouts[i] = sctp_timeouts[i];
565
566 /* there's a 1:1 mapping between attributes and protocol states. */
567 for (i=CTA_TIMEOUT_SCTP_UNSPEC+1; i<CTA_TIMEOUT_SCTP_MAX+1; i++) {
568 if (tb[i]) {
569 timeouts[i] = ntohl(nla_get_be32(tb[i])) * HZ;
570 }
571 }
572 return 0;
573}
574
575static int
576sctp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
577{
578 const unsigned int *timeouts = data;
579 int i;
580
581 for (i=CTA_TIMEOUT_SCTP_UNSPEC+1; i<CTA_TIMEOUT_SCTP_MAX+1; i++)
582 NLA_PUT_BE32(skb, i, htonl(timeouts[i] / HZ));
583
584 return 0;
585
586nla_put_failure:
587 return -ENOSPC;
588}
589
590static const struct nla_policy
591sctp_timeout_nla_policy[CTA_TIMEOUT_SCTP_MAX+1] = {
592 [CTA_TIMEOUT_SCTP_CLOSED] = { .type = NLA_U32 },
593 [CTA_TIMEOUT_SCTP_COOKIE_WAIT] = { .type = NLA_U32 },
594 [CTA_TIMEOUT_SCTP_COOKIE_ECHOED] = { .type = NLA_U32 },
595 [CTA_TIMEOUT_SCTP_ESTABLISHED] = { .type = NLA_U32 },
596 [CTA_TIMEOUT_SCTP_SHUTDOWN_SENT] = { .type = NLA_U32 },
597 [CTA_TIMEOUT_SCTP_SHUTDOWN_RECD] = { .type = NLA_U32 },
598 [CTA_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT] = { .type = NLA_U32 },
599};
600#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
601
602
552#ifdef CONFIG_SYSCTL 603#ifdef CONFIG_SYSCTL
553static unsigned int sctp_sysctl_table_users; 604static unsigned int sctp_sysctl_table_users;
554static struct ctl_table_header *sctp_sysctl_header; 605static struct ctl_table_header *sctp_sysctl_header;
@@ -682,6 +733,15 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
682 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 733 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
683 .nla_policy = nf_ct_port_nla_policy, 734 .nla_policy = nf_ct_port_nla_policy,
684#endif 735#endif
736#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
737 .ctnl_timeout = {
738 .nlattr_to_obj = sctp_timeout_nlattr_to_obj,
739 .obj_to_nlattr = sctp_timeout_obj_to_nlattr,
740 .nlattr_max = CTA_TIMEOUT_SCTP_MAX,
741 .obj_size = sizeof(unsigned int) * SCTP_CONNTRACK_MAX,
742 .nla_policy = sctp_timeout_nla_policy,
743 },
744#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
685#ifdef CONFIG_SYSCTL 745#ifdef CONFIG_SYSCTL
686 .ctl_table_users = &sctp_sysctl_table_users, 746 .ctl_table_users = &sctp_sysctl_table_users,
687 .ctl_table_header = &sctp_sysctl_header, 747 .ctl_table_header = &sctp_sysctl_header,
@@ -712,6 +772,15 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
712 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, 772 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
713 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 773 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
714 .nla_policy = nf_ct_port_nla_policy, 774 .nla_policy = nf_ct_port_nla_policy,
775#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
776 .ctnl_timeout = {
777 .nlattr_to_obj = sctp_timeout_nlattr_to_obj,
778 .obj_to_nlattr = sctp_timeout_obj_to_nlattr,
779 .nlattr_max = CTA_TIMEOUT_SCTP_MAX,
780 .obj_size = sizeof(unsigned int) * SCTP_CONNTRACK_MAX,
781 .nla_policy = sctp_timeout_nla_policy,
782 },
783#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
715#endif 784#endif
716#ifdef CONFIG_SYSCTL 785#ifdef CONFIG_SYSCTL
717 .ctl_table_users = &sctp_sysctl_table_users, 786 .ctl_table_users = &sctp_sysctl_table_users,
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 8372bb43feb0..361eade62a09 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -1244,6 +1244,113 @@ static int tcp_nlattr_tuple_size(void)
1244} 1244}
1245#endif 1245#endif
1246 1246
1247#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
1248
1249#include <linux/netfilter/nfnetlink.h>
1250#include <linux/netfilter/nfnetlink_cttimeout.h>
1251
1252static int tcp_timeout_nlattr_to_obj(struct nlattr *tb[], void *data)
1253{
1254 unsigned int *timeouts = data;
1255 int i;
1256
1257 /* set default TCP timeouts. */
1258 for (i=0; i<TCP_CONNTRACK_TIMEOUT_MAX; i++)
1259 timeouts[i] = tcp_timeouts[i];
1260
1261 if (tb[CTA_TIMEOUT_TCP_SYN_SENT]) {
1262 timeouts[TCP_CONNTRACK_SYN_SENT] =
1263 ntohl(nla_get_be32(tb[CTA_TIMEOUT_TCP_SYN_SENT]))*HZ;
1264 }
1265 if (tb[CTA_TIMEOUT_TCP_SYN_RECV]) {
1266 timeouts[TCP_CONNTRACK_SYN_RECV] =
1267 ntohl(nla_get_be32(tb[CTA_TIMEOUT_TCP_SYN_RECV]))*HZ;
1268 }
1269 if (tb[CTA_TIMEOUT_TCP_ESTABLISHED]) {
1270 timeouts[TCP_CONNTRACK_ESTABLISHED] =
1271 ntohl(nla_get_be32(tb[CTA_TIMEOUT_TCP_ESTABLISHED]))*HZ;
1272 }
1273 if (tb[CTA_TIMEOUT_TCP_FIN_WAIT]) {
1274 timeouts[TCP_CONNTRACK_FIN_WAIT] =
1275 ntohl(nla_get_be32(tb[CTA_TIMEOUT_TCP_FIN_WAIT]))*HZ;
1276 }
1277 if (tb[CTA_TIMEOUT_TCP_CLOSE_WAIT]) {
1278 timeouts[TCP_CONNTRACK_CLOSE_WAIT] =
1279 ntohl(nla_get_be32(tb[CTA_TIMEOUT_TCP_CLOSE_WAIT]))*HZ;
1280 }
1281 if (tb[CTA_TIMEOUT_TCP_LAST_ACK]) {
1282 timeouts[TCP_CONNTRACK_LAST_ACK] =
1283 ntohl(nla_get_be32(tb[CTA_TIMEOUT_TCP_LAST_ACK]))*HZ;
1284 }
1285 if (tb[CTA_TIMEOUT_TCP_TIME_WAIT]) {
1286 timeouts[TCP_CONNTRACK_TIME_WAIT] =
1287 ntohl(nla_get_be32(tb[CTA_TIMEOUT_TCP_TIME_WAIT]))*HZ;
1288 }
1289 if (tb[CTA_TIMEOUT_TCP_CLOSE]) {
1290 timeouts[TCP_CONNTRACK_CLOSE] =
1291 ntohl(nla_get_be32(tb[CTA_TIMEOUT_TCP_CLOSE]))*HZ;
1292 }
1293 if (tb[CTA_TIMEOUT_TCP_SYN_SENT2]) {
1294 timeouts[TCP_CONNTRACK_SYN_SENT2] =
1295 ntohl(nla_get_be32(tb[CTA_TIMEOUT_TCP_SYN_SENT2]))*HZ;
1296 }
1297 if (tb[CTA_TIMEOUT_TCP_RETRANS]) {
1298 timeouts[TCP_CONNTRACK_RETRANS] =
1299 ntohl(nla_get_be32(tb[CTA_TIMEOUT_TCP_RETRANS]))*HZ;
1300 }
1301 if (tb[CTA_TIMEOUT_TCP_UNACK]) {
1302 timeouts[TCP_CONNTRACK_UNACK] =
1303 ntohl(nla_get_be32(tb[CTA_TIMEOUT_TCP_UNACK]))*HZ;
1304 }
1305 return 0;
1306}
1307
1308static int
1309tcp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
1310{
1311 const unsigned int *timeouts = data;
1312
1313 NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_SYN_SENT,
1314 htonl(timeouts[TCP_CONNTRACK_SYN_SENT] / HZ));
1315 NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_SYN_RECV,
1316 htonl(timeouts[TCP_CONNTRACK_SYN_RECV] / HZ));
1317 NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_ESTABLISHED,
1318 htonl(timeouts[TCP_CONNTRACK_ESTABLISHED] / HZ));
1319 NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_FIN_WAIT,
1320 htonl(timeouts[TCP_CONNTRACK_FIN_WAIT] / HZ));
1321 NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_CLOSE_WAIT,
1322 htonl(timeouts[TCP_CONNTRACK_CLOSE_WAIT] / HZ));
1323 NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_LAST_ACK,
1324 htonl(timeouts[TCP_CONNTRACK_LAST_ACK] / HZ));
1325 NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_TIME_WAIT,
1326 htonl(timeouts[TCP_CONNTRACK_TIME_WAIT] / HZ));
1327 NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_CLOSE,
1328 htonl(timeouts[TCP_CONNTRACK_CLOSE] / HZ));
1329 NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_SYN_SENT2,
1330 htonl(timeouts[TCP_CONNTRACK_SYN_SENT2] / HZ));
1331 NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_RETRANS,
1332 htonl(timeouts[TCP_CONNTRACK_RETRANS] / HZ));
1333 NLA_PUT_BE32(skb, CTA_TIMEOUT_TCP_UNACK,
1334 htonl(timeouts[TCP_CONNTRACK_UNACK] / HZ));
1335 return 0;
1336
1337nla_put_failure:
1338 return -ENOSPC;
1339}
1340
1341static const struct nla_policy tcp_timeout_nla_policy[CTA_TIMEOUT_TCP_MAX+1] = {
1342 [CTA_TIMEOUT_TCP_SYN_SENT] = { .type = NLA_U32 },
1343 [CTA_TIMEOUT_TCP_SYN_RECV] = { .type = NLA_U32 },
1344 [CTA_TIMEOUT_TCP_ESTABLISHED] = { .type = NLA_U32 },
1345 [CTA_TIMEOUT_TCP_FIN_WAIT] = { .type = NLA_U32 },
1346 [CTA_TIMEOUT_TCP_CLOSE_WAIT] = { .type = NLA_U32 },
1347 [CTA_TIMEOUT_TCP_LAST_ACK] = { .type = NLA_U32 },
1348 [CTA_TIMEOUT_TCP_TIME_WAIT] = { .type = NLA_U32 },
1349 [CTA_TIMEOUT_TCP_CLOSE] = { .type = NLA_U32 },
1350 [CTA_TIMEOUT_TCP_SYN_SENT2] = { .type = NLA_U32 },
1351};
1352#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
1353
1247#ifdef CONFIG_SYSCTL 1354#ifdef CONFIG_SYSCTL
1248static unsigned int tcp_sysctl_table_users; 1355static unsigned int tcp_sysctl_table_users;
1249static struct ctl_table_header *tcp_sysctl_header; 1356static struct ctl_table_header *tcp_sysctl_header;
@@ -1462,6 +1569,16 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly =
1462 .nlattr_tuple_size = tcp_nlattr_tuple_size, 1569 .nlattr_tuple_size = tcp_nlattr_tuple_size,
1463 .nla_policy = nf_ct_port_nla_policy, 1570 .nla_policy = nf_ct_port_nla_policy,
1464#endif 1571#endif
1572#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
1573 .ctnl_timeout = {
1574 .nlattr_to_obj = tcp_timeout_nlattr_to_obj,
1575 .obj_to_nlattr = tcp_timeout_obj_to_nlattr,
1576 .nlattr_max = CTA_TIMEOUT_TCP_MAX,
1577 .obj_size = sizeof(unsigned int) *
1578 TCP_CONNTRACK_TIMEOUT_MAX,
1579 .nla_policy = tcp_timeout_nla_policy,
1580 },
1581#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
1465#ifdef CONFIG_SYSCTL 1582#ifdef CONFIG_SYSCTL
1466 .ctl_table_users = &tcp_sysctl_table_users, 1583 .ctl_table_users = &tcp_sysctl_table_users,
1467 .ctl_table_header = &tcp_sysctl_header, 1584 .ctl_table_header = &tcp_sysctl_header,
@@ -1495,6 +1612,16 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly =
1495 .nlattr_tuple_size = tcp_nlattr_tuple_size, 1612 .nlattr_tuple_size = tcp_nlattr_tuple_size,
1496 .nla_policy = nf_ct_port_nla_policy, 1613 .nla_policy = nf_ct_port_nla_policy,
1497#endif 1614#endif
1615#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
1616 .ctnl_timeout = {
1617 .nlattr_to_obj = tcp_timeout_nlattr_to_obj,
1618 .obj_to_nlattr = tcp_timeout_obj_to_nlattr,
1619 .nlattr_max = CTA_TIMEOUT_TCP_MAX,
1620 .obj_size = sizeof(unsigned int) *
1621 TCP_CONNTRACK_TIMEOUT_MAX,
1622 .nla_policy = tcp_timeout_nla_policy,
1623 },
1624#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
1498#ifdef CONFIG_SYSCTL 1625#ifdef CONFIG_SYSCTL
1499 .ctl_table_users = &tcp_sysctl_table_users, 1626 .ctl_table_users = &tcp_sysctl_table_users,
1500 .ctl_table_header = &tcp_sysctl_header, 1627 .ctl_table_header = &tcp_sysctl_header,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 70e005992d5b..a9073dc1548d 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -152,6 +152,52 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
152 return NF_ACCEPT; 152 return NF_ACCEPT;
153} 153}
154 154
155#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
156
157#include <linux/netfilter/nfnetlink.h>
158#include <linux/netfilter/nfnetlink_cttimeout.h>
159
160static int udp_timeout_nlattr_to_obj(struct nlattr *tb[], void *data)
161{
162 unsigned int *timeouts = data;
163
164 /* set default timeouts for UDP. */
165 timeouts[UDP_CT_UNREPLIED] = udp_timeouts[UDP_CT_UNREPLIED];
166 timeouts[UDP_CT_REPLIED] = udp_timeouts[UDP_CT_REPLIED];
167
168 if (tb[CTA_TIMEOUT_UDP_UNREPLIED]) {
169 timeouts[UDP_CT_UNREPLIED] =
170 ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_UNREPLIED])) * HZ;
171 }
172 if (tb[CTA_TIMEOUT_UDP_REPLIED]) {
173 timeouts[UDP_CT_REPLIED] =
174 ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_REPLIED])) * HZ;
175 }
176 return 0;
177}
178
179static int
180udp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
181{
182 const unsigned int *timeouts = data;
183
184 NLA_PUT_BE32(skb, CTA_TIMEOUT_UDP_UNREPLIED,
185 htonl(timeouts[UDP_CT_UNREPLIED] / HZ));
186 NLA_PUT_BE32(skb, CTA_TIMEOUT_UDP_REPLIED,
187 htonl(timeouts[UDP_CT_REPLIED] / HZ));
188 return 0;
189
190nla_put_failure:
191 return -ENOSPC;
192}
193
194static const struct nla_policy
195udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = {
196 [CTA_TIMEOUT_UDP_UNREPLIED] = { .type = NLA_U32 },
197 [CTA_TIMEOUT_UDP_REPLIED] = { .type = NLA_U32 },
198};
199#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
200
155#ifdef CONFIG_SYSCTL 201#ifdef CONFIG_SYSCTL
156static unsigned int udp_sysctl_table_users; 202static unsigned int udp_sysctl_table_users;
157static struct ctl_table_header *udp_sysctl_header; 203static struct ctl_table_header *udp_sysctl_header;
@@ -211,6 +257,15 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
211 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, 257 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
212 .nla_policy = nf_ct_port_nla_policy, 258 .nla_policy = nf_ct_port_nla_policy,
213#endif 259#endif
260#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
261 .ctnl_timeout = {
262 .nlattr_to_obj = udp_timeout_nlattr_to_obj,
263 .obj_to_nlattr = udp_timeout_obj_to_nlattr,
264 .nlattr_max = CTA_TIMEOUT_UDP_MAX,
265 .obj_size = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
266 .nla_policy = udp_timeout_nla_policy,
267 },
268#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
214#ifdef CONFIG_SYSCTL 269#ifdef CONFIG_SYSCTL
215 .ctl_table_users = &udp_sysctl_table_users, 270 .ctl_table_users = &udp_sysctl_table_users,
216 .ctl_table_header = &udp_sysctl_header, 271 .ctl_table_header = &udp_sysctl_header,
@@ -240,6 +295,15 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =
240 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, 295 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
241 .nla_policy = nf_ct_port_nla_policy, 296 .nla_policy = nf_ct_port_nla_policy,
242#endif 297#endif
298#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
299 .ctnl_timeout = {
300 .nlattr_to_obj = udp_timeout_nlattr_to_obj,
301 .obj_to_nlattr = udp_timeout_obj_to_nlattr,
302 .nlattr_max = CTA_TIMEOUT_UDP_MAX,
303 .obj_size = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
304 .nla_policy = udp_timeout_nla_policy,
305 },
306#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
243#ifdef CONFIG_SYSCTL 307#ifdef CONFIG_SYSCTL
244 .ctl_table_users = &udp_sysctl_table_users, 308 .ctl_table_users = &udp_sysctl_table_users,
245 .ctl_table_header = &udp_sysctl_header, 309 .ctl_table_header = &udp_sysctl_header,
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index 0b32ccb1d515..e0606392cda0 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -156,6 +156,52 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl,
156 return NF_ACCEPT; 156 return NF_ACCEPT;
157} 157}
158 158
159#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
160
161#include <linux/netfilter/nfnetlink.h>
162#include <linux/netfilter/nfnetlink_cttimeout.h>
163
164static int udplite_timeout_nlattr_to_obj(struct nlattr *tb[], void *data)
165{
166 unsigned int *timeouts = data;
167
168 /* set default timeouts for UDPlite. */
169 timeouts[UDPLITE_CT_UNREPLIED] = udplite_timeouts[UDPLITE_CT_UNREPLIED];
170 timeouts[UDPLITE_CT_REPLIED] = udplite_timeouts[UDPLITE_CT_REPLIED];
171
172 if (tb[CTA_TIMEOUT_UDPLITE_UNREPLIED]) {
173 timeouts[UDPLITE_CT_UNREPLIED] =
174 ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDPLITE_UNREPLIED])) * HZ;
175 }
176 if (tb[CTA_TIMEOUT_UDPLITE_REPLIED]) {
177 timeouts[UDPLITE_CT_REPLIED] =
178 ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDPLITE_REPLIED])) * HZ;
179 }
180 return 0;
181}
182
183static int
184udplite_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
185{
186 const unsigned int *timeouts = data;
187
188 NLA_PUT_BE32(skb, CTA_TIMEOUT_UDPLITE_UNREPLIED,
189 htonl(timeouts[UDPLITE_CT_UNREPLIED] / HZ));
190 NLA_PUT_BE32(skb, CTA_TIMEOUT_UDPLITE_REPLIED,
191 htonl(timeouts[UDPLITE_CT_REPLIED] / HZ));
192 return 0;
193
194nla_put_failure:
195 return -ENOSPC;
196}
197
198static const struct nla_policy
199udplite_timeout_nla_policy[CTA_TIMEOUT_UDPLITE_MAX+1] = {
200 [CTA_TIMEOUT_UDPLITE_UNREPLIED] = { .type = NLA_U32 },
201 [CTA_TIMEOUT_UDPLITE_REPLIED] = { .type = NLA_U32 },
202};
203#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
204
159#ifdef CONFIG_SYSCTL 205#ifdef CONFIG_SYSCTL
160static unsigned int udplite_sysctl_table_users; 206static unsigned int udplite_sysctl_table_users;
161static struct ctl_table_header *udplite_sysctl_header; 207static struct ctl_table_header *udplite_sysctl_header;
@@ -196,6 +242,16 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
196 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 242 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
197 .nla_policy = nf_ct_port_nla_policy, 243 .nla_policy = nf_ct_port_nla_policy,
198#endif 244#endif
245#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
246 .ctnl_timeout = {
247 .nlattr_to_obj = udplite_timeout_nlattr_to_obj,
248 .obj_to_nlattr = udplite_timeout_obj_to_nlattr,
249 .nlattr_max = CTA_TIMEOUT_UDPLITE_MAX,
250 .obj_size = sizeof(unsigned int) *
251 CTA_TIMEOUT_UDPLITE_MAX,
252 .nla_policy = udplite_timeout_nla_policy,
253 },
254#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
199#ifdef CONFIG_SYSCTL 255#ifdef CONFIG_SYSCTL
200 .ctl_table_users = &udplite_sysctl_table_users, 256 .ctl_table_users = &udplite_sysctl_table_users,
201 .ctl_table_header = &udplite_sysctl_header, 257 .ctl_table_header = &udplite_sysctl_header,
@@ -221,6 +277,16 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
221 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, 277 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
222 .nla_policy = nf_ct_port_nla_policy, 278 .nla_policy = nf_ct_port_nla_policy,
223#endif 279#endif
280#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
281 .ctnl_timeout = {
282 .nlattr_to_obj = udplite_timeout_nlattr_to_obj,
283 .obj_to_nlattr = udplite_timeout_obj_to_nlattr,
284 .nlattr_max = CTA_TIMEOUT_UDPLITE_MAX,
285 .obj_size = sizeof(unsigned int) *
286 CTA_TIMEOUT_UDPLITE_MAX,
287 .nla_policy = udplite_timeout_nla_policy,
288 },
289#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
224#ifdef CONFIG_SYSCTL 290#ifdef CONFIG_SYSCTL
225 .ctl_table_users = &udplite_sysctl_table_users, 291 .ctl_table_users = &udplite_sysctl_table_users,
226 .ctl_table_header = &udplite_sysctl_header, 292 .ctl_table_header = &udplite_sysctl_header,
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
new file mode 100644
index 000000000000..b860d5217189
--- /dev/null
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -0,0 +1,398 @@
1/*
2 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
3 * (C) 2012 by Vyatta Inc. <http://www.vyatta.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation (or any later at your option).
8 */
9#include <linux/init.h>
10#include <linux/module.h>
11#include <linux/kernel.h>
12#include <linux/rculist.h>
13#include <linux/rculist_nulls.h>
14#include <linux/types.h>
15#include <linux/timer.h>
16#include <linux/security.h>
17#include <linux/skbuff.h>
18#include <linux/errno.h>
19#include <linux/netlink.h>
20#include <linux/spinlock.h>
21#include <linux/interrupt.h>
22#include <linux/slab.h>
23
24#include <linux/netfilter.h>
25#include <net/netlink.h>
26#include <net/sock.h>
27#include <net/netfilter/nf_conntrack.h>
28#include <net/netfilter/nf_conntrack_core.h>
29#include <net/netfilter/nf_conntrack_l3proto.h>
30#include <net/netfilter/nf_conntrack_l4proto.h>
31#include <net/netfilter/nf_conntrack_tuple.h>
32
33#include <linux/netfilter/nfnetlink.h>
34#include <linux/netfilter/nfnetlink_cttimeout.h>
35
36MODULE_LICENSE("GPL");
37MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
38MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning");
39
40struct ctnl_timeout {
41 struct list_head head;
42 struct rcu_head rcu_head;
43 atomic_t refcnt;
44 char name[CTNL_TIMEOUT_NAME_MAX];
45 __u16 l3num;
46 __u8 l4num;
47 char data[0];
48};
49
50static LIST_HEAD(cttimeout_list);
51
52static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
53 [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING },
54 [CTA_TIMEOUT_L3PROTO] = { .type = NLA_U16 },
55 [CTA_TIMEOUT_L4PROTO] = { .type = NLA_U8 },
56 [CTA_TIMEOUT_DATA] = { .type = NLA_NESTED },
57};
58
59static int
60ctnl_timeout_parse_policy(struct ctnl_timeout *timeout,
61 struct nf_conntrack_l4proto *l4proto,
62 const struct nlattr *attr)
63{
64 int ret = 0;
65
66 if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) {
67 struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max+1];
68
69 nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max,
70 attr, l4proto->ctnl_timeout.nla_policy);
71
72 ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, &timeout->data);
73 }
74 return ret;
75}
76
77static int
78cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
79 const struct nlmsghdr *nlh,
80 const struct nlattr * const cda[])
81{
82 __u16 l3num;
83 __u8 l4num;
84 struct nf_conntrack_l4proto *l4proto;
85 struct ctnl_timeout *timeout, *matching = NULL;
86 char *name;
87 int ret;
88
89 if (!cda[CTA_TIMEOUT_NAME] ||
90 !cda[CTA_TIMEOUT_L3PROTO] ||
91 !cda[CTA_TIMEOUT_L4PROTO] ||
92 !cda[CTA_TIMEOUT_DATA])
93 return -EINVAL;
94
95 name = nla_data(cda[CTA_TIMEOUT_NAME]);
96 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
97 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
98
99 list_for_each_entry(timeout, &cttimeout_list, head) {
100 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
101 continue;
102
103 if (nlh->nlmsg_flags & NLM_F_EXCL)
104 return -EEXIST;
105
106 matching = timeout;
107 break;
108 }
109
110 l4proto = __nf_ct_l4proto_find(l3num, l4num);
111
112 /* This protocol is not supportted, skip. */
113 if (l4proto->l4proto != l4num)
114 return -EOPNOTSUPP;
115
116 if (matching) {
117 if (nlh->nlmsg_flags & NLM_F_REPLACE) {
118 /* You cannot replace one timeout policy by another of
119 * different kind, sorry.
120 */
121 if (matching->l3num != l3num ||
122 matching->l4num != l4num)
123 return -EINVAL;
124
125 ret = ctnl_timeout_parse_policy(matching, l4proto,
126 cda[CTA_TIMEOUT_DATA]);
127 return ret;
128 }
129 return -EBUSY;
130 }
131
132 timeout = kzalloc(sizeof(struct ctnl_timeout) +
133 l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
134 if (timeout == NULL)
135 return -ENOMEM;
136
137 ret = ctnl_timeout_parse_policy(timeout, l4proto,
138 cda[CTA_TIMEOUT_DATA]);
139 if (ret < 0)
140 goto err;
141
142 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
143 timeout->l3num = l3num;
144 timeout->l4num = l4num;
145 atomic_set(&timeout->refcnt, 1);
146 list_add_tail_rcu(&timeout->head, &cttimeout_list);
147
148 return 0;
149err:
150 kfree(timeout);
151 return ret;
152}
153
154static int
155ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,
156 int event, struct ctnl_timeout *timeout)
157{
158 struct nlmsghdr *nlh;
159 struct nfgenmsg *nfmsg;
160 unsigned int flags = pid ? NLM_F_MULTI : 0;
161 struct nf_conntrack_l4proto *l4proto;
162
163 event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8;
164 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
165 if (nlh == NULL)
166 goto nlmsg_failure;
167
168 nfmsg = nlmsg_data(nlh);
169 nfmsg->nfgen_family = AF_UNSPEC;
170 nfmsg->version = NFNETLINK_V0;
171 nfmsg->res_id = 0;
172
173 NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name);
174 NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num));
175 NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4num);
176 NLA_PUT_BE32(skb, CTA_TIMEOUT_USE,
177 htonl(atomic_read(&timeout->refcnt)));
178
179 l4proto = __nf_ct_l4proto_find(timeout->l3num, timeout->l4num);
180
181 /* If the timeout object does not match the layer 4 protocol tracker,
182 * then skip dumping the data part since we don't know how to
183 * interpret it. This may happen for UPDlite, SCTP and DCCP since
184 * you can unload the module.
185 */
186 if (timeout->l4num != l4proto->l4proto)
187 goto out;
188
189 if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
190 struct nlattr *nest_parms;
191 int ret;
192
193 nest_parms = nla_nest_start(skb,
194 CTA_TIMEOUT_DATA | NLA_F_NESTED);
195 if (!nest_parms)
196 goto nla_put_failure;
197
198 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data);
199 if (ret < 0)
200 goto nla_put_failure;
201
202 nla_nest_end(skb, nest_parms);
203 }
204out:
205 nlmsg_end(skb, nlh);
206 return skb->len;
207
208nlmsg_failure:
209nla_put_failure:
210 nlmsg_cancel(skb, nlh);
211 return -1;
212}
213
214static int
215ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
216{
217 struct ctnl_timeout *cur, *last;
218
219 if (cb->args[2])
220 return 0;
221
222 last = (struct ctnl_timeout *)cb->args[1];
223 if (cb->args[1])
224 cb->args[1] = 0;
225
226 rcu_read_lock();
227 list_for_each_entry_rcu(cur, &cttimeout_list, head) {
228 if (last && cur != last)
229 continue;
230
231 if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).pid,
232 cb->nlh->nlmsg_seq,
233 NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
234 IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) {
235 cb->args[1] = (unsigned long)cur;
236 break;
237 }
238 }
239 if (!cb->args[1])
240 cb->args[2] = 1;
241 rcu_read_unlock();
242 return skb->len;
243}
244
245static int
246cttimeout_get_timeout(struct sock *ctnl, struct sk_buff *skb,
247 const struct nlmsghdr *nlh,
248 const struct nlattr * const cda[])
249{
250 int ret = -ENOENT;
251 char *name;
252 struct ctnl_timeout *cur;
253
254 if (nlh->nlmsg_flags & NLM_F_DUMP) {
255 struct netlink_dump_control c = {
256 .dump = ctnl_timeout_dump,
257 };
258 return netlink_dump_start(ctnl, skb, nlh, &c);
259 }
260
261 if (!cda[CTA_TIMEOUT_NAME])
262 return -EINVAL;
263 name = nla_data(cda[CTA_TIMEOUT_NAME]);
264
265 list_for_each_entry(cur, &cttimeout_list, head) {
266 struct sk_buff *skb2;
267
268 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
269 continue;
270
271 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
272 if (skb2 == NULL) {
273 ret = -ENOMEM;
274 break;
275 }
276
277 ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).pid,
278 nlh->nlmsg_seq,
279 NFNL_MSG_TYPE(nlh->nlmsg_type),
280 IPCTNL_MSG_TIMEOUT_NEW, cur);
281 if (ret <= 0) {
282 kfree_skb(skb2);
283 break;
284 }
285 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid,
286 MSG_DONTWAIT);
287 if (ret > 0)
288 ret = 0;
289
290 /* this avoids a loop in nfnetlink. */
291 return ret == -EAGAIN ? -ENOBUFS : ret;
292 }
293 return ret;
294}
295
296/* try to delete object, fail if it is still in use. */
297static int ctnl_timeout_try_del(struct ctnl_timeout *timeout)
298{
299 int ret = 0;
300
301 /* we want to avoid races with nf_ct_timeout_find_get. */
302 if (atomic_dec_and_test(&timeout->refcnt)) {
303 /* We are protected by nfnl mutex. */
304 list_del_rcu(&timeout->head);
305 kfree_rcu(timeout, rcu_head);
306 } else {
307 /* still in use, restore reference counter. */
308 atomic_inc(&timeout->refcnt);
309 ret = -EBUSY;
310 }
311 return ret;
312}
313
314static int
315cttimeout_del_timeout(struct sock *ctnl, struct sk_buff *skb,
316 const struct nlmsghdr *nlh,
317 const struct nlattr * const cda[])
318{
319 char *name;
320 struct ctnl_timeout *cur;
321 int ret = -ENOENT;
322
323 if (!cda[CTA_TIMEOUT_NAME]) {
324 list_for_each_entry(cur, &cttimeout_list, head)
325 ctnl_timeout_try_del(cur);
326
327 return 0;
328 }
329 name = nla_data(cda[CTA_TIMEOUT_NAME]);
330
331 list_for_each_entry(cur, &cttimeout_list, head) {
332 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
333 continue;
334
335 ret = ctnl_timeout_try_del(cur);
336 if (ret < 0)
337 return ret;
338
339 break;
340 }
341 return ret;
342}
343
344static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = {
345 [IPCTNL_MSG_TIMEOUT_NEW] = { .call = cttimeout_new_timeout,
346 .attr_count = CTA_TIMEOUT_MAX,
347 .policy = cttimeout_nla_policy },
348 [IPCTNL_MSG_TIMEOUT_GET] = { .call = cttimeout_get_timeout,
349 .attr_count = CTA_TIMEOUT_MAX,
350 .policy = cttimeout_nla_policy },
351 [IPCTNL_MSG_TIMEOUT_DELETE] = { .call = cttimeout_del_timeout,
352 .attr_count = CTA_TIMEOUT_MAX,
353 .policy = cttimeout_nla_policy },
354};
355
356static const struct nfnetlink_subsystem cttimeout_subsys = {
357 .name = "conntrack_timeout",
358 .subsys_id = NFNL_SUBSYS_CTNETLINK_TIMEOUT,
359 .cb_count = IPCTNL_MSG_TIMEOUT_MAX,
360 .cb = cttimeout_cb,
361};
362
363MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT);
364
365static int __init cttimeout_init(void)
366{
367 int ret;
368
369 ret = nfnetlink_subsys_register(&cttimeout_subsys);
370 if (ret < 0) {
371 pr_err("cttimeout_init: cannot register cttimeout with "
372 "nfnetlink.\n");
373 goto err_out;
374 }
375 return 0;
376
377err_out:
378 return ret;
379}
380
381static void __exit cttimeout_exit(void)
382{
383 struct ctnl_timeout *cur, *tmp;
384
385 pr_info("cttimeout: unregistering from nfnetlink.\n");
386
387 nfnetlink_subsys_unregister(&cttimeout_subsys);
388 list_for_each_entry_safe(cur, tmp, &cttimeout_list, head) {
389 list_del_rcu(&cur->head);
390 /* We are sure that our objects have no clients at this point,
391 * it's safe to release them all without checking refcnt.
392 */
393 kfree_rcu(cur, rcu_head);
394 }
395}
396
397module_init(cttimeout_init);
398module_exit(cttimeout_exit);