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");
+ }
+}
+