add support for multiple conntrack hooks
Change-Id: Ia21a3c7be9f42c5e06affb0a163274a01754fd92
Signed-off-by: Matthew McClintock <mmcclint@codeaurora.org>
diff --git a/nss_connmgr_ipv4.c b/nss_connmgr_ipv4.c
index 6e2127f..7723e2c 100755
--- a/nss_connmgr_ipv4.c
+++ b/nss_connmgr_ipv4.c
@@ -39,6 +39,7 @@
#include <linux/string.h>
#include <linux/debugfs.h>
#include <linux/netdevice.h>
+#include <linux/notifier.h>
#include <net/route.h>
#include <net/ip.h>
@@ -291,10 +292,16 @@
struct task_struct *thread;
/* Control thread */
void *nss_context; /* Registration context used to identify the manager in calls to the NSS driver */
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ struct notifier_block conntrack_notifier;
+#else
struct nf_ct_event_notifier conntrack_notifier;
+#endif
/* NF conntrack event system to monitor connection tracking changes */
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
int (*conntrack_event_cb) (struct nf_conn *ct);
/* conntrack event callback to propagate events to other clients (ipv6) */
+#endif
struct notifier_block netdev_notifier;
struct nss_connmgr_ipv4_connection connection[NSS_CONNMGR_IPV4_CONN_MAX];
/* Connection Table */
@@ -328,7 +335,12 @@
static ssize_t nss_connmgr_ipv4_clear_stats(struct file *fp, const char __user *ubuf, size_t count, loff_t *ppos);
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+static int nss_connmgr_ipv4_conntrack_event(struct notifier_block *this,
+ unsigned long events, void *ptr);
+#else
static int nss_connmgr_ipv4_conntrack_event(unsigned int events, struct nf_ct_event *item);
+#endif
static struct nss_connmgr_ipv4_instance nss_connmgr_ipv4 = {
@@ -337,7 +349,11 @@
.thread = NULL,
.nss_context = NULL,
.conntrack_notifier = {
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ .notifier_call = nss_connmgr_ipv4_conntrack_event,
+#else
.fcn = nss_connmgr_ipv4_conntrack_event,
+#endif
},
.need_mark = 0,
};
@@ -2718,15 +2734,24 @@
* nss_connmgr_ipv4_conntrack_event()
* Callback event invoked when conntrack connection state changes, currently we handle destroy events to quickly release state
*/
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+static int nss_connmgr_ipv4_conntrack_event(struct notifier_block *this,
+ unsigned long events, void *ptr)
+#else
static int nss_connmgr_ipv4_conntrack_event(unsigned int events, struct nf_ct_event *item)
+#endif
{
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ struct nf_ct_event *item = ptr;
+#endif
struct nss_ipv4_destroy unid;
struct nf_conn *ct = item->ct;
struct nf_conntrack_tuple orig_tuple;
struct nf_conntrack_tuple reply_tuple;
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
int (*event_cb) (struct nf_conn *ct);
+#endif
- int ret = 0;
nss_tx_status_t nss_tx_status;
@@ -2752,14 +2777,16 @@
/*
* Invoke ipv6 callback, if registered
*/
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
event_cb = nss_connmgr_ipv4.conntrack_event_cb;
if ((nf_ct_l3num(ct) == AF_INET6) && event_cb) {
- ret = event_cb(ct);
+ int ret = event_cb(ct);
if (ret) {
NSS_CONNMGR_DEBUG_WARN("conntrack_event_cb failed %d \n", ret);
}
return NOTIFY_DONE;
}
+#endif
/*
* Only interested if this is IPv4
@@ -2864,6 +2891,7 @@
return NOTIFY_DONE;
}
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
/*
* nss_connmgr_ipv4_register_conntrack_event_cb
* Registers a callback for NF conntrack destoy event
@@ -2891,6 +2919,7 @@
}
EXPORT_SYMBOL(nss_connmgr_ipv4_unregister_conntrack_event_cb);
#endif
+#endif
/*
* nss_connmgr_ipv4_register_bond_slave_linkup_cb
@@ -3288,11 +3317,13 @@
goto task_cleanup_7;
}
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
/*
* Initialize the conntrack event callback function to NULL.
* This will remain NULL unless other clients (ipv6 conn mgr) register a CB
*/
nss_connmgr_ipv4.conntrack_event_cb = NULL;
+#endif
/*
* Allow wakeup signals
diff --git a/nss_connmgr_ipv6.c b/nss_connmgr_ipv6.c
index 6ddd143..3669b28 100755
--- a/nss_connmgr_ipv6.c
+++ b/nss_connmgr_ipv6.c
@@ -309,6 +309,9 @@
/* Control thread */
void *nss_context;
/* Registration context used to identify the manager in calls to the NSS driver */
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ struct notifier_block conntrack_notifier;
+#endif
struct nss_connmgr_ipv6_connection connection[NSS_CONNMGR_IPV6_CONN_MAX];
/* Connection Table */
struct notifier_block netdev_notifier;
@@ -334,8 +337,11 @@
static ssize_t nss_connmgr_ipv6_read_debug_stats(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos);
static ssize_t nss_connmgr_ipv6_clear_stats(struct file *fp, const char __user *ubuf, size_t count, loff_t *ppos);
-#ifdef CONFIG_NF_CONNTRACK_EVENTS
+#if defined(CONFIG_NF_CONNTRACK_EVENTS) && !defined(CONFIG_NF_CONNTRACK_CHAIN_EVENTS)
static int nss_connmgr_ipv6_conntrack_event(struct nf_conn *ct);
+#elif defined(CONFIG_NF_CONNTRACK_EVENTS)
+static int nss_connmgr_ipv6_conntrack_event(struct notifier_block *this,
+ unsigned long events, void *ptr);
#endif
static struct nss_connmgr_ipv6_instance nss_connmgr_ipv6 = {
@@ -343,6 +349,11 @@
.terminate = 0,
.thread = NULL,
.nss_context = NULL,
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ .conntrack_notifier = {
+ .notifier_call = nss_connmgr_ipv6_conntrack_event,
+ },
+#endif
};
extern struct net_device *bond_get_tx_dev(struct sk_buff *skb,
@@ -2624,8 +2635,16 @@
* nss_connmgr_ipv6_conntrack_event()
* Callback event invoked when conntrack connection state changes, currently we handle destroy events to quickly release state
*/
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+static int nss_connmgr_ipv6_conntrack_event(struct notifier_block *this,
+ unsigned long events, void *ptr)
+#else
static int nss_connmgr_ipv6_conntrack_event(struct nf_conn *ct)
+#endif
{
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ struct nf_conn *ct = ((struct nf_ct_event *)ptr)->ct;
+#endif
struct nss_ipv6_destroy unid;
struct nf_conntrack_tuple orig_tuple;
struct nf_conntrack_tuple reply_tuple;
@@ -2644,6 +2663,22 @@
return NOTIFY_DONE;
}
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ /*
+ * Only interested in destroy events
+ */
+ if (!(events & (1 << IPCT_DESTROY))) {
+ return NOTIFY_DONE;
+ }
+
+ /*
+ * Only interested if this is IPv4
+ */
+ if (nf_ct_l3num(ct) != AF_INET6) {
+ return NOTIFY_DONE;
+ }
+#endif
+
/*
* Now examine conntrack to identify the protocol, IP addresses and portal information involved
* IMPORTANT: The information here will be as the 'ORIGINAL' direction, i.e. who established the connection.
@@ -2981,25 +3016,31 @@
goto task_cleanup_4;
}
-#ifdef CONFIG_NF_CONNTRACK_EVENTS
/*
* We register a callback with ipv4 connection manager module
* to get NF conntrack notifications of expired connections
*/
+#if defined(CONFIG_NF_CONNTRACK_EVENTS) && !defined(CONFIG_NF_CONNTRACK_CHAIN_EVENTS)
nss_connmgr_ipv4_register_conntrack_event_cb(nss_connmgr_ipv6_conntrack_event);
+#elif defined(CONFIG_NF_CONNTRACK_CHAIN_EVENTS)
+ result = nf_conntrack_register_notifier(&init_net, &nss_connmgr_ipv6.conntrack_notifier);
+ if (result < 0) {
+ NSS_CONNMGR_DEBUG_ERROR("Can't register nf notifier hook %d\n", result);
+ goto task_cleanup_5;
+ }
#endif
nss_connmgr_ipv6.netdev_notifier.notifier_call = nss_connmgr_netdev_notifier_cb;
result = register_netdevice_notifier(&nss_connmgr_ipv6.netdev_notifier);
if (result != 0) {
NSS_CONNMGR_DEBUG_ERROR("Can't register ipv6 netdevice notifier %d\n", result);
- goto task_cleanup_5;
+ goto task_cleanup_6;
}
result = sysfs_create_file(nss_connmgr_ipv6.nom_v6, &nss_connmgr_ipv6_need_mark_attr.attr);
if (result) {
NSS_CONNMGR_DEBUG_ERROR("Failed to register need mark file %d\n", result);
- goto task_cleanup_6;
+ goto task_cleanup_7;
}
nss_connmgr_ipv4_register_bond_slave_linkup_cb(nss_connmgr_bond_link_up);
@@ -3025,11 +3066,14 @@
nss_connmgr_ipv4_unregister_bond_slave_linkup_cb();
sysfs_remove_file(nss_connmgr_ipv6.nom_v6, &nss_connmgr_ipv6_need_mark_attr.attr);
-task_cleanup_6:
+task_cleanup_7:
unregister_netdevice_notifier(&nss_connmgr_ipv6.netdev_notifier);
-task_cleanup_5:
-#ifdef CONFIG_NF_CONNTRACK_EVENTS
+task_cleanup_6:
+#if defined(CONFIG_NF_CONNTRACK_EVENTS) && !defined(CONFIG_NF_CONNTRACK_CHAIN_EVENTS)
nss_connmgr_ipv4_unregister_conntrack_event_cb();
+#elif defined(CONFIG_NF_CONNTRACK_CHAIN_EVENTS)
+ nf_conntrack_unregister_notifier(&init_net, &nss_connmgr_ipv6.conntrack_notifier);
+task_cleanup_5:
#endif
sysfs_remove_file(nss_connmgr_ipv6.nom_v6, &nss_connmgr_ipv6_stop_attr.attr);
task_cleanup_4: