1
2
3
4
5
6
7
8
9
10#include <linux/types.h>
11#include <linux/timer.h>
12#include <linux/module.h>
13#include <linux/udp.h>
14#include <linux/seq_file.h>
15#include <linux/skbuff.h>
16#include <linux/ipv6.h>
17#include <net/ip6_checksum.h>
18#include <net/checksum.h>
19
20#include <linux/netfilter.h>
21#include <linux/netfilter_ipv4.h>
22#include <linux/netfilter_ipv6.h>
23#include <net/netfilter/nf_conntrack_l4proto.h>
24#include <net/netfilter/nf_conntrack_ecache.h>
25#include <net/netfilter/nf_log.h>
26#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
27#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
28
29static unsigned int udp_timeouts[UDP_CT_MAX] = {
30 [UDP_CT_UNREPLIED] = 30*HZ,
31 [UDP_CT_REPLIED] = 180*HZ,
32};
33
34static inline struct nf_udp_net *udp_pernet(struct net *net)
35{
36 return &net->ct.nf_ct_proto.udp;
37}
38
39static bool udp_pkt_to_tuple(const struct sk_buff *skb,
40 unsigned int dataoff,
41 struct nf_conntrack_tuple *tuple)
42{
43 const struct udphdr *hp;
44 struct udphdr _hdr;
45
46
47 hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
48 if (hp == NULL)
49 return false;
50
51 tuple->src.u.udp.port = hp->source;
52 tuple->dst.u.udp.port = hp->dest;
53
54 return true;
55}
56
57static bool udp_invert_tuple(struct nf_conntrack_tuple *tuple,
58 const struct nf_conntrack_tuple *orig)
59{
60 tuple->src.u.udp.port = orig->dst.u.udp.port;
61 tuple->dst.u.udp.port = orig->src.u.udp.port;
62 return true;
63}
64
65
66static int udp_print_tuple(struct seq_file *s,
67 const struct nf_conntrack_tuple *tuple)
68{
69 return seq_printf(s, "sport=%hu dport=%hu ",
70 ntohs(tuple->src.u.udp.port),
71 ntohs(tuple->dst.u.udp.port));
72}
73
74static unsigned int *udp_get_timeouts(struct net *net)
75{
76 return udp_pernet(net)->timeouts;
77}
78
79
80static int udp_packet(struct nf_conn *ct,
81 const struct sk_buff *skb,
82 unsigned int dataoff,
83 enum ip_conntrack_info ctinfo,
84 u_int8_t pf,
85 unsigned int hooknum,
86 unsigned int *timeouts)
87{
88
89
90 if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
91 nf_ct_refresh_acct(ct, ctinfo, skb,
92 timeouts[UDP_CT_REPLIED]);
93
94 if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
95 nf_conntrack_event_cache(IPCT_ASSURED, ct);
96 } else {
97 nf_ct_refresh_acct(ct, ctinfo, skb,
98 timeouts[UDP_CT_UNREPLIED]);
99 }
100 return NF_ACCEPT;
101}
102
103
104static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
105 unsigned int dataoff, unsigned int *timeouts)
106{
107 return true;
108}
109
110#ifdef CONFIG_NF_CT_PROTO_UDPLITE
111static int udplite_error(struct net *net, struct nf_conn *tmpl,
112 struct sk_buff *skb,
113 unsigned int dataoff,
114 u8 pf, unsigned int hooknum)
115{
116 unsigned int udplen = skb->len - dataoff;
117 const struct udphdr *hdr;
118 struct udphdr _hdr;
119 unsigned int cscov;
120
121
122 hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
123 if (!hdr) {
124 if (LOG_INVALID(net, IPPROTO_UDPLITE))
125 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
126 "nf_ct_udplite: short packet ");
127 return -NF_ACCEPT;
128 }
129
130 cscov = ntohs(hdr->len);
131 if (cscov == 0) {
132 cscov = udplen;
133 } else if (cscov < sizeof(*hdr) || cscov > udplen) {
134 if (LOG_INVALID(net, IPPROTO_UDPLITE))
135 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
136 "nf_ct_udplite: invalid checksum coverage ");
137 return -NF_ACCEPT;
138 }
139
140
141 if (!hdr->check) {
142 if (LOG_INVALID(net, IPPROTO_UDPLITE))
143 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
144 "nf_ct_udplite: checksum missing ");
145 return -NF_ACCEPT;
146 }
147
148
149 if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
150 nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
151 pf)) {
152 if (LOG_INVALID(net, IPPROTO_UDPLITE))
153 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
154 "nf_ct_udplite: bad UDPLite checksum ");
155 return -NF_ACCEPT;
156 }
157
158 return NF_ACCEPT;
159}
160#endif
161
162static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
163 unsigned int dataoff,
164 u_int8_t pf,
165 unsigned int hooknum)
166{
167 unsigned int udplen = skb->len - dataoff;
168 const struct udphdr *hdr;
169 struct udphdr _hdr;
170
171
172 hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
173 if (hdr == NULL) {
174 if (LOG_INVALID(net, IPPROTO_UDP))
175 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
176 "nf_ct_udp: short packet ");
177 return -NF_ACCEPT;
178 }
179
180
181 if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
182 if (LOG_INVALID(net, IPPROTO_UDP))
183 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
184 "nf_ct_udp: truncated/malformed packet ");
185 return -NF_ACCEPT;
186 }
187
188
189 if (!hdr->check)
190 return NF_ACCEPT;
191
192
193
194
195
196 if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
197 nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
198 if (LOG_INVALID(net, IPPROTO_UDP))
199 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
200 "nf_ct_udp: bad UDP checksum ");
201 return -NF_ACCEPT;
202 }
203
204 return NF_ACCEPT;
205}
206
207#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
208
209#include <linux/netfilter/nfnetlink.h>
210#include <linux/netfilter/nfnetlink_cttimeout.h>
211
212static int udp_timeout_nlattr_to_obj(struct nlattr *tb[],
213 struct net *net, void *data)
214{
215 unsigned int *timeouts = data;
216 struct nf_udp_net *un = udp_pernet(net);
217
218
219 timeouts[UDP_CT_UNREPLIED] = un->timeouts[UDP_CT_UNREPLIED];
220 timeouts[UDP_CT_REPLIED] = un->timeouts[UDP_CT_REPLIED];
221
222 if (tb[CTA_TIMEOUT_UDP_UNREPLIED]) {
223 timeouts[UDP_CT_UNREPLIED] =
224 ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_UNREPLIED])) * HZ;
225 }
226 if (tb[CTA_TIMEOUT_UDP_REPLIED]) {
227 timeouts[UDP_CT_REPLIED] =
228 ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_REPLIED])) * HZ;
229 }
230 return 0;
231}
232
233static int
234udp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
235{
236 const unsigned int *timeouts = data;
237
238 if (nla_put_be32(skb, CTA_TIMEOUT_UDP_UNREPLIED,
239 htonl(timeouts[UDP_CT_UNREPLIED] / HZ)) ||
240 nla_put_be32(skb, CTA_TIMEOUT_UDP_REPLIED,
241 htonl(timeouts[UDP_CT_REPLIED] / HZ)))
242 goto nla_put_failure;
243 return 0;
244
245nla_put_failure:
246 return -ENOSPC;
247}
248
249static const struct nla_policy
250udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = {
251 [CTA_TIMEOUT_UDP_UNREPLIED] = { .type = NLA_U32 },
252 [CTA_TIMEOUT_UDP_REPLIED] = { .type = NLA_U32 },
253};
254#endif
255
256#ifdef CONFIG_SYSCTL
257static struct ctl_table udp_sysctl_table[] = {
258 {
259 .procname = "nf_conntrack_udp_timeout",
260 .maxlen = sizeof(unsigned int),
261 .mode = 0644,
262 .proc_handler = proc_dointvec_jiffies,
263 },
264 {
265 .procname = "nf_conntrack_udp_timeout_stream",
266 .maxlen = sizeof(unsigned int),
267 .mode = 0644,
268 .proc_handler = proc_dointvec_jiffies,
269 },
270 { }
271};
272#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
273static struct ctl_table udp_compat_sysctl_table[] = {
274 {
275 .procname = "ip_conntrack_udp_timeout",
276 .maxlen = sizeof(unsigned int),
277 .mode = 0644,
278 .proc_handler = proc_dointvec_jiffies,
279 },
280 {
281 .procname = "ip_conntrack_udp_timeout_stream",
282 .maxlen = sizeof(unsigned int),
283 .mode = 0644,
284 .proc_handler = proc_dointvec_jiffies,
285 },
286 { }
287};
288#endif
289#endif
290
291static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn,
292 struct nf_udp_net *un)
293{
294#ifdef CONFIG_SYSCTL
295 if (pn->ctl_table)
296 return 0;
297 pn->ctl_table = kmemdup(udp_sysctl_table,
298 sizeof(udp_sysctl_table),
299 GFP_KERNEL);
300 if (!pn->ctl_table)
301 return -ENOMEM;
302 pn->ctl_table[0].data = &un->timeouts[UDP_CT_UNREPLIED];
303 pn->ctl_table[1].data = &un->timeouts[UDP_CT_REPLIED];
304#endif
305 return 0;
306}
307
308static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn,
309 struct nf_udp_net *un)
310{
311#ifdef CONFIG_SYSCTL
312#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
313 pn->ctl_compat_table = kmemdup(udp_compat_sysctl_table,
314 sizeof(udp_compat_sysctl_table),
315 GFP_KERNEL);
316 if (!pn->ctl_compat_table)
317 return -ENOMEM;
318
319 pn->ctl_compat_table[0].data = &un->timeouts[UDP_CT_UNREPLIED];
320 pn->ctl_compat_table[1].data = &un->timeouts[UDP_CT_REPLIED];
321#endif
322#endif
323 return 0;
324}
325
326static int udp_init_net(struct net *net, u_int16_t proto)
327{
328 int ret;
329 struct nf_udp_net *un = udp_pernet(net);
330 struct nf_proto_net *pn = &un->pn;
331
332 if (!pn->users) {
333 int i;
334
335 for (i = 0; i < UDP_CT_MAX; i++)
336 un->timeouts[i] = udp_timeouts[i];
337 }
338
339 if (proto == AF_INET) {
340 ret = udp_kmemdup_compat_sysctl_table(pn, un);
341 if (ret < 0)
342 return ret;
343
344 ret = udp_kmemdup_sysctl_table(pn, un);
345 if (ret < 0)
346 nf_ct_kfree_compat_sysctl_table(pn);
347 } else
348 ret = udp_kmemdup_sysctl_table(pn, un);
349
350 return ret;
351}
352
353static struct nf_proto_net *udp_get_net_proto(struct net *net)
354{
355 return &net->ct.nf_ct_proto.udp.pn;
356}
357
358struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
359{
360 .l3proto = PF_INET,
361 .l4proto = IPPROTO_UDP,
362 .name = "udp",
363 .pkt_to_tuple = udp_pkt_to_tuple,
364 .invert_tuple = udp_invert_tuple,
365 .print_tuple = udp_print_tuple,
366 .packet = udp_packet,
367 .get_timeouts = udp_get_timeouts,
368 .new = udp_new,
369 .error = udp_error,
370#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
371 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
372 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
373 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
374 .nla_policy = nf_ct_port_nla_policy,
375#endif
376#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
377 .ctnl_timeout = {
378 .nlattr_to_obj = udp_timeout_nlattr_to_obj,
379 .obj_to_nlattr = udp_timeout_obj_to_nlattr,
380 .nlattr_max = CTA_TIMEOUT_UDP_MAX,
381 .obj_size = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
382 .nla_policy = udp_timeout_nla_policy,
383 },
384#endif
385 .init_net = udp_init_net,
386 .get_net_proto = udp_get_net_proto,
387};
388EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4);
389
390#ifdef CONFIG_NF_CT_PROTO_UDPLITE
391struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
392{
393 .l3proto = PF_INET,
394 .l4proto = IPPROTO_UDPLITE,
395 .name = "udplite",
396 .pkt_to_tuple = udp_pkt_to_tuple,
397 .invert_tuple = udp_invert_tuple,
398 .print_tuple = udp_print_tuple,
399 .packet = udp_packet,
400 .get_timeouts = udp_get_timeouts,
401 .new = udp_new,
402 .error = udplite_error,
403#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
404 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
405 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
406 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
407 .nla_policy = nf_ct_port_nla_policy,
408#endif
409#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
410 .ctnl_timeout = {
411 .nlattr_to_obj = udp_timeout_nlattr_to_obj,
412 .obj_to_nlattr = udp_timeout_obj_to_nlattr,
413 .nlattr_max = CTA_TIMEOUT_UDP_MAX,
414 .obj_size = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
415 .nla_policy = udp_timeout_nla_policy,
416 },
417#endif
418 .init_net = udp_init_net,
419 .get_net_proto = udp_get_net_proto,
420};
421EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite4);
422#endif
423
424struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =
425{
426 .l3proto = PF_INET6,
427 .l4proto = IPPROTO_UDP,
428 .name = "udp",
429 .pkt_to_tuple = udp_pkt_to_tuple,
430 .invert_tuple = udp_invert_tuple,
431 .print_tuple = udp_print_tuple,
432 .packet = udp_packet,
433 .get_timeouts = udp_get_timeouts,
434 .new = udp_new,
435 .error = udp_error,
436#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
437 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
438 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
439 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
440 .nla_policy = nf_ct_port_nla_policy,
441#endif
442#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
443 .ctnl_timeout = {
444 .nlattr_to_obj = udp_timeout_nlattr_to_obj,
445 .obj_to_nlattr = udp_timeout_obj_to_nlattr,
446 .nlattr_max = CTA_TIMEOUT_UDP_MAX,
447 .obj_size = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
448 .nla_policy = udp_timeout_nla_policy,
449 },
450#endif
451 .init_net = udp_init_net,
452 .get_net_proto = udp_get_net_proto,
453};
454EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6);
455
456#ifdef CONFIG_NF_CT_PROTO_UDPLITE
457struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
458{
459 .l3proto = PF_INET6,
460 .l4proto = IPPROTO_UDPLITE,
461 .name = "udplite",
462 .pkt_to_tuple = udp_pkt_to_tuple,
463 .invert_tuple = udp_invert_tuple,
464 .print_tuple = udp_print_tuple,
465 .packet = udp_packet,
466 .get_timeouts = udp_get_timeouts,
467 .new = udp_new,
468 .error = udplite_error,
469#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
470 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
471 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
472 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
473 .nla_policy = nf_ct_port_nla_policy,
474#endif
475#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
476 .ctnl_timeout = {
477 .nlattr_to_obj = udp_timeout_nlattr_to_obj,
478 .obj_to_nlattr = udp_timeout_obj_to_nlattr,
479 .nlattr_max = CTA_TIMEOUT_UDP_MAX,
480 .obj_size = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
481 .nla_policy = udp_timeout_nla_policy,
482 },
483#endif
484 .init_net = udp_init_net,
485 .get_net_proto = udp_get_net_proto,
486};
487EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite6);
488#endif
489