Initial commit of PSE and CDU

Change-Id: Ibcd57f7dac5ea7be54f7b8b37634baeba161b233
diff --git a/client_data_usage/cdu_nf_events.c b/client_data_usage/cdu_nf_events.c
new file mode 100644
index 0000000..ef66472
--- /dev/null
+++ b/client_data_usage/cdu_nf_events.c
@@ -0,0 +1,96 @@
+/* cdu_nf_events.c
+ *
+ * This file handles client data usage netfilter conntrack events.
+ *
+ * Author: Cradlepoint Technology, Inc.  <source@cradlepoint.com>
+ *		Adrian Sitterle <asitterle@cradlepoint.com>
+ *
+ * Copyright (C) 2019 Cradlepoint Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+
+#include "cdu_db.h"
+#include "cdu_nf_events.h"
+#include "cdu_xt_target.h"
+#include "cdu_types.h"
+
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+#error Can not use this module without conntrack events
+#endif
+
+static u_int8_t nf_registered;
+
+static int cdu_nf_event(struct notifier_block *this, unsigned long events, void *ptr)
+{
+	struct nf_ct_event *item = (struct nf_ct_event *)ptr;
+	struct nf_conn *ct = item->ct;
+
+	if (!ct) {
+		CDU_DEBUG("No ct available\n");
+		return -EINVAL;
+	}
+
+	if (ct->orig_direction == CDU_DIR_NOT_SET) {
+		/* This ct does not have a direction information because it didn't
+		 * travel through the xt hook, which means that we don't care
+		 * about this traffic
+		 */
+		return NOTIFY_DONE;
+	}
+
+	/* Update data usage htable entry on end of flow trigger */
+	if (events & (1 << IPCT_DESTROY)) {
+		CDU_DEBUG("Caught %s NF event. mac=%pM, dir %s, ct %p\n",
+			events & (1 << IPCT_NEW)?"NEW":"DESTROY", ct->mac,
+			(ct->orig_direction == CDU_DIR_SRC)?"DIR_SRC":"DIR_DEST", ct);
+
+		cdu_db_update_entry(ct, CDU_DB_UPDATE_PERMA_SET, CDU_DB_CONNTR_NOCLEAR);
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block cdu_nf_notifier = {
+	.notifier_call	= cdu_nf_event,
+};
+
+int cdu_nf_events_register(void)
+{
+	int result;
+
+	if (!nf_registered) {
+		result = nf_conntrack_register_notifier(&init_net, &cdu_nf_notifier);
+		if (result < 0) {
+			CDU_INFO("Failed to register conntrack notifier %d\n", result);
+			return result;
+		}
+		nf_registered = 1;
+	}
+
+	CDU_DEBUG("initialized\n");
+	return 0;
+}
+
+void cdu_nf_events_unregister(void)
+{
+	if (nf_registered) {
+		nf_conntrack_unregister_notifier(&init_net, &cdu_nf_notifier);
+		CDU_DEBUG("uninitialized\n");
+	}
+}
+