1/*
2 **************************************************************************
3 * Copyright (c) 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/module.h>
21#include <linux/kthread.h>
22#include <linux/string.h>
23#include <linux/debugfs.h>
24#include <asm/unaligned.h>
25#include <asm/uaccess.h>	/* for put_user */
26#include <linux/inet.h>
27#include <linux/ipv6.h>
28#include <linux/netfilter_bridge.h>
29
30/*
31 * Debug output levels
32 * 0 = OFF
33 * 1 = ASSERTS / ERRORS
34 * 2 = 1 + WARN
35 * 3 = 2 + INFO
36 * 4 = 3 + TRACE
37 */
38#define DEBUG_LEVEL ECM_STATE_DEBUG_LEVEL
39
40#include "ecm_types.h"
41#include "ecm_db_types.h"
42#include "ecm_state.h"
43#include "ecm_tracker.h"
44#include "ecm_classifier.h"
45#include "ecm_front_end_types.h"
46#include "ecm_classifier_default.h"
47#include "ecm_db.h"
48
49/*
50 * Magic numbers
51 */
52#define ECM_STATE_FILE_INSTANCE_MAGIC 0xB3FE
53
54/*
55 * Debugfs dentry object.
56 */
57static struct dentry *ecm_state_dentry;
58
59/*
60 * Locking of the state - concurrency control
61 */
62static DEFINE_SPINLOCK(ecm_state_lock);					/* Protect the table from SMP access. */
63
64/*
65 * Character device stuff - used to communicate status back to user space
66 */
67static int ecm_state_dev_major_id = 0;			/* Major ID of registered char dev from which we can dump out state to userspace */
68
69/*
70 * Buffer sizes
71 */
72#define ECM_STATE_FILE_PREFIX_SIZE 128
73#define ECM_STATE_FILE_PREFIX_LEVELS_MAX 10
74#define ECM_STATE_FILE_BUFFER_SIZE 32768
75
76/*
77 * Output selection flags
78 */
79#define ECM_STATE_FILE_OUTPUT_CONNECTIONS 1
80#define ECM_STATE_FILE_OUTPUT_MAPPINGS 2
81#define ECM_STATE_FILE_OUTPUT_HOSTS 4
82#define ECM_STATE_FILE_OUTPUT_NODES 8
83#define ECM_STATE_FILE_OUTPUT_INTERFACES 16
84#define ECM_STATE_FILE_OUTPUT_CONNECTIONS_CHAIN 32
85#define ECM_STATE_FILE_OUTPUT_MAPPINGS_CHAIN 64
86#define ECM_STATE_FILE_OUTPUT_HOSTS_CHAIN 128
87#define ECM_STATE_FILE_OUTPUT_NODES_CHAIN 256
88#define ECM_STATE_FILE_OUTPUT_INTERFACES_CHAIN 512
89#define ECM_STATE_FILE_OUTPUT_PROTOCOL_COUNTS 1024
90#ifdef ECM_DB_CTA_TRACK_ENABLE
91#define ECM_STATE_FILE_OUTPUT_CLASSIFIER_TYPE_ASSIGNMENTS 2048
92#endif
93
94/*
95 * struct ecm_state_file_instance
96 *	Structure used as state per open instance of our db state file
97 */
98struct ecm_state_file_instance {
99	int output_mask;				/* The content types wanted by the user */
100	struct ecm_db_connection_instance *ci;		/* All connections list iterator */
101	struct ecm_db_mapping_instance *mi;		/* All mappings list iterator */
102	struct ecm_db_host_instance *hi;		/* All hosts list iterator */
103	struct ecm_db_node_instance *ni;		/* All nodes list iterator */
104	struct ecm_db_iface_instance *ii;		/* All interfaces list iterator */
105#ifdef ECM_DB_CTA_TRACK_ENABLE
106	struct ecm_db_connection_instance *classifier_type_assignments[ECM_CLASSIFIER_TYPES];
107							/* Classifier type connection assignments iterator, one for each classifier type */
108#endif
109	int connection_hash_index;			/* Connection hash table lengths iterator */
110	int mapping_hash_index;				/* Mapping hash table lengths iterator */
111	int host_hash_index;				/* Host hash table lengths iterator */
112	int node_hash_index;				/* Node hash table lengths iterator */
113	int iface_hash_index;				/* Interface hash table lengths iterator */
114	int protocol;					/* Protocol connection count iterator */
115
116	char prefix[ECM_STATE_FILE_PREFIX_SIZE];	/* This is the prefix added to every message written */
117	int prefix_levels[ECM_STATE_FILE_PREFIX_LEVELS_MAX];
118							/* How many nested prefixes supported */
119	int prefix_level;				/* Prefix nest level */
120
121	char msg[ECM_STATE_FILE_BUFFER_SIZE];		/* The message written / being returned to the reader */
122	char *msgp;					/* Points into the msg buffer as we output it to the reader piece by piece */
123	int msg_len;					/* Length of the msg buffer still to be written out */
124#if (DEBUG_LEVEL > 0)
125	uint16_t magic;
126#endif
127};
128static int ecm_state_file_output_mask = ECM_STATE_FILE_OUTPUT_CONNECTIONS;
129							/* Bit mask specifies which data to output in the state file */
130
131/*
132 * ecm_state_write_reset()
133 *	Reset the msg buffer, specifying a new initial prefix
134 *
135 * Returns 0 on success
136 */
137int ecm_state_write_reset(struct ecm_state_file_instance *sfi, char *prefix)
138{
139	int result;
140
141	DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi);
142	sfi->msgp = sfi->msg;
143	sfi->msg_len = 0;
144
145	result = snprintf(sfi->prefix, ECM_STATE_FILE_PREFIX_SIZE, "%s", prefix);
146	if ((result < 0) || (result >= ECM_STATE_FILE_PREFIX_SIZE)) {
147		return -1;
148	}
149	sfi->prefix_level = 0;
150	sfi->prefix_levels[sfi->prefix_level] = result;
151	return 0;
152}
153EXPORT_SYMBOL(ecm_state_write_reset);
154
155/*
156 * ecm_state_prefix_add()
157 *	Add another level to the prefix
158 *
159 * Returns 0 on success
160 */
161int ecm_state_prefix_add(struct ecm_state_file_instance *sfi, char *prefix)
162{
163	int pxsz;
164	int pxremain;
165	int result;
166
167	DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi);
168
169	pxsz = sfi->prefix_levels[sfi->prefix_level];
170	pxremain = ECM_STATE_FILE_PREFIX_SIZE - pxsz;
171	result = snprintf(sfi->prefix + pxsz, pxremain, ".%s", prefix);
172	if ((result < 0) || (result >= pxremain)) {
173		return -1;
174	}
175
176	sfi->prefix_level++;
177	DEBUG_ASSERT(sfi->prefix_level < ECM_STATE_FILE_PREFIX_LEVELS_MAX, "Bad prefix handling\n");
178	sfi->prefix_levels[sfi->prefix_level] = pxsz + result;
179	return 0;
180}
181EXPORT_SYMBOL(ecm_state_prefix_add);
182
183/*
184 * ecm_state_prefix_index_add()
185 *	Add another level (numeric) to the prefix
186 *
187 * Returns 0 on success
188 */
189int ecm_state_prefix_index_add(struct ecm_state_file_instance *sfi, int index)
190{
191	int pxsz;
192	int pxremain;
193	int result;
194
195	DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi);
196
197	pxsz = sfi->prefix_levels[sfi->prefix_level];
198	pxremain = ECM_STATE_FILE_PREFIX_SIZE - pxsz;
199	result = snprintf(sfi->prefix + pxsz, pxremain, ".%d", index);
200	if ((result < 0) || (result >= pxremain)) {
201		return -1;
202	}
203
204	sfi->prefix_level++;
205	DEBUG_ASSERT(sfi->prefix_level < ECM_STATE_FILE_PREFIX_LEVELS_MAX, "Bad prefix handling\n");
206	sfi->prefix_levels[sfi->prefix_level] = pxsz + result;
207	return 0;
208}
209EXPORT_SYMBOL(ecm_state_prefix_index_add);
210
211/*
212 * ecm_state_prefix_remove()
213 *	Remove level from the prefix
214 *
215 * Returns 0 on success
216 */
217int ecm_state_prefix_remove(struct ecm_state_file_instance *sfi)
218{
219	int pxsz;
220
221	DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi);
222
223	sfi->prefix_level--;
224	DEBUG_ASSERT(sfi->prefix_level >= 0, "Bad prefix handling\n");
225	pxsz = sfi->prefix_levels[sfi->prefix_level];
226	sfi->prefix[pxsz] = 0;
227	return 0;
228}
229EXPORT_SYMBOL(ecm_state_prefix_remove);
230
231/*
232 * ecm_state_write()
233 *	Write out to the message buffer, prefix is added automatically.
234 *
235 * Returns 0 on success
236 */
237int ecm_state_write(struct ecm_state_file_instance *sfi, char *name, char *fmt, ...)
238{
239	int remain;
240	char *ptr;
241	int result;
242	va_list args;
243
244	DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi);
245
246	remain = ECM_STATE_FILE_BUFFER_SIZE - sfi->msg_len;
247	ptr = sfi->msg + sfi->msg_len;
248	result = snprintf(ptr, remain, "%s.%s=", sfi->prefix, name);
249	if ((result < 0) || (result >= remain)) {
250		return -1;
251	}
252
253	sfi->msg_len += result;
254	remain -= result;
255	ptr += result;
256
257	va_start(args, fmt);
258	result = vsnprintf(ptr, remain, fmt, args);
259	va_end(args);
260	if ((result < 0) || (result >= remain)) {
261		return -2;
262	}
263
264	sfi->msg_len += result;
265	remain -= result;
266	ptr += result;
267
268	result = snprintf(ptr, remain, "\n");
269	if ((result < 0) || (result >= remain)) {
270		return -3;
271	}
272
273	sfi->msg_len += result;
274	return 0;
275}
276EXPORT_SYMBOL(ecm_state_write);
277
278/*
279 * ecm_state_char_dev_conn_msg_prep()
280 *	Prepare a connection message
281 */
282static bool ecm_state_char_dev_conn_msg_prep(struct ecm_state_file_instance *sfi)
283{
284	int result;
285
286	DEBUG_TRACE("%p: Prep conn msg for %p\n", sfi, sfi->ci);
287
288	if ((result = ecm_state_write_reset(sfi, "conns"))) {
289		return result;
290	}
291	return ecm_db_connection_state_get(sfi, sfi->ci);
292}
293
294/*
295 * ecm_state_char_dev_mapping_msg_prep()
296 *	Prepare a mapping message
297 */
298static bool ecm_state_char_dev_mapping_msg_prep(struct ecm_state_file_instance *sfi)
299{
300	int result;
301
302	DEBUG_TRACE("%p: Prep mapping msg for %p\n", sfi, sfi->mi);
303
304	if ((result = ecm_state_write_reset(sfi, "mappings"))) {
305		return result;
306	}
307	return ecm_db_mapping_state_get(sfi, sfi->mi);
308}
309
310/*
311 * ecm_state_char_dev_host_msg_prep()
312 *	Prepare a host message
313 */
314static bool ecm_state_char_dev_host_msg_prep(struct ecm_state_file_instance *sfi)
315{
316	int result;
317
318	DEBUG_TRACE("%p: Prep host msg for %p\n", sfi, sfi->hi);
319
320	if ((result = ecm_state_write_reset(sfi, "hosts"))) {
321		return result;
322	}
323
324	return ecm_db_host_state_get(sfi, sfi->hi);
325}
326
327/*
328 * ecm_state_char_dev_node_msg_prep()
329 *	Prepare a node message
330 */
331static bool ecm_state_char_dev_node_msg_prep(struct ecm_state_file_instance *sfi)
332{
333	int result;
334
335	DEBUG_TRACE("%p: Prep node msg for %p\n", sfi, sfi->ni);
336
337	if ((result = ecm_state_write_reset(sfi, "nodes"))) {
338		return result;
339	}
340
341	return ecm_db_node_state_get(sfi, sfi->ni);
342}
343
344/*
345 * ecm_state_char_dev_iface_msg_prep()
346 *	Prepare an interface message
347 */
348static int ecm_state_char_dev_iface_msg_prep(struct ecm_state_file_instance *sfi)
349{
350	int result;
351
352	DEBUG_TRACE("%p: Prep iface msg for %p\n", sfi, sfi->ii);
353
354	if ((result = ecm_state_write_reset(sfi, "ifaces"))) {
355		return result;
356	}
357	return ecm_db_iface_state_get(sfi, sfi->ii);
358}
359
360/*
361 * ecm_state_char_dev_conn_chain_msg_prep()
362 *	Generate an conn hash table chain message
363 */
364static bool ecm_state_char_dev_conn_chain_msg_prep(struct ecm_state_file_instance *sfi)
365{
366	int result;
367	int chain_len;
368	DEBUG_TRACE("%p: Prep conn chain msg\n", sfi);
369
370	/*
371	 * Get hash table chain length
372	 */
373	chain_len = ecm_db_connection_hash_table_lengths_get(sfi->connection_hash_index);
374
375	if ((result = ecm_state_write_reset(sfi, "conn_chain"))) {
376		return result;
377	}
378	if ((result = ecm_state_prefix_index_add(sfi, sfi->connection_hash_index))) {
379		return result;
380	}
381	return ecm_state_write(sfi, "length", "%d", chain_len);
382}
383
384/*
385 * ecm_state_char_dev_mapping_chain_msg_prep()
386 *	Generate an mapping hash table chain message
387 */
388static bool ecm_state_char_dev_mapping_chain_msg_prep(struct ecm_state_file_instance *sfi)
389{
390	int result;
391	int chain_len;
392	DEBUG_TRACE("%p: Prep mapping chain msg\n", sfi);
393
394	/*
395	 * Get hash table chain length
396	 */
397	chain_len = ecm_db_mapping_hash_table_lengths_get(sfi->mapping_hash_index);
398
399	if ((result = ecm_state_write_reset(sfi, "mapping_chain"))) {
400		return result;
401	}
402	if ((result = ecm_state_prefix_index_add(sfi, sfi->mapping_hash_index))) {
403		return result;
404	}
405	return ecm_state_write(sfi, "length", "%d", chain_len);
406}
407
408/*
409 * ecm_state_char_dev_host_chain_msg_prep()
410 *	Generate an host hash table chain message
411 */
412static bool ecm_state_char_dev_host_chain_msg_prep(struct ecm_state_file_instance *sfi)
413{
414	int result;
415	int chain_len;
416	DEBUG_TRACE("%p: Prep host chain msg\n", sfi);
417
418	/*
419	 * Get hash table chain length
420	 */
421	chain_len = ecm_db_host_hash_table_lengths_get(sfi->host_hash_index);
422
423	if ((result = ecm_state_write_reset(sfi, "host_chain"))) {
424		return result;
425	}
426	if ((result = ecm_state_prefix_index_add(sfi, sfi->host_hash_index))) {
427		return result;
428	}
429	return ecm_state_write(sfi, "length", "%d", chain_len);
430}
431
432/*
433 * ecm_state_char_dev_node_chain_msg_prep()
434 *	Generate an node hash table chain message
435 */
436static bool ecm_state_char_dev_node_chain_msg_prep(struct ecm_state_file_instance *sfi)
437{
438	int result;
439	int chain_len;
440	DEBUG_TRACE("%p: Prep node chain msg\n", sfi);
441
442	/*
443	 * Get hash table chain length
444	 */
445	chain_len = ecm_db_node_hash_table_lengths_get(sfi->node_hash_index);
446
447	if ((result = ecm_state_write_reset(sfi, "node_chain"))) {
448		return result;
449	}
450	if ((result = ecm_state_prefix_index_add(sfi, sfi->node_hash_index))) {
451		return result;
452	}
453	return ecm_state_write(sfi, "length", "%d", chain_len);
454}
455
456/*
457 * ecm_state_char_dev_iface_chain_msg_prep()
458 *	Generate an interface hash table chain message
459 */
460static bool ecm_state_char_dev_iface_chain_msg_prep(struct ecm_state_file_instance *sfi)
461{
462	int result;
463	int chain_len;
464	DEBUG_TRACE("%p: Prep iface chain msg\n", sfi);
465
466	/*
467	 * Get hash table chain length
468	 */
469	chain_len = ecm_db_iface_hash_table_lengths_get(sfi->iface_hash_index);
470
471	if ((result = ecm_state_write_reset(sfi, "iface_chain"))) {
472		return result;
473	}
474	if ((result = ecm_state_prefix_index_add(sfi, sfi->iface_hash_index))) {
475		return result;
476	}
477	return ecm_state_write(sfi, "length", "%d", chain_len);
478}
479
480/*
481 * ecm_state_char_dev_protocol_count_msg_prep()
482 *	Generate a protocol usage message
483 */
484static bool ecm_state_char_dev_protocol_count_msg_prep(struct ecm_state_file_instance *sfi)
485{
486	int result;
487	int count;
488	DEBUG_TRACE("%p: Prep protocol msg\n", sfi);
489
490	/*
491	 * Get protocol connection total count
492	 */
493	count = ecm_db_connection_count_by_protocol_get(sfi->protocol);
494
495	if ((result = ecm_state_write_reset(sfi, "protocol"))) {
496		return result;
497	}
498	if ((result = ecm_state_prefix_index_add(sfi, sfi->protocol))) {
499		return result;
500	}
501	return ecm_state_write(sfi, "connections", "%d", count);
502}
503
504#ifdef ECM_DB_CTA_TRACK_ENABLE
505/*
506 * ecm_state_char_dev_cta_msg_prep()
507 *	Generate a classifier type assignment message
508 */
509static int ecm_state_char_dev_cta_msg_prep(struct ecm_state_file_instance *sfi, ecm_classifier_type_t ca_type)
510{
511	struct ecm_db_connection_instance *ci;
512	int result;
513
514	DEBUG_TRACE("%p: Prep classifier type assignment msg: %d\n", sfi, ca_type);
515
516	ci = sfi->classifier_type_assignments[ca_type];
517	if (!ci) {
518		return 0;
519	}
520
521	if ((result = ecm_state_write_reset(sfi, "cta"))) {
522		return result;
523	}
524	if ((result = ecm_state_prefix_index_add(sfi, ca_type))) {
525		return result;
526	}
527	if ((result = ecm_state_write(sfi, "conn.serial", "%u", ecm_db_connection_serial_get(ci)))) {
528		return result;
529	}
530
531	/*
532	 * Prep next connection for when we are called again, releasing this one.
533	 */
534	sfi->classifier_type_assignments[ca_type] = ecm_db_connection_by_classifier_type_assignment_get_and_ref_next(ci, ca_type);
535	ecm_db_connection_by_classifier_type_assignment_deref(ci, ca_type);
536	return 0;
537}
538
539/*
540 * ecm_state_file_classifier_type_assignments_release()
541 *	Releases any uniterated classifier assignments
542 */
543static void ecm_state_file_classifier_type_assignments_release(struct ecm_state_file_instance *sfi)
544{
545	ecm_classifier_type_t ca_type;
546
547	for (ca_type = 0; ca_type < ECM_CLASSIFIER_TYPES; ++ca_type) {
548		struct ecm_db_connection_instance *ci;
549
550		ci = sfi->classifier_type_assignments[ca_type];
551		if (!ci) {
552			continue;
553		}
554
555		ecm_db_connection_by_classifier_type_assignment_deref(ci, ca_type);
556	}
557}
558#endif
559
560/*
561 * ecm_state_char_device_open()
562 *	Opens the special char device file which we use to dump our state.
563 */
564static int ecm_state_char_device_open(struct inode *inode, struct file *file)
565{
566	struct ecm_state_file_instance *sfi;
567
568	DEBUG_INFO("State open\n");
569
570	/*
571	 * Allocate state information for the reading
572	 */
573	DEBUG_ASSERT(file->private_data == NULL, "unexpected double open: %p?\n", file->private_data);
574
575	sfi = (struct ecm_state_file_instance *)kzalloc(sizeof(struct ecm_state_file_instance), GFP_ATOMIC | __GFP_NOWARN);
576	if (!sfi) {
577		return -ENOMEM;
578	}
579	DEBUG_SET_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC);
580	file->private_data = sfi;
581
582	/*
583	 * Snapshot output mask for this file
584	 */
585	spin_lock_bh(&ecm_state_lock);
586	sfi->output_mask = ecm_state_file_output_mask;
587	spin_unlock_bh(&ecm_state_lock);
588
589	/*
590	 * Get the first indicies for hash and protocol stats should they be needed.
591	 * NOTE: There are no references held here so it does not matter to get them all even if they are not wanted.
592	 */
593	sfi->connection_hash_index = ecm_db_connection_hash_index_get_first();
594	sfi->mapping_hash_index = ecm_db_mapping_hash_index_get_first();
595	sfi->host_hash_index = ecm_db_host_hash_index_get_first();
596	sfi->node_hash_index = ecm_db_node_hash_index_get_first();
597	sfi->iface_hash_index = ecm_db_iface_hash_index_get_first();
598	sfi->protocol = ecm_db_protocol_get_first();
599
600	/*
601	 * Take references to each object list that we are going to generate state for.
602	 */
603	if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_CONNECTIONS) {
604		sfi->ci = ecm_db_connections_get_and_ref_first();
605	}
606	if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_MAPPINGS) {
607		sfi->mi = ecm_db_mappings_get_and_ref_first();
608	}
609	if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_HOSTS) {
610		sfi->hi = ecm_db_hosts_get_and_ref_first();
611	}
612	if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_NODES) {
613		sfi->ni = ecm_db_nodes_get_and_ref_first();
614	}
615	if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_INTERFACES) {
616		sfi->ii = ecm_db_interfaces_get_and_ref_first();
617	}
618#ifdef ECM_DB_CTA_TRACK_ENABLE
619	if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_CLASSIFIER_TYPE_ASSIGNMENTS) {
620		ecm_classifier_type_t ca_type;
621
622		/*
623		 * Iterate all classifier type assignments.
624		 * Hold the head of each list to start us off on our iterating process.
625		 */
626		for (ca_type = 0; ca_type < ECM_CLASSIFIER_TYPES; ++ca_type) {
627			sfi->classifier_type_assignments[ca_type] = ecm_db_connection_by_classifier_type_assignment_get_and_ref_first(ca_type);
628		}
629	}
630#endif
631
632	DEBUG_INFO("State opened %p\n", sfi);
633
634	return 0;
635}
636
637/*
638 * ecm_state_char_device_release()
639 *	Called when a process closes the device file.
640 */
641static int ecm_state_char_device_release(struct inode *inode, struct file *file)
642{
643	struct ecm_state_file_instance *sfi;
644
645	sfi = (struct ecm_state_file_instance *)file->private_data;
646	DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi);
647	DEBUG_INFO("%p: State close\n", sfi);
648
649	/*
650	 * Release any references held
651	 */
652	if (sfi->ci) {
653		ecm_db_connection_deref(sfi->ci);
654	}
655	if (sfi->mi) {
656		ecm_db_mapping_deref(sfi->mi);
657	}
658	if (sfi->hi) {
659		ecm_db_host_deref(sfi->hi);
660	}
661	if (sfi->ni) {
662		ecm_db_node_deref(sfi->ni);
663	}
664	if (sfi->ii) {
665		ecm_db_iface_deref(sfi->ii);
666	}
667#ifdef ECM_DB_CTA_TRACK_ENABLE
668	ecm_state_file_classifier_type_assignments_release(sfi);
669#endif
670
671	DEBUG_CLEAR_MAGIC(sfi);
672	kfree(sfi);
673
674	return 0;
675}
676
677/*
678 * ecm_state_char_device_read()
679 *	Called to read the state
680 */
681static ssize_t ecm_state_char_device_read(struct file *file,	/* see include/linux/fs.h   */
682			   char *buffer,				/* buffer to fill with data */
683			   size_t length,				/* length of the buffer     */
684			   loff_t *offset)				/* Doesn't apply - this is a char file */
685{
686	struct ecm_state_file_instance *sfi;
687	int bytes_read = 0;						/* Number of bytes actually written to the buffer */
688#ifdef ECM_DB_CTA_TRACK_ENABLE
689	ecm_classifier_type_t ca_type;
690#endif
691
692	sfi = (struct ecm_state_file_instance *)file->private_data;
693	DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi);
694	DEBUG_TRACE("%p: State read up to length %d bytes\n", sfi, length);
695
696	/*
697	 * If there is still some message remaining to be output then complete that first
698	 */
699	if (sfi->msg_len) {
700		goto char_device_read_output;
701	}
702
703	if (sfi->ci) {
704		struct ecm_db_connection_instance *cin;
705		if (ecm_state_char_dev_conn_msg_prep(sfi)) {
706			return -EIO;
707		}
708
709		/*
710		 * Next connection for when we return
711		 */
712		cin = ecm_db_connection_get_and_ref_next(sfi->ci);
713		ecm_db_connection_deref(sfi->ci);
714		sfi->ci = cin;
715
716		goto char_device_read_output;
717	}
718
719	if (sfi->mi) {
720		struct ecm_db_mapping_instance *min;
721		if (ecm_state_char_dev_mapping_msg_prep(sfi)) {
722			return -EIO;
723		}
724
725		/*
726		 * Next mapping for when we return
727		 */
728		min = ecm_db_mapping_get_and_ref_next(sfi->mi);
729		ecm_db_mapping_deref(sfi->mi);
730		sfi->mi = min;
731
732		goto char_device_read_output;
733	}
734
735	if (sfi->hi) {
736		struct ecm_db_host_instance *hin;
737		if (ecm_state_char_dev_host_msg_prep(sfi)) {
738			return -EIO;
739		}
740
741		/*
742		 * Next host for when we return
743		 */
744		hin = ecm_db_host_get_and_ref_next(sfi->hi);
745		ecm_db_host_deref(sfi->hi);
746		sfi->hi = hin;
747
748		goto char_device_read_output;
749	}
750
751	if (sfi->ni) {
752		struct ecm_db_node_instance *nin;
753		if (ecm_state_char_dev_node_msg_prep(sfi)) {
754			return -EIO;
755		}
756
757		/*
758		 * Next node for when we return
759		 */
760		nin = ecm_db_node_get_and_ref_next(sfi->ni);
761		ecm_db_node_deref(sfi->ni);
762		sfi->ni = nin;
763
764		goto char_device_read_output;
765	}
766
767	if (sfi->ii) {
768		struct ecm_db_iface_instance *iin;
769		if (ecm_state_char_dev_iface_msg_prep(sfi)) {
770			return -EIO;
771		}
772
773		/*
774		 * Next iface for when we return
775		 */
776		iin = ecm_db_interface_get_and_ref_next(sfi->ii);
777		ecm_db_iface_deref(sfi->ii);
778		sfi->ii = iin;
779
780		goto char_device_read_output;
781	}
782
783	if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_CONNECTIONS_CHAIN) && (sfi->connection_hash_index >= 0)) {
784		if (ecm_state_char_dev_conn_chain_msg_prep(sfi)) {
785			return -EIO;
786		}
787		sfi->connection_hash_index = ecm_db_connection_hash_index_get_next(sfi->connection_hash_index);
788		goto char_device_read_output;
789	}
790
791	if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_MAPPINGS_CHAIN) && (sfi->mapping_hash_index >= 0)) {
792		if (ecm_state_char_dev_mapping_chain_msg_prep(sfi)) {
793			return -EIO;
794		}
795		sfi->mapping_hash_index = ecm_db_mapping_hash_index_get_next(sfi->mapping_hash_index);
796		goto char_device_read_output;
797	}
798
799	if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_HOSTS_CHAIN) && (sfi->host_hash_index >= 0)) {
800		if (ecm_state_char_dev_host_chain_msg_prep(sfi)) {
801			return -EIO;
802		}
803		sfi->host_hash_index = ecm_db_host_hash_index_get_next(sfi->host_hash_index);
804		goto char_device_read_output;
805	}
806
807	if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_NODES_CHAIN) && (sfi->node_hash_index >= 0)) {
808		if (ecm_state_char_dev_node_chain_msg_prep(sfi)) {
809			return -EIO;
810		}
811		sfi->node_hash_index = ecm_db_node_hash_index_get_next(sfi->node_hash_index);
812		goto char_device_read_output;
813	}
814
815	if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_INTERFACES_CHAIN) && (sfi->iface_hash_index >= 0)) {
816		if (ecm_state_char_dev_iface_chain_msg_prep(sfi)) {
817			return -EIO;
818		}
819		sfi->iface_hash_index = ecm_db_iface_hash_index_get_next(sfi->iface_hash_index);
820		goto char_device_read_output;
821	}
822
823	if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_PROTOCOL_COUNTS) && (sfi->protocol >= 0)) {
824		if (ecm_state_char_dev_protocol_count_msg_prep(sfi)) {
825			return -EIO;
826		}
827		sfi->protocol = ecm_db_protocol_get_next(sfi->protocol);
828		goto char_device_read_output;
829	}
830
831#ifdef ECM_DB_CTA_TRACK_ENABLE
832	for (ca_type = 0; ca_type < ECM_CLASSIFIER_TYPES; ++ca_type) {
833		if (!sfi->classifier_type_assignments[ca_type]) continue;
834		if (ecm_state_char_dev_cta_msg_prep(sfi, ca_type)) {
835			return -EIO;
836		}
837		goto char_device_read_output;
838	}
839#endif
840
841	/*
842	 * EOF
843	 */
844	return 0;
845
846char_device_read_output:
847
848	/*
849	 * If supplied buffer is small we limit what we output
850	 */
851	bytes_read = sfi->msg_len;
852	if (bytes_read > length) {
853		bytes_read = length;
854	}
855	if (copy_to_user(buffer, sfi->msgp, bytes_read)) {
856		return -EIO;
857	}
858	sfi->msg_len -= bytes_read;
859	sfi->msgp += bytes_read;
860
861	DEBUG_TRACE("State read done, bytes_read %d bytes\n", bytes_read);
862
863	/*
864	 * Most read functions return the number of bytes put into the buffer
865	 */
866	return bytes_read;
867}
868
869/*
870 * ecm_state_char_device_write()
871 */
872static ssize_t ecm_state_char_device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
873{
874	return -EINVAL;
875}
876
877/*
878 * File operations used in the char device
879 *	NOTE: The char device is a simple file that allows us to dump our connection tracking state
880 */
881static struct file_operations ecm_state_fops = {
882	.read = ecm_state_char_device_read,
883	.write = ecm_state_char_device_write,
884	.open = ecm_state_char_device_open,
885	.release = ecm_state_char_device_release
886};
887
888/*
889 * ecm_state_init()
890 */
891int ecm_state_init(struct dentry *dentry)
892{
893	int result = -1;
894	DEBUG_INFO("ECM State init\n");
895
896	ecm_state_dentry = debugfs_create_dir("ecm_state", dentry);
897	if (!ecm_state_dentry) {
898		DEBUG_ERROR("Failed to create ecm state directory in debugfs\n");
899		return -1;
900	}
901
902	if (!debugfs_create_u32("state_dev_major", S_IRUGO, ecm_state_dentry,
903					(u32 *)&ecm_state_dev_major_id)) {
904		DEBUG_ERROR("Failed to create ecm state dev major file in debugfs\n");
905		goto init_cleanup;
906	}
907
908	if (!debugfs_create_u32("state_file_output_mask", S_IRUGO | S_IWUSR, ecm_state_dentry,
909					(u32 *)&ecm_state_file_output_mask)) {
910		DEBUG_ERROR("Failed to create ecm state output mask file in debugfs\n");
911		goto init_cleanup;
912	}
913
914	/*
915	 * Register a char device that we will use to provide a dump of our state
916	 */
917	result = register_chrdev(0, "ecm_state", &ecm_state_fops);
918	if (result < 0) {
919                DEBUG_ERROR("Failed to register chrdev %d\n", result);
920		goto init_cleanup;
921	}
922	ecm_state_dev_major_id = result;
923	DEBUG_TRACE("registered chr dev major id assigned %d\n", ecm_state_dev_major_id);
924
925	return 0;
926
927init_cleanup:
928
929	debugfs_remove_recursive(ecm_state_dentry);
930	return result;
931}
932EXPORT_SYMBOL(ecm_state_init);
933
934/*
935 * ecm_state_exit()
936 */
937void ecm_state_exit(void)
938{
939	DEBUG_INFO("ECM State exit\n");
940
941	unregister_chrdev(ecm_state_dev_major_id, "ecm_state");
942
943	/*
944	 * Remove the debugfs files recursively.
945	 */
946	if (ecm_state_dentry) {
947		debugfs_remove_recursive(ecm_state_dentry);
948	}
949}
950EXPORT_SYMBOL(ecm_state_exit);
951
952