1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/jiffies.h>
11#include <linux/timer.h>
12#include <linux/netfilter.h>
13#include <net/netfilter/nf_conntrack_l4proto.h>
14
15static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
16
17static bool nf_generic_should_process(u8 proto)
18{
19	switch (proto) {
20#ifdef CONFIG_NF_CT_PROTO_SCTP_MODULE
21	case IPPROTO_SCTP:
22		return false;
23#endif
24#ifdef CONFIG_NF_CT_PROTO_DCCP_MODULE
25	case IPPROTO_DCCP:
26		return false;
27#endif
28#ifdef CONFIG_NF_CT_PROTO_GRE_MODULE
29	case IPPROTO_GRE:
30		return false;
31#endif
32#ifdef CONFIG_NF_CT_PROTO_UDPLITE_MODULE
33	case IPPROTO_UDPLITE:
34		return false;
35#endif
36	default:
37		return true;
38	}
39}
40
41static inline struct nf_generic_net *generic_pernet(struct net *net)
42{
43	return &net->ct.nf_ct_proto.generic;
44}
45
46static bool generic_pkt_to_tuple(const struct sk_buff *skb,
47				 unsigned int dataoff,
48				 struct nf_conntrack_tuple *tuple)
49{
50	tuple->src.u.all = 0;
51	tuple->dst.u.all = 0;
52
53	return true;
54}
55
56static bool generic_invert_tuple(struct nf_conntrack_tuple *tuple,
57				 const struct nf_conntrack_tuple *orig)
58{
59	tuple->src.u.all = 0;
60	tuple->dst.u.all = 0;
61
62	return true;
63}
64
65/* Print out the per-protocol part of the tuple. */
66static int generic_print_tuple(struct seq_file *s,
67			       const struct nf_conntrack_tuple *tuple)
68{
69	return 0;
70}
71
72static unsigned int *generic_get_timeouts(struct net *net)
73{
74	return &(generic_pernet(net)->timeout);
75}
76
77/* Returns verdict for packet, or -1 for invalid. */
78static int generic_packet(struct nf_conn *ct,
79			  const struct sk_buff *skb,
80			  unsigned int dataoff,
81			  enum ip_conntrack_info ctinfo,
82			  u_int8_t pf,
83			  unsigned int hooknum,
84			  unsigned int *timeout)
85{
86	nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
87	return NF_ACCEPT;
88}
89
90/* Called when a new connection for this protocol found. */
91static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb,
92			unsigned int dataoff, unsigned int *timeouts)
93{
94	return nf_generic_should_process(nf_ct_protonum(ct));
95}
96
97#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
98
99#include <linux/netfilter/nfnetlink.h>
100#include <linux/netfilter/nfnetlink_cttimeout.h>
101
102static int generic_timeout_nlattr_to_obj(struct nlattr *tb[],
103					 struct net *net, void *data)
104{
105	unsigned int *timeout = data;
106	struct nf_generic_net *gn = generic_pernet(net);
107
108	if (tb[CTA_TIMEOUT_GENERIC_TIMEOUT])
109		*timeout =
110		    ntohl(nla_get_be32(tb[CTA_TIMEOUT_GENERIC_TIMEOUT])) * HZ;
111	else {
112		/* Set default generic timeout. */
113		*timeout = gn->timeout;
114	}
115
116	return 0;
117}
118
119static int
120generic_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
121{
122	const unsigned int *timeout = data;
123
124	if (nla_put_be32(skb, CTA_TIMEOUT_GENERIC_TIMEOUT, htonl(*timeout / HZ)))
125		goto nla_put_failure;
126
127	return 0;
128
129nla_put_failure:
130        return -ENOSPC;
131}
132
133static const struct nla_policy
134generic_timeout_nla_policy[CTA_TIMEOUT_GENERIC_MAX+1] = {
135	[CTA_TIMEOUT_GENERIC_TIMEOUT]	= { .type = NLA_U32 },
136};
137#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
138
139#ifdef CONFIG_SYSCTL
140static struct ctl_table generic_sysctl_table[] = {
141	{
142		.procname	= "nf_conntrack_generic_timeout",
143		.maxlen		= sizeof(unsigned int),
144		.mode		= 0644,
145		.proc_handler	= proc_dointvec_jiffies,
146	},
147	{ }
148};
149#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
150static struct ctl_table generic_compat_sysctl_table[] = {
151	{
152		.procname	= "ip_conntrack_generic_timeout",
153		.maxlen		= sizeof(unsigned int),
154		.mode		= 0644,
155		.proc_handler	= proc_dointvec_jiffies,
156	},
157	{ }
158};
159#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
160#endif /* CONFIG_SYSCTL */
161
162static int generic_kmemdup_sysctl_table(struct nf_proto_net *pn,
163					struct nf_generic_net *gn)
164{
165#ifdef CONFIG_SYSCTL
166	pn->ctl_table = kmemdup(generic_sysctl_table,
167				sizeof(generic_sysctl_table),
168				GFP_KERNEL);
169	if (!pn->ctl_table)
170		return -ENOMEM;
171
172	pn->ctl_table[0].data = &gn->timeout;
173#endif
174	return 0;
175}
176
177static int generic_kmemdup_compat_sysctl_table(struct nf_proto_net *pn,
178					       struct nf_generic_net *gn)
179{
180#ifdef CONFIG_SYSCTL
181#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
182	pn->ctl_compat_table = kmemdup(generic_compat_sysctl_table,
183				       sizeof(generic_compat_sysctl_table),
184				       GFP_KERNEL);
185	if (!pn->ctl_compat_table)
186		return -ENOMEM;
187
188	pn->ctl_compat_table[0].data = &gn->timeout;
189#endif
190#endif
191	return 0;
192}
193
194static int generic_init_net(struct net *net, u_int16_t proto)
195{
196	int ret;
197	struct nf_generic_net *gn = generic_pernet(net);
198	struct nf_proto_net *pn = &gn->pn;
199
200	gn->timeout = nf_ct_generic_timeout;
201
202	ret = generic_kmemdup_compat_sysctl_table(pn, gn);
203	if (ret < 0)
204		return ret;
205
206	ret = generic_kmemdup_sysctl_table(pn, gn);
207	if (ret < 0)
208		nf_ct_kfree_compat_sysctl_table(pn);
209
210	return ret;
211}
212
213static struct nf_proto_net *generic_get_net_proto(struct net *net)
214{
215	return &net->ct.nf_ct_proto.generic.pn;
216}
217
218struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
219{
220	.l3proto		= PF_UNSPEC,
221	.l4proto		= 255,
222	.name			= "unknown",
223	.pkt_to_tuple		= generic_pkt_to_tuple,
224	.invert_tuple		= generic_invert_tuple,
225	.print_tuple		= generic_print_tuple,
226	.packet			= generic_packet,
227	.get_timeouts		= generic_get_timeouts,
228	.new			= generic_new,
229#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
230	.ctnl_timeout		= {
231		.nlattr_to_obj	= generic_timeout_nlattr_to_obj,
232		.obj_to_nlattr	= generic_timeout_obj_to_nlattr,
233		.nlattr_max	= CTA_TIMEOUT_GENERIC_MAX,
234		.obj_size	= sizeof(unsigned int),
235		.nla_policy	= generic_timeout_nla_policy,
236	},
237#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
238	.init_net		= generic_init_net,
239	.get_net_proto		= generic_get_net_proto,
240};
241