1/*
2 **************************************************************************
3 * Copyright (c) 2014-2015, The Linux Foundation.  All rights reserved.
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
16
17#include <linux/version.h>
18#include <linux/types.h>
19#include <linux/ip.h>
20#include <linux/tcp.h>
21#include <linux/module.h>
22#include <linux/skbuff.h>
23#include <linux/icmp.h>
24#include <linux/sysctl.h>
25#include <linux/kthread.h>
26#include <linux/device.h>
27#include <linux/fs.h>
28#include <linux/pkt_sched.h>
29#include <linux/string.h>
30#include <net/route.h>
31#include <net/ip.h>
32#include <net/tcp.h>
33#include <asm/unaligned.h>
34#include <asm/uaccess.h>	/* for put_user */
35#include <net/ipv6.h>
36#include <linux/inet.h>
37#include <linux/in.h>
38#include <linux/udp.h>
39#include <linux/tcp.h>
40
41#include <linux/netfilter_ipv4.h>
42#include <linux/netfilter_bridge.h>
43#include <net/netfilter/nf_conntrack.h>
44#include <net/netfilter/nf_conntrack_helper.h>
45#include <net/netfilter/nf_conntrack_l4proto.h>
46#include <net/netfilter/nf_conntrack_l3proto.h>
47#include <net/netfilter/nf_conntrack_core.h>
48#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
49#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
50
51/*
52 * Debug output levels
53 * 0 = OFF
54 * 1 = ASSERTS / ERRORS
55 * 2 = 1 + WARN
56 * 3 = 2 + INFO
57 * 4 = 3 + TRACE
58 */
59#define DEBUG_LEVEL ECM_TRACKER_UDP_DEBUG_LEVEL
60
61#include "ecm_types.h"
62#include "ecm_db_types.h"
63#include "ecm_state.h"
64#include "ecm_tracker.h"
65#include "ecm_tracker_udp.h"
66
67/*
68 * Magic numbers
69 */
70#define ECM_TRACKER_UDP_INSTANCE_MAGIC 0x7765
71#define ECM_TRACKER_UDP_SKB_CB_MAGIC 0xAAAB
72
73/*
74 * Useful constants
75 */
76#define ECM_TRACKER_UDP_HEADER_SIZE 8		/* UDP header is always 8 bytes RFC 768 Page 1 */
77
78#ifdef ECM_TRACKER_DPI_SUPPORT_ENABLE
79/*
80 * struct ecm_tracker_udp_skb_cb_format
81 *	Map of the cb[] array within our cached buffers - we use that area for our tracking
82 */
83struct ecm_tracker_udp_skb_cb_format {
84	uint32_t data_offset;			/* Offset in skb data to the actual datagram data - i.e. omitting headers */
85	uint32_t data_size;			/* Size of data */
86#if (DEBUG_LEVEL > 0)
87	uint16_t magic;
88#endif
89};
90#endif
91
92/*
93 * struct ecm_tracker_udp_internal_instance
94 */
95struct ecm_tracker_udp_internal_instance {
96	struct ecm_tracker_udp_instance udp_base;			/* MUST BE FIRST FIELD */
97
98#ifdef ECM_TRACKER_DPI_SUPPORT_ENABLE
99	/*
100	 * skb-next and skb->prev pointers are leveraged for these lists
101	 */
102	struct sk_buff *src_recvd_order;	/* sk buff list as sent by src */
103	struct sk_buff *src_recvd_order_last;	/* Last skb send - for fast appending of new buffers */
104	int32_t src_count;			/* Count of datagrams in list */
105	int32_t src_bytes_total;		/* Total bytes in all received datagrams */
106
107	struct sk_buff *dest_recvd_order;	/* sk buff list as sent by dest */
108	struct sk_buff *dest_recvd_order_last;	/* Last skb send - for fast appending of new buffers */
109	int32_t dest_count;			/* Count of datagrams in list */
110	int32_t dest_bytes_total;		/* Total bytes in all received datagrams */
111
112	int32_t data_limit;			/* Limit for tracked data */
113#endif
114
115	ecm_tracker_sender_state_t sender_state[ECM_TRACKER_SENDER_MAX];
116						/* State of each sender */
117	ecm_db_timer_group_t timer_group;	/* Recommended timer group for connection that is using this tracker */
118
119	spinlock_t lock;			/* lock */
120
121	int refs;				/* Integer to trap we never go negative */
122#if (DEBUG_LEVEL > 0)
123	uint16_t magic;
124#endif
125};
126
127int ecm_tracker_udp_count = 0;		/* Counts the number of UDP data trackers right now */
128static DEFINE_SPINLOCK(ecm_tracker_udp_lock);		/* Global lock for the tracker globals */
129
130/*
131 * ecm_trracker_udp_connection_state_matrix[][]
132 *	Matrix to convert from/to states to connection state
133 */
134static ecm_tracker_connection_state_t ecm_tracker_udp_connection_state_matrix[ECM_TRACKER_SENDER_STATE_MAX][ECM_TRACKER_SENDER_STATE_MAX] =
135{	/* 			Unknown						Establishing					Established					Closing					Closed					Fault */
136	/* Unknown */		{ECM_TRACKER_CONNECTION_STATE_ESTABLISHING,	ECM_TRACKER_CONNECTION_STATE_ESTABLISHING,	ECM_TRACKER_CONNECTION_STATE_ESTABLISHED,	ECM_TRACKER_CONNECTION_STATE_FAULT,	ECM_TRACKER_CONNECTION_STATE_FAULT,	ECM_TRACKER_CONNECTION_STATE_FAULT},
137	/* Establishing */	{ECM_TRACKER_CONNECTION_STATE_ESTABLISHING,	ECM_TRACKER_CONNECTION_STATE_ESTABLISHING,	ECM_TRACKER_CONNECTION_STATE_ESTABLISHED,	ECM_TRACKER_CONNECTION_STATE_FAULT,	ECM_TRACKER_CONNECTION_STATE_FAULT,	ECM_TRACKER_CONNECTION_STATE_FAULT},
138	/* Established */	{ECM_TRACKER_CONNECTION_STATE_ESTABLISHED,	ECM_TRACKER_CONNECTION_STATE_ESTABLISHED,	ECM_TRACKER_CONNECTION_STATE_ESTABLISHED,	ECM_TRACKER_CONNECTION_STATE_CLOSING,	ECM_TRACKER_CONNECTION_STATE_CLOSING,	ECM_TRACKER_CONNECTION_STATE_FAULT},
139	/* Closing */		{ECM_TRACKER_CONNECTION_STATE_FAULT,		ECM_TRACKER_CONNECTION_STATE_FAULT,		ECM_TRACKER_CONNECTION_STATE_CLOSING,		ECM_TRACKER_CONNECTION_STATE_CLOSING,	ECM_TRACKER_CONNECTION_STATE_CLOSING,	ECM_TRACKER_CONNECTION_STATE_FAULT},
140	/* Closed */		{ECM_TRACKER_CONNECTION_STATE_FAULT,		ECM_TRACKER_CONNECTION_STATE_FAULT,		ECM_TRACKER_CONNECTION_STATE_CLOSING,		ECM_TRACKER_CONNECTION_STATE_CLOSING,	ECM_TRACKER_CONNECTION_STATE_CLOSED, 	ECM_TRACKER_CONNECTION_STATE_FAULT},
141	/* Fault */		{ECM_TRACKER_CONNECTION_STATE_FAULT,		ECM_TRACKER_CONNECTION_STATE_FAULT,		ECM_TRACKER_CONNECTION_STATE_FAULT,		ECM_TRACKER_CONNECTION_STATE_FAULT,	ECM_TRACKER_CONNECTION_STATE_FAULT,	ECM_TRACKER_CONNECTION_STATE_FAULT},
142};
143
144/*
145 * ecm_tracker_udp_check_header_and_read()
146 *	Check for validly sized header and read the udp protocol header
147 */
148struct udphdr *ecm_tracker_udp_check_header_and_read(struct sk_buff *skb, struct ecm_tracker_ip_header *ip_hdr, struct udphdr *port_buffer)
149{
150	struct ecm_tracker_ip_protocol_header *header;
151
152	/*
153	 * Is there a UDP header?
154	 */
155	header = &ip_hdr->headers[ECM_TRACKER_IP_PROTOCOL_TYPE_UDP];
156	if (header->header_size != ECM_TRACKER_UDP_HEADER_SIZE) {
157		DEBUG_WARN("Skb: %p, UDP header size bad %u\n", skb, header->header_size);
158		return NULL;
159	}
160
161	return skb_header_pointer(skb, header->offset, sizeof(*port_buffer), port_buffer);
162}
163EXPORT_SYMBOL(ecm_tracker_udp_check_header_and_read);
164
165#ifdef ECM_TRACKER_DPI_SUPPORT_ENABLE
166/*
167 * ecm_tracker_udp_datagram_discard()
168 *	Discard n number of datagrams at the head of the datagram list that were sent to the target
169 */
170static void ecm_tracker_udp_datagram_discard(struct ecm_tracker_udp_internal_instance *utii, ecm_tracker_sender_type_t sender, int32_t n)
171{
172	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
173
174	DEBUG_TRACE("%p: discard %u datagrams for %d\n", utii, n, sender);
175
176	/*
177	 * Which list?
178	 */
179	if (sender == ECM_TRACKER_SENDER_TYPE_SRC) {
180		/*
181		 * iterate n times and discard the buffers
182		 */
183		while (n) {
184			struct sk_buff *skb;
185
186			spin_lock_bh(&utii->lock);
187
188			skb = utii->src_recvd_order;
189			DEBUG_ASSERT(skb, "%p: bad list\n", utii);
190
191			utii->src_recvd_order = skb->next;
192			if (!utii->src_recvd_order) {
193				DEBUG_ASSERT(utii->src_recvd_order_last == skb, "%p: bad list\n", utii);
194				utii->src_recvd_order_last = NULL;
195			} else {
196				utii->src_recvd_order->prev = NULL;
197			}
198
199			utii->src_count--;
200			DEBUG_ASSERT(utii->src_count >= 0, "%p: bad total\n", utii);
201			utii->src_bytes_total -= skb->truesize;
202			ecm_tracker_data_total_decrease(skb->len, skb->truesize);
203			DEBUG_ASSERT(utii->src_bytes_total >= 0, "%p: bad bytes total\n", utii);
204
205			spin_unlock_bh(&utii->lock);
206			kfree_skb(skb);
207
208			n--;
209		}
210		return;
211	}
212
213	/*
214	 * iterate n times and discard the buffers
215	 */
216	while (n) {
217		struct sk_buff *skb;
218
219		spin_lock_bh(&utii->lock);
220
221		skb = utii->dest_recvd_order;
222		DEBUG_ASSERT(skb, "%p: bad list\n", utii);
223
224		utii->dest_recvd_order = skb->next;
225		if (!utii->dest_recvd_order) {
226			DEBUG_ASSERT(utii->dest_recvd_order_last == skb, "%p: bad list\n", utii);
227			utii->dest_recvd_order_last = NULL;
228		} else {
229			utii->dest_recvd_order->prev = NULL;
230		}
231
232		utii->dest_count--;
233		DEBUG_ASSERT(utii->dest_count >= 0, "%p: bad total\n", utii);
234		utii->dest_bytes_total -= skb->truesize;
235		ecm_tracker_data_total_decrease(skb->len, skb->truesize);
236		DEBUG_ASSERT(utii->dest_bytes_total >= 0, "%p: bad bytes total\n", utii);
237
238		spin_unlock_bh(&utii->lock);
239		kfree_skb(skb);
240
241		n--;
242	}
243}
244
245/*
246 * ecm_tracker_udp_discard_all()
247 *	Discard all tracked data
248 */
249void ecm_tracker_udp_discard_all(struct ecm_tracker_udp_internal_instance *utii)
250{
251	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
252
253	/*
254	 * Destroy all datagrams
255	 */
256	DEBUG_TRACE("%p: destroy all\n", utii);
257	ecm_tracker_udp_datagram_discard(utii, ECM_TRACKER_SENDER_TYPE_SRC, utii->src_count);
258	ecm_tracker_udp_datagram_discard(utii, ECM_TRACKER_SENDER_TYPE_DEST, utii->dest_count);
259}
260
261/*
262 * ecm_tracker_udp_discard_all_callback()
263 *	Discard all tracked data
264 */
265static void ecm_tracker_udp_discard_all_callback(struct ecm_tracker_instance *ti)
266{
267	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
268	ecm_tracker_udp_discard_all(utii);
269}
270#endif
271
272/*
273 * ecm_tracker_udp_ref()
274 */
275static void ecm_tracker_udp_ref(struct ecm_tracker_udp_internal_instance *utii)
276{
277	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
278
279	spin_lock_bh(&utii->lock);
280
281	utii->refs++;
282	DEBUG_ASSERT(utii->refs > 0, "%p: ref wrap", utii);
283	DEBUG_TRACE("%p: ref %d\n", utii, utii->refs);
284
285	spin_unlock_bh(&utii->lock);
286}
287
288/*
289 * ecm_tracker_udp_ref_callback()
290 */
291void ecm_tracker_udp_ref_callback(struct ecm_tracker_instance *ti)
292{
293	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
294	ecm_tracker_udp_ref(utii);
295}
296
297/*
298 * ecm_tracker_udp_deref()
299 */
300static int ecm_tracker_udp_deref(struct ecm_tracker_udp_internal_instance *utii)
301{
302	int refs;
303	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
304
305	spin_lock_bh(&utii->lock);
306	utii->refs--;
307	refs = utii->refs;
308	DEBUG_ASSERT(utii->refs >= 0, "%p: ref wrap", utii);
309	DEBUG_TRACE("%p: deref %d\n", utii, utii->refs);
310
311	if (utii->refs > 0) {
312		spin_unlock_bh(&utii->lock);
313		return refs;
314	}
315	spin_unlock_bh(&utii->lock);
316
317	DEBUG_TRACE("%p: final\n", utii);
318
319#ifdef ECM_TRACKER_DPI_SUPPORT_ENABLE
320	/*
321	 * Destroy all datagrams
322	 */
323	ecm_tracker_udp_datagram_discard(utii, ECM_TRACKER_SENDER_TYPE_SRC, utii->src_count);
324	ecm_tracker_udp_datagram_discard(utii, ECM_TRACKER_SENDER_TYPE_DEST, utii->dest_count);
325#endif
326
327	spin_lock_bh(&ecm_tracker_udp_lock);
328	ecm_tracker_udp_count--;
329	DEBUG_ASSERT(ecm_tracker_udp_count >= 0, "%p: tracker count wrap", utii);
330	spin_unlock_bh(&ecm_tracker_udp_lock);
331
332	DEBUG_INFO("%p: Udp tracker final\n", utii);
333	DEBUG_CLEAR_MAGIC(utii);
334	kfree(utii);
335
336	return 0;
337}
338
339/*
340 * _ecm_tracker_udp_deref_callback()
341 */
342int ecm_tracker_udp_deref_callback(struct ecm_tracker_instance *ti)
343{
344	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
345	return ecm_tracker_udp_deref(utii);
346}
347
348#ifdef ECM_TRACKER_DPI_SUPPORT_ENABLE
349/*
350 * ecm_tracker_udp_datagram_count_get()
351 *	Return number of available datagrams sent to the specified target
352 */
353static int32_t ecm_tracker_udp_datagram_count_get(struct ecm_tracker_udp_internal_instance *utii, ecm_tracker_sender_type_t sender)
354{
355	int32_t count;
356
357	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
358
359	/*
360	 * Which list?
361	 */
362	spin_lock_bh(&utii->lock);
363	if (sender == ECM_TRACKER_SENDER_TYPE_SRC) {
364		count = utii->src_count;
365	} else {
366		count = utii->dest_count;
367	}
368	spin_unlock_bh(&utii->lock);
369
370	DEBUG_TRACE("%p: datagram count get for %d is %d\n", utii, sender, count);
371
372	return count;
373}
374
375/*
376 * ecm_tracker_udp_datagram_count_get_callback()
377 *	Return number of available datagrams sent to the specified target
378 */
379static int32_t ecm_tracker_udp_datagram_count_get_callback(struct ecm_tracker_instance *ti, ecm_tracker_sender_type_t sender)
380{
381	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
382	return ecm_tracker_udp_datagram_count_get(utii, sender);
383}
384
385/*
386 * ecm_tracker_udp_datagram_discard_callback()
387 *	Discard n number of datagrams at the head of the datagram list that were sent to the target
388 */
389static void ecm_tracker_udp_datagram_discard_callback(struct ecm_tracker_instance *ti, ecm_tracker_sender_type_t sender, int32_t n)
390{
391	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
392
393	ecm_tracker_udp_datagram_discard(utii, sender, n);
394}
395
396/*
397 * ecm_tracker_udp_datagram_size_get()
398 *	Return size in bytes of datagram at index i that was sent to the target
399 */
400int32_t ecm_tracker_udp_datagram_size_get(struct ecm_tracker_udp_instance *uti, ecm_tracker_sender_type_t sender, int32_t i)
401{
402	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)uti;
403	int32_t size;
404	struct sk_buff *skb;
405	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
406
407	/*
408	 * Which list?
409	 */
410	spin_lock_bh(&utii->lock);
411	if (sender == ECM_TRACKER_SENDER_TYPE_SRC) {
412		skb = utii->src_recvd_order;
413	} else {
414		skb = utii->dest_recvd_order;
415	}
416
417	/*
418	 * Iterate to the i'th datagram
419	 */
420	while (i) {
421		DEBUG_ASSERT(skb, "%p: index bad\n", utii);
422		skb = skb->next;
423		i--;
424	}
425	DEBUG_ASSERT(skb, "%p: index bad\n", utii);
426
427	size = skb->len;
428
429	spin_unlock_bh(&utii->lock);
430	return size;
431}
432
433/*
434 * ecm_tracker_udp_datagram_size_get_callback()
435 *	Return size in bytes of datagram at index i that was sent to the target
436 */
437static int32_t ecm_tracker_udp_datagram_size_get_callback(struct ecm_tracker_instance *ti, ecm_tracker_sender_type_t sender, int32_t i)
438{
439	struct ecm_tracker_udp_instance *uti = (struct ecm_tracker_udp_instance *)ti;
440
441	return ecm_tracker_udp_datagram_size_get(uti, sender, i);
442}
443
444/*
445 * ecm_tracker_udp_datagram_read()
446 *	Read size bytes from datagram at index i into the buffer
447 */
448int ecm_tracker_udp_datagram_read(struct ecm_tracker_udp_instance *uti, ecm_tracker_sender_type_t sender, int32_t i, int32_t offset, int32_t size, void *buffer)
449{
450	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)uti;
451	int res;
452	struct sk_buff *skb;
453	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
454	DEBUG_TRACE("%p: datagram %d read at offset %d for %d bytes for %d\n", utii, i, offset, size, sender);
455
456	/*
457	 * Which list?
458	 */
459	spin_lock_bh(&utii->lock);
460	if (sender == ECM_TRACKER_SENDER_TYPE_SRC) {
461		skb = utii->src_recvd_order;
462	} else {
463		skb = utii->dest_recvd_order;
464	}
465
466	/*
467	 * Iterate to the i'th datagram
468	 */
469	while (i) {
470		DEBUG_ASSERT(skb, "%p: index bad\n", utii);
471		skb = skb->next;
472		i--;
473	}
474	DEBUG_ASSERT(skb, "%p: index bad\n", utii);
475
476	/*
477	 * Perform read
478	 */
479	res = skb_copy_bits(skb, offset, buffer, (unsigned int)size);
480
481	spin_unlock_bh(&utii->lock);
482
483	return res;
484}
485
486/*
487 * ecm_tracker_udp_datagram_read_callback()
488 *	Read size bytes from datagram at index i into the buffer
489 */
490static int ecm_tracker_udp_datagram_read_callback(struct ecm_tracker_instance *ti, ecm_tracker_sender_type_t sender, int32_t i, int32_t offset, int32_t size, void *buffer)
491{
492	struct ecm_tracker_udp_instance *uti = (struct ecm_tracker_udp_instance *)ti;
493
494	return ecm_tracker_udp_datagram_read(uti, sender, i, offset, size, buffer);
495}
496
497/*
498 * ecm_tracker_udp_data_total_get_callback()
499 *	Return total tracked data
500 */
501static int32_t ecm_tracker_udp_data_total_get_callback(struct ecm_tracker_instance *ti)
502{
503	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
504	int32_t data_total;
505
506	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
507
508	spin_lock_bh(&utii->lock);
509	data_total = utii->src_bytes_total + utii->dest_bytes_total;
510	spin_unlock_bh(&utii->lock);
511
512	return data_total;
513}
514
515/*
516 * ecm_tracker_udp_data_limit_get_callback()
517 *	Return tracked data limit
518 */
519static int32_t ecm_tracker_udp_data_limit_get_callback(struct ecm_tracker_instance *ti)
520{
521	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
522	int32_t data_limit;
523
524	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
525
526	spin_lock_bh(&utii->lock);
527	data_limit = utii->data_limit;
528	spin_unlock_bh(&utii->lock);
529
530	return data_limit;
531}
532
533/*
534 * ecm_tracker_udp_data_limit_set_callback()
535 *	Set tracked data limit
536 */
537static void ecm_tracker_udp_data_limit_set_callback(struct ecm_tracker_instance *ti, int32_t data_limit)
538{
539	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
540
541	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
542
543	spin_lock_bh(&utii->lock);
544	utii->data_limit = data_limit;
545	spin_unlock_bh(&utii->lock);
546}
547
548/*
549 * ecm_tracker_udp_datagram_add()
550 *	Append the datagram onto the tracker queue for the given target
551 */
552static bool ecm_tracker_udp_datagram_add(struct ecm_tracker_udp_internal_instance *utii, ecm_tracker_sender_type_t sender,
553								struct ecm_tracker_ip_header *ip_hdr, struct ecm_tracker_ip_protocol_header *ecm_udp_header,
554								struct udphdr *udp_header, struct sk_buff *skb)
555{
556	struct sk_buff *skbc;
557	struct ecm_tracker_udp_skb_cb_format *skbc_cb;
558
559	DEBUG_TRACE("%p: datagram %p add for %d, ip_hdr_len %u, total len: %u, offset: %u, size: %u\n",
560			utii, skb, sender, ip_hdr->ip_header_length, ip_hdr->total_length,
561			ecm_udp_header->offset, ecm_udp_header->size);
562
563	/*
564	 * Clone the packet
565	 */
566	skbc = skb_clone(skb, GFP_ATOMIC | __GFP_NOWARN);
567	if (!skbc) {
568		DEBUG_WARN("%p: Failed to clone packet %p\n", utii, skb);
569		return false;
570	}
571
572	DEBUG_TRACE("%p: cloned %p to %p\n", utii, skb, skbc);
573
574	/*
575	 * Get the private cb area and initialise it.
576	 * ALL DATAGRAMS HAVE TO HAVE ONE.
577	 */
578	skbc_cb = (struct ecm_tracker_udp_skb_cb_format *)skbc->cb;
579	DEBUG_SET_MAGIC(skbc_cb, ECM_TRACKER_UDP_SKB_CB_MAGIC);
580	skbc_cb->data_offset = ecm_udp_header->offset + ecm_udp_header->header_size;
581	if (ip_hdr->total_length < (ecm_udp_header->offset + ecm_udp_header->size)) {
582		DEBUG_WARN("%p: Invalid headers\n", utii);
583		kfree_skb(skbc);
584		return false;
585	}
586	skbc_cb->data_size = ecm_udp_header->size - ecm_udp_header->header_size;
587
588	/*
589	 * Are we within instance limit?
590	 */
591	spin_lock_bh(&utii->lock);
592	DEBUG_ASSERT((utii->src_bytes_total + utii->dest_bytes_total + skbc->truesize) > 0, "%p: bad total\n", utii);
593	if ((utii->src_bytes_total + utii->dest_bytes_total + skbc->truesize) > utii->data_limit) {
594		DEBUG_TRACE("%p: over limit\n", utii);
595		spin_unlock_bh(&utii->lock);
596		kfree_skb(skbc);
597		return false;
598	}
599
600	/*
601	 * Within global limit?
602	 */
603	if (!ecm_tracker_data_total_increase(skbc->len, skbc->truesize)) {
604		DEBUG_TRACE("%p: over global limit\n", utii);
605		spin_unlock_bh(&utii->lock);
606		kfree_skb(skbc);
607		return false;
608	}
609
610	/*
611	 * Which list to insert the datagram in to?
612	 */
613	if (sender == ECM_TRACKER_SENDER_TYPE_SRC) {
614		skbc->next = NULL;
615		skbc->prev = utii->src_recvd_order_last;
616		utii->src_recvd_order_last = skbc;
617		if (skbc->prev) {
618			skbc->prev->next = skbc;
619		} else {
620			DEBUG_ASSERT(utii->src_recvd_order == NULL, "%p: bad list\n", utii);
621			utii->src_recvd_order = skbc;
622		}
623
624		utii->src_count++;
625		DEBUG_ASSERT(utii->src_count > 0, "%p: bad total\n", utii);
626		utii->src_bytes_total += skbc->truesize;
627		spin_unlock_bh(&utii->lock);
628		return true;
629	}
630
631	skbc->next = NULL;
632	skbc->prev = utii->dest_recvd_order_last;
633	utii->dest_recvd_order_last = skbc;
634	if (skbc->prev) {
635		skbc->prev->next = skbc;
636	} else {
637		DEBUG_ASSERT(utii->dest_recvd_order == NULL, "%p: bad list\n", utii);
638		utii->dest_recvd_order = skbc;
639	}
640
641	utii->dest_count++;
642	DEBUG_ASSERT(utii->dest_count > 0, "%p: bad total\n", utii);
643	utii->dest_bytes_total += skbc->truesize;
644	spin_unlock_bh(&utii->lock);
645	return true;
646}
647
648/*
649 * _ecm_tracker_udp_datagram_add_callback()
650 *	Append the datagram onto the tracker queue for the given target
651 */
652static bool ecm_tracker_udp_datagram_add_callback(struct ecm_tracker_instance *ti, ecm_tracker_sender_type_t sender, struct sk_buff *skb)
653{
654	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
655	struct ecm_tracker_ip_header ip_hdr;
656	struct ecm_tracker_ip_protocol_header *ecm_udp_header;
657	struct udphdr *udp_header;
658	struct udphdr udp_header_buffer;
659
660	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
661
662	/*
663	 * Obtain the IP header from the skb
664	 */
665	if (!ecm_tracker_ip_check_header_and_read(&ip_hdr, skb)) {
666		DEBUG_WARN("%p: no ip_hdr for %p\n", utii, skb);
667		return false;
668	}
669
670	/*
671	 * Get UDP header
672	 */
673	udp_header = ecm_tracker_udp_check_header_and_read(skb, &ip_hdr, &udp_header_buffer);
674	if (!udp_header) {
675		DEBUG_WARN("%p: not/invalid udp %d\n", utii, ip_hdr.protocol);
676		return false;
677	}
678	ecm_udp_header = &ip_hdr.headers[ECM_TRACKER_IP_PROTOCOL_TYPE_UDP];
679
680	return ecm_tracker_udp_datagram_add(utii, sender, &ip_hdr, ecm_udp_header, udp_header, skb);
681}
682
683/*
684 * ecm_tracker_udp_datagram_add_checked_callback()
685 *	Add a pre-checked datagram
686 */
687static bool ecm_tracker_udp_datagram_add_checked_callback(struct ecm_tracker_udp_instance *uti, ecm_tracker_sender_type_t sender,
688								struct ecm_tracker_ip_header *ip_hdr, struct ecm_tracker_ip_protocol_header *ecm_udp_header,
689								struct udphdr *udp_header, struct sk_buff *skb)
690{
691	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)uti;
692	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
693	return ecm_tracker_udp_datagram_add(utii, sender, ip_hdr, ecm_udp_header, udp_header, skb);
694}
695
696/*
697 * ecm_tracker_udp_data_read_callback()
698 *	Return size bytes of datagram data at index i that was sent to the target
699 */
700static int ecm_tracker_udp_data_read_callback(struct ecm_tracker_udp_instance *uti, ecm_tracker_sender_type_t sender, int32_t i,
701								int32_t offset, int32_t size, void *buffer)
702
703{
704	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)uti;
705	int res;
706	struct sk_buff *skb;
707	struct ecm_tracker_udp_skb_cb_format *skb_cb;
708
709	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
710	DEBUG_TRACE("%p: datagram data %d read at offset %d for %d bytes for %d\n", utii, i, offset, size, sender);
711
712	/*
713	 * Which list?
714	 */
715	spin_lock_bh(&utii->lock);
716	if (sender == ECM_TRACKER_SENDER_TYPE_SRC) {
717		skb = utii->src_recvd_order;
718	} else {
719		skb = utii->dest_recvd_order;
720	}
721
722	/*
723	 * Iterate to the i'th datagram
724	 */
725	while (i) {
726		DEBUG_ASSERT(skb, "%p: index bad\n", utii);
727		skb = skb->next;
728		i--;
729	}
730	DEBUG_ASSERT(skb, "%p: index bad\n", utii);
731
732	/*
733	 * Perform read of data excluding headers
734	 */
735	skb_cb = (struct ecm_tracker_udp_skb_cb_format *)skb->cb;
736	DEBUG_CHECK_MAGIC(skb_cb, ECM_TRACKER_UDP_SKB_CB_MAGIC, "%p: invalid cb magic %p\n", utii, skb);
737	offset += skb_cb->data_offset;
738	DEBUG_ASSERT(size <= skb_cb->data_size, "%p: size %d too large for skb %p at %u\n", utii, size, skb, skb_cb->data_size);
739	res = skb_copy_bits(skb, offset, buffer, (unsigned int)size);
740
741	spin_unlock_bh(&utii->lock);
742
743	return res;
744}
745
746/*
747 * ecm_tracker_udp_data_size_get_callback()
748 *	Read size in bytes of data at index i into the buffer
749 */
750static int32_t ecm_tracker_udp_data_size_get_callback(struct ecm_tracker_udp_instance *uti, ecm_tracker_sender_type_t sender, int32_t i)
751{
752	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)uti;
753	int32_t size;
754	struct sk_buff *skb;
755	struct ecm_tracker_udp_skb_cb_format *skb_cb;
756
757	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
758	DEBUG_TRACE("%p: datagram %u data size get for %d\n", utii, i, sender);
759
760	/*
761	 * Which list?
762	 */
763	spin_lock_bh(&utii->lock);
764	if (sender == ECM_TRACKER_SENDER_TYPE_SRC) {
765		skb = utii->src_recvd_order;
766	} else {
767		skb = utii->dest_recvd_order;
768	}
769
770	/*
771	 * Iterate to the i'th datagram
772	 */
773	while (i) {
774		DEBUG_ASSERT(skb, "%p: index bad\n", utii);
775		skb = skb->next;
776		i--;
777	}
778	DEBUG_ASSERT(skb, "%p: index bad\n", utii);
779
780	/*
781	 * Perform read of data excluding headers
782	 */
783	skb_cb = (struct ecm_tracker_udp_skb_cb_format *)skb->cb;
784	DEBUG_CHECK_MAGIC(skb_cb, ECM_TRACKER_UDP_SKB_CB_MAGIC, "%p: invalid cb magic %p\n", utii, skb);
785	size = skb_cb->data_size;
786	spin_unlock_bh(&utii->lock);
787
788	return size;
789}
790#endif
791
792/*
793 * ecm_tracker_udp_state_update_callback()
794 * 	Update connection state based on the knowledge we have and the skb given
795 */
796static void ecm_tracker_udp_state_update_callback(struct ecm_tracker_instance *ti, ecm_tracker_sender_type_t sender, struct ecm_tracker_ip_header *ip_hdr, struct sk_buff *skb)
797{
798	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
799	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
800
801	/*
802	 * As long as a sender has seen data then we consider the sender established
803	 */
804	spin_lock_bh(&utii->lock);
805	utii->sender_state[sender] = ECM_TRACKER_SENDER_STATE_ESTABLISHED;
806	spin_unlock_bh(&utii->lock);
807}
808
809/*
810 * ecm_tracker_udp_state_get_callback()
811 * 	Get state
812 */
813static void ecm_tracker_udp_state_get_callback(struct ecm_tracker_instance *ti, ecm_tracker_sender_state_t *src_state,
814					ecm_tracker_sender_state_t *dest_state, ecm_tracker_connection_state_t *state, ecm_db_timer_group_t *tg)
815{
816	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
817	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
818	spin_lock_bh(&utii->lock);
819	*src_state = utii->sender_state[ECM_TRACKER_SENDER_TYPE_SRC];
820	*dest_state = utii->sender_state[ECM_TRACKER_SENDER_TYPE_DEST];
821	*tg = utii->timer_group;
822	spin_unlock_bh(&utii->lock);
823	*state = ecm_tracker_udp_connection_state_matrix[*src_state][*dest_state];
824}
825
826#ifdef ECM_STATE_OUTPUT_ENABLE
827/*
828 * ecm_tracker_udp_state_text_get_callback()
829 *	Return state
830 */
831static int ecm_tracker_udp_state_text_get_callback(struct ecm_tracker_instance *ti, struct ecm_state_file_instance *sfi)
832{
833	int result;
834	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)ti;
835#ifdef ECM_TRACKER_DPI_SUPPORT_ENABLE
836	int32_t src_count;
837	int32_t src_bytes_total;
838	int32_t dest_count;
839	int32_t dest_bytes_total;
840	int32_t data_limit;
841#endif
842	ecm_db_timer_group_t timer_group;
843	ecm_tracker_sender_state_t sender_state[ECM_TRACKER_SENDER_MAX];
844	ecm_tracker_connection_state_t connection_state;
845	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
846
847	if ((result = ecm_state_prefix_add(sfi, "tracker_udp"))) {
848		return result;
849	}
850
851	/*
852	 * Capture state
853	 */
854	spin_lock_bh(&utii->lock);
855#ifdef ECM_TRACKER_DPI_SUPPORT_ENABLE
856	src_count = utii->src_count;
857	src_bytes_total = utii->src_bytes_total;
858	dest_count = utii->dest_count;
859	dest_bytes_total = utii->dest_bytes_total;
860	data_limit = utii->data_limit;
861#endif
862	sender_state[ECM_TRACKER_SENDER_TYPE_SRC] = utii->sender_state[ECM_TRACKER_SENDER_TYPE_SRC];
863	sender_state[ECM_TRACKER_SENDER_TYPE_DEST] = utii->sender_state[ECM_TRACKER_SENDER_TYPE_DEST];
864	timer_group = utii->timer_group;
865	spin_unlock_bh(&utii->lock);
866	connection_state = ecm_tracker_udp_connection_state_matrix[sender_state[ECM_TRACKER_SENDER_TYPE_SRC]][sender_state[ECM_TRACKER_SENDER_TYPE_DEST]];
867
868#ifdef ECM_TRACKER_DPI_SUPPORT_ENABLE
869	if ((result = ecm_state_write(sfi, "src_count", "%d", src_count))) {
870		return result;
871	}
872	if ((result = ecm_state_write(sfi, "src_bytes_total", "%d", src_bytes_total))) {
873		return result;
874	}
875	if ((result = ecm_state_write(sfi, "dest_count", "%d", dest_count))) {
876		return result;
877	}
878	if ((result = ecm_state_write(sfi, "dest_bytes_total", "%d", dest_bytes_total))) {
879		return result;
880	}
881	if ((result = ecm_state_write(sfi, "data_limit", "%d", data_limit))) {
882		return result;
883	}
884#endif
885
886	connection_state = ecm_tracker_udp_connection_state_matrix[sender_state[ECM_TRACKER_SENDER_TYPE_SRC]][sender_state[ECM_TRACKER_SENDER_TYPE_DEST]];
887	if ((result = ecm_state_write(sfi, "timer_group", "%d", ECM_DB_TIMER_GROUPS_CONNECTION_GENERIC_TIMEOUT))) {
888		return result;
889	}
890	if ((result = ecm_state_write(sfi, "src_sender_state", "%s", ecm_tracker_sender_state_to_string(sender_state[ECM_TRACKER_SENDER_TYPE_SRC])))) {
891		return result;
892	}
893	if ((result = ecm_state_write(sfi, "dest_sender_state", "%s", ecm_tracker_sender_state_to_string(sender_state[ECM_TRACKER_SENDER_TYPE_DEST])))) {
894		return result;
895	}
896	if ((result = ecm_state_write(sfi, "connection_state", "%s", ecm_tracker_connection_state_to_string(connection_state)))) {
897		return result;
898	}
899
900 	return ecm_state_prefix_remove(sfi);
901}
902#endif
903
904/*
905 * ecm_tracker_udp_init()
906 *	Initialise the two host addresses that define the two directions we track data for
907 */
908void ecm_tracker_udp_init(struct ecm_tracker_udp_instance *uti, int32_t data_limit, int src_port, int dest_port)
909{
910	struct ecm_tracker_udp_internal_instance *utii = (struct ecm_tracker_udp_internal_instance *)uti;
911	DEBUG_CHECK_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC, "%p: magic failed", utii);
912	DEBUG_TRACE("%p: init udp tracker\n", utii);
913
914	spin_lock_bh(&utii->lock);
915#ifdef ECM_TRACKER_DPI_SUPPORT_ENABLE
916	utii->data_limit = data_limit;
917#endif
918	if ((src_port < 1024) || (dest_port < 1024)) {
919		/*
920		 * Because UDP connections can be reaped we assign well known ports to the WKP timer group.
921		 * The WKP group is not reaped thus preserving connections involving known services.
922		 * NOTE: Classifiers are still free to change the group as they see fit.
923		 */
924		utii->timer_group = ECM_DB_TIMER_GROUPS_CONNECTION_UDP_WKP_TIMEOUT;
925		spin_unlock_bh(&utii->lock);
926		return;
927	}
928	utii->timer_group = ECM_DB_TIMER_GROUPS_CONNECTION_UDP_GENERIC_TIMEOUT;
929	spin_unlock_bh(&utii->lock);
930}
931EXPORT_SYMBOL(ecm_tracker_udp_init);
932
933/*
934 * ecm_tracker_udp_alloc()
935 */
936struct ecm_tracker_udp_instance *ecm_tracker_udp_alloc(void)
937{
938	struct ecm_tracker_udp_internal_instance *utii;
939
940	utii = (struct ecm_tracker_udp_internal_instance *)kzalloc(sizeof(struct ecm_tracker_udp_internal_instance), GFP_ATOMIC | __GFP_NOWARN);
941	if (!utii) {
942		DEBUG_WARN("Failed to allocate udp tracker instance\n");
943		return NULL;
944	}
945
946	utii->udp_base.base.ref = ecm_tracker_udp_ref_callback;
947	utii->udp_base.base.deref = ecm_tracker_udp_deref_callback;
948	utii->udp_base.base.state_update = ecm_tracker_udp_state_update_callback;
949	utii->udp_base.base.state_get = ecm_tracker_udp_state_get_callback;
950#ifdef ECM_TRACKER_DPI_SUPPORT_ENABLE
951	utii->udp_base.base.datagram_count_get = ecm_tracker_udp_datagram_count_get_callback;
952	utii->udp_base.base.datagram_discard = ecm_tracker_udp_datagram_discard_callback;
953	utii->udp_base.base.datagram_read = ecm_tracker_udp_datagram_read_callback;
954	utii->udp_base.base.datagram_size_get = ecm_tracker_udp_datagram_size_get_callback;
955	utii->udp_base.base.datagram_add = ecm_tracker_udp_datagram_add_callback;
956	utii->udp_base.base.discard_all = ecm_tracker_udp_discard_all_callback;
957	utii->udp_base.base.data_total_get = ecm_tracker_udp_data_total_get_callback;
958	utii->udp_base.base.data_limit_get = ecm_tracker_udp_data_limit_get_callback;
959	utii->udp_base.base.data_limit_set = ecm_tracker_udp_data_limit_set_callback;
960
961	utii->udp_base.data_read = ecm_tracker_udp_data_read_callback;
962	utii->udp_base.data_size_get = ecm_tracker_udp_data_size_get_callback;
963	utii->udp_base.datagram_add = ecm_tracker_udp_datagram_add_checked_callback;
964#endif
965#ifdef ECM_STATE_OUTPUT_ENABLE
966	utii->udp_base.base.state_text_get = ecm_tracker_udp_state_text_get_callback;
967#endif
968
969	spin_lock_init(&utii->lock);
970
971	utii->refs = 1;
972	DEBUG_SET_MAGIC(utii, ECM_TRACKER_UDP_INSTANCE_MAGIC);
973
974	spin_lock_bh(&ecm_tracker_udp_lock);
975	ecm_tracker_udp_count++;
976	DEBUG_ASSERT(ecm_tracker_udp_count > 0, "%p: udp tracker count wrap\n", utii);
977	spin_unlock_bh(&ecm_tracker_udp_lock);
978
979	DEBUG_TRACE("UDP tracker created %p\n", utii);
980	return (struct ecm_tracker_udp_instance *)utii;
981}
982EXPORT_SYMBOL(ecm_tracker_udp_alloc);
983