[strongSwan-dev] [PATCH] fndp-netlink: Plugin to do proxy NDP and proxy ARP

Volker Rümelin vr_strongswan at t-online.de
Sun Nov 13 13:40:14 CET 2016


This plugin manages proxy host address entries in the
kernel neighbour table.
---
 conf/Makefile.am                                   |   1 +
 conf/plugins/fndp-netlink.opt                      |  10 +
 configure.ac                                       |   4 +
 src/libcharon/Makefile.am                          |   7 +
 src/libcharon/plugins/fndp_netlink/Makefile.am     |  27 +++
 .../plugins/fndp_netlink/fndp_netlink_interface.c  | 140 +++++++++++
 .../plugins/fndp_netlink/fndp_netlink_interface.h  |  71 ++++++
 .../plugins/fndp_netlink/fndp_netlink_listener.c   | 257 +++++++++++++++++++++
 .../plugins/fndp_netlink/fndp_netlink_listener.h   |  61 +++++
 .../plugins/fndp_netlink/fndp_netlink_plugin.c     | 119 ++++++++++
 .../plugins/fndp_netlink/fndp_netlink_plugin.h     |  50 ++++
 11 files changed, 747 insertions(+)
 create mode 100644 conf/plugins/fndp-netlink.opt
 create mode 100644 src/libcharon/plugins/fndp_netlink/Makefile.am
 create mode 100644 src/libcharon/plugins/fndp_netlink/fndp_netlink_interface.c
 create mode 100644 src/libcharon/plugins/fndp_netlink/fndp_netlink_interface.h
 create mode 100644 src/libcharon/plugins/fndp_netlink/fndp_netlink_listener.c
 create mode 100644 src/libcharon/plugins/fndp_netlink/fndp_netlink_listener.h
 create mode 100644 src/libcharon/plugins/fndp_netlink/fndp_netlink_plugin.c
 create mode 100644 src/libcharon/plugins/fndp_netlink/fndp_netlink_plugin.h

diff --git a/conf/Makefile.am b/conf/Makefile.am
index 4588b09..e0c55d1 100644
--- a/conf/Makefile.am
+++ b/conf/Makefile.am
@@ -50,6 +50,7 @@ plugins = \
 	plugins/eap-ttls.opt \
 	plugins/error-notify.opt \
 	plugins/ext-auth.opt \
+	plugins/fndp-netlink.opt \
 	plugins/forecast.opt \
 	plugins/gcrypt.opt \
 	plugins/ha.opt \
diff --git a/conf/plugins/fndp-netlink.opt b/conf/plugins/fndp-netlink.opt
new file mode 100644
index 0000000..ab83b14
--- /dev/null
+++ b/conf/plugins/fndp-netlink.opt
@@ -0,0 +1,10 @@
+charon.plugins.fndp-netlink.ipv6 = yes
+	Do proxy NDP for peers. To enable proxy NDP also set one or more
+	of the sysctl variables net.ipv6.conf.all.proxy_ndp or
+	net.ipv6.conf.$INTERFACE.proxy_ndp to 1.
+
+charon.plugins.fndp-netlink.ipv4 = no
+	Do proxy ARP for peers. The fndp-netlink plugin only installs host
+	addresses in the kernel neighbour table. For whole subnets use the
+	farp plugin. Don't forget to disable the farp plugin with
+	charon.plugins.farp.load = no if you set this option to yes.
diff --git a/configure.ac b/configure.ac
index 622c79a..e3cbaf2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -259,6 +259,7 @@ ARG_ENABL_SET([forecast],       [enable forecast plugin forwarding broadcast/mul
 ARG_ENABL_SET([duplicheck],     [advanced duplicate checking plugin using liveness checks.])
 ARG_ENABL_SET([error-notify],   [enable error notification plugin.])
 ARG_ENABL_SET([farp],           [enable ARP faking plugin that responds to ARP requests to peers virtual IP])
+ARG_ENABL_SET([fndp-netlink],   [enable NDP and ARP proxy.])
 ARG_ENABL_SET([ha],             [enable high availability cluster plugin.])
 ARG_ENABL_SET([led],            [enable plugin to control LEDs on IKEv2 activity using the Linux kernel LED subsystem.])
 ARG_ENABL_SET([load-tester],    [enable load testing plugin for IKEv2 daemon.])
@@ -1391,6 +1392,7 @@ ADD_PLUGIN([socket-win],           [c charon])
 ADD_PLUGIN([connmark],             [c charon])
 ADD_PLUGIN([forecast],             [c charon])
 ADD_PLUGIN([farp],                 [c charon])
+ADD_PLUGIN([fndp-netlink],         [c charon])
 ADD_PLUGIN([stroke],               [c charon])
 ADD_PLUGIN([vici],                 [c charon])
 ADD_PLUGIN([smp],                  [c charon])
@@ -1611,6 +1613,7 @@ AM_CONDITIONAL(USE_SOCKET_WIN, test x$socket_win = xtrue)
 AM_CONDITIONAL(USE_CONNMARK, test x$connmark = xtrue)
 AM_CONDITIONAL(USE_FORECAST, test x$forecast = xtrue)
 AM_CONDITIONAL(USE_FARP, test x$farp = xtrue)
+AM_CONDITIONAL(USE_FNDP_NETLINK, test x$fndp_netlink = xtrue)
 AM_CONDITIONAL(USE_ADDRBLOCK, test x$addrblock = xtrue)
 AM_CONDITIONAL(USE_UNITY, test x$unity = xtrue)
 AM_CONDITIONAL(USE_RESOLVE, test x$resolve = xtrue)
@@ -1858,6 +1861,7 @@ AC_CONFIG_FILES([
 	src/libcharon/plugins/connmark/Makefile
 	src/libcharon/plugins/forecast/Makefile
 	src/libcharon/plugins/farp/Makefile
+	src/libcharon/plugins/fndp_netlink/Makefile
 	src/libcharon/plugins/smp/Makefile
 	src/libcharon/plugins/sql/Makefile
 	src/libcharon/plugins/dnscert/Makefile
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index e530205..0647732 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -240,6 +240,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_FNDP_NETLINK
+  SUBDIRS += plugins/fndp_netlink
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/fndp_netlink/libstrongswan-fndp-netlink.la
+endif
+endif
+
 if USE_STROKE
   SUBDIRS += plugins/stroke
 if MONOLITHIC
diff --git a/src/libcharon/plugins/fndp_netlink/Makefile.am b/src/libcharon/plugins/fndp_netlink/Makefile.am
new file mode 100644
index 0000000..7b99c7b
--- /dev/null
+++ b/src/libcharon/plugins/fndp_netlink/Makefile.am
@@ -0,0 +1,27 @@
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libcharon \
+	-I$(top_srcdir)/src/libcharon/plugins/kernel_netlink
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+libstrongswan_fndp_netlink_la_SOURCES = \
+	fndp_netlink_plugin.h fndp_netlink_plugin.c \
+	fndp_netlink_listener.h fndp_netlink_listener.c \
+	fndp_netlink_interface.h fndp_netlink_interface.c \
+	$(top_srcdir)/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-fndp-netlink.la
+if !USE_KERNEL_NETLINK
+libstrongswan_fndp_netlink_la_SOURCES += \
+	$(top_srcdir)/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
+endif
+else
+plugin_LTLIBRARIES = libstrongswan-fndp-netlink.la
+libstrongswan_fndp_netlink_la_SOURCES += \
+	$(top_srcdir)/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
+endif
+
+libstrongswan_fndp_netlink_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/fndp_netlink/fndp_netlink_interface.c b/src/libcharon/plugins/fndp_netlink/fndp_netlink_interface.c
new file mode 100644
index 0000000..0ca893b
--- /dev/null
+++ b/src/libcharon/plugins/fndp_netlink/fndp_netlink_interface.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2016 Volker Rümelin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "fndp_netlink_interface.h"
+
+#include <kernel_netlink_shared.h>
+
+#include <linux/rtnetlink.h>
+#include <net/if.h>
+
+ENUM(fndp_rtm_names, RTM_NEWLINK, RTM_GETRULE,
+	"RTM_NEWLINK",
+	"RTM_DELLINK",
+	"RTM_GETLINK",
+	"RTM_SETLINK",
+	"RTM_NEWADDR",
+	"RTM_DELADDR",
+	"RTM_GETADDR",
+	"31",
+	"RTM_NEWROUTE",
+	"RTM_DELROUTE",
+	"RTM_GETROUTE",
+	"35",
+	"RTM_NEWNEIGH",
+	"RTM_DELNEIGH",
+	"RTM_GETNEIGH",
+	"RTM_NEWRULE",
+	"RTM_DELRULE",
+	"RTM_GETRULE",
+);
+
+typedef struct private_fndp_netlink_interface_t
+	private_fndp_netlink_interface_t;
+
+/**
+ * Private data of fndp netlink interface
+ */
+struct private_fndp_netlink_interface_t {
+
+	/**
+	 * Implements fndp netlink interface
+	 */
+	fndp_netlink_interface_t public;
+
+	/**
+	 * Netlink socket
+	 */
+	netlink_socket_t *socket;
+};
+
+static bool modify_proxy(private_fndp_netlink_interface_t *this, host_t *proxy,
+						 char *iface, int msgtype, int msgflags)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *hdr;
+	struct ndmsg *msg;
+	chunk_t chunk;
+
+	memset(&request, 0, sizeof(request));
+
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = msgflags | NLM_F_REQUEST | NLM_F_ACK;
+	hdr->nlmsg_type = msgtype;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+
+	msg = NLMSG_DATA(hdr);
+	msg->ndm_family = proxy->get_family(proxy);
+	msg->ndm_state = NUD_PERMANENT;
+	msg->ndm_flags = NTF_PROXY;
+	msg->ndm_ifindex = if_nametoindex(iface);
+
+	chunk = proxy->get_address(proxy);
+	netlink_add_attribute(hdr, NDA_DST, chunk, sizeof(request));
+
+	return this->socket->send_ack(this->socket, hdr) == SUCCESS;
+}
+
+METHOD(fndp_netlink_interface_t, install_proxy, bool,
+	private_fndp_netlink_interface_t *this, host_t *proxy, char *iface)
+{
+	return modify_proxy(this, proxy, iface, RTM_NEWNEIGH,
+						NLM_F_CREATE | NLM_F_EXCL);
+}
+
+METHOD(fndp_netlink_interface_t, remove_proxy, bool,
+	private_fndp_netlink_interface_t *this, host_t *proxy, char *iface)
+{
+	return modify_proxy(this, proxy, iface, RTM_DELNEIGH, 0);
+}
+
+METHOD(fndp_netlink_interface_t, destroy, void,
+	private_fndp_netlink_interface_t *this)
+{
+	DESTROY_IF(this->socket);
+	free(this);
+}
+
+/**
+ * Create a fndp_netlink_interface instance
+ */
+fndp_netlink_interface_t *fndp_netlink_interface_create()
+{
+	private_fndp_netlink_interface_t *this;
+
+	INIT(this,
+		.public = {
+			.install_proxy = _install_proxy,
+			.remove_proxy = _remove_proxy,
+			.destroy = _destroy,
+		},
+		.socket = netlink_socket_create(NETLINK_ROUTE, fndp_rtm_names, FALSE),
+	);
+
+	if (!this->socket)
+	{
+		destroy(this);
+		return NULL;
+	}
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/fndp_netlink/fndp_netlink_interface.h b/src/libcharon/plugins/fndp_netlink/fndp_netlink_interface.h
new file mode 100644
index 0000000..0646d76
--- /dev/null
+++ b/src/libcharon/plugins/fndp_netlink/fndp_netlink_interface.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 Volker Rümelin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @defgroup fndp_netlink_interface fndp_netlink_interface
+ * @{ @ingroup fndp_netlink
+ */
+
+#ifndef FNDP_NETLINK_INTERFACE_H_
+#define FNDP_NETLINK_INTERFACE_H_
+
+#include <networking/host.h>
+
+typedef struct fndp_netlink_interface_t fndp_netlink_interface_t;
+
+/**
+ * Netlink interface.
+ */
+struct fndp_netlink_interface_t {
+
+	/**
+	 * Install proxy address in kernel neighbour table.
+	 *
+	 * @param host		proxy address
+	 * @param iface		interface name
+	 * @return			TRUE if installation was successful
+	 */
+	bool (*install_proxy)(fndp_netlink_interface_t *this,
+						  host_t *host, char *iface);
+
+	/**
+	 * Remove proxy address from kernel neighbour table.
+	 *
+	 * @param host		proxy address
+	 * @param iface		interface name
+	 * @return			TRUE if proxy address was successfully removed
+	 */
+	bool (*remove_proxy)(fndp_netlink_interface_t *this,
+						 host_t *host, char *iface);
+
+	/**
+	 * Destroy this fndp_netlink_interface instance.
+	 */
+	void (*destroy)(fndp_netlink_interface_t *this);
+};
+
+/**
+ * Create a fndp_netlink_interface instance.
+ */
+fndp_netlink_interface_t *fndp_netlink_interface_create();
+
+#endif /** FNDP_NETLINK_INTERFACE_H_ @}*/
diff --git a/src/libcharon/plugins/fndp_netlink/fndp_netlink_listener.c b/src/libcharon/plugins/fndp_netlink/fndp_netlink_listener.c
new file mode 100644
index 0000000..26969e7
--- /dev/null
+++ b/src/libcharon/plugins/fndp_netlink/fndp_netlink_listener.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2016 Volker Rümelin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "fndp_netlink_listener.h"
+
+#include "fndp_netlink_interface.h"
+#include <daemon.h>
+#include <collections/hashtable.h>
+
+typedef struct proxy_addr_entry_t proxy_addr_entry_t;
+
+struct proxy_addr_entry_t {
+	/** Proxy address **/
+	host_t *ip;
+
+	/** Interface name **/
+	char *iface;
+
+	/** Installation result **/
+	bool installed;
+};
+
+/**
+ * Hash a proxy_addr_entry_t object
+ */
+static u_int proxy_addr_entry_hash(proxy_addr_entry_t *this)
+{
+	return chunk_hash(this->ip->get_address(this->ip));
+}
+
+/**
+ * Compare two proxy_addr_entry_t objects, two entries are equal if the
+ * IP address is the same
+ */
+static bool proxy_addr_entry_equals(proxy_addr_entry_t *a,
+	proxy_addr_entry_t *b)
+{
+	return a->ip->ip_equals(a->ip, b->ip);
+}
+
+typedef struct private_fndp_netlink_listener_t private_fndp_netlink_listener_t;
+
+/**
+ * Private data of a fndp_netlink_listener_t object
+ */
+struct private_fndp_netlink_listener_t {
+
+	/**
+	 * Public fndp_netlink_listener_t interface
+	 */
+	fndp_netlink_listener_t public;
+
+	/**
+	 * Netlink interface
+	 */
+	fndp_netlink_interface_t *netlink;
+
+	/**
+	 * Collection of installed proxy addresses
+	 */
+	hashtable_t *addrs;
+
+	/**
+	 * Install NDP proxies
+	 */
+	bool proxy_ipv6;
+
+	/**
+	 * Install ARP proxies
+	 */
+	bool proxy_ipv4;
+};
+
+static bool local_ts_includes(child_sa_t *child_sa, host_t *ip)
+{
+	enumerator_t *enumerator;
+	traffic_selector_t *ts;
+	bool found = FALSE;
+
+	enumerator = child_sa->create_ts_enumerator(child_sa, TRUE);
+	while (!found && enumerator->enumerate(enumerator, &ts))
+	{
+		found = ts->includes(ts, ip);
+	}
+	enumerator->destroy(enumerator);
+
+	return found;
+}
+
+METHOD(listener_t, child_updown, bool,
+	private_fndp_netlink_listener_t *this,
+	ike_sa_t *ike_sa, child_sa_t *child_sa, bool up)
+{
+	enumerator_t *enumerator;
+	traffic_selector_t *ts;
+
+	enumerator = child_sa->create_ts_enumerator(child_sa, FALSE);
+	while (enumerator->enumerate(enumerator, &ts))
+	{
+		proxy_addr_entry_t lookup, *entry;
+		uint8_t mask;
+
+		if (!ts->is_host(ts, NULL))
+		{
+			continue;
+		}
+
+		lookup.ip = NULL;
+		ts->to_subnet(ts, &lookup.ip, &mask);
+		if (!lookup.ip)
+		{
+			continue;
+		}
+
+		lookup.iface = NULL;
+		lookup.installed = FALSE;
+		entry = this->addrs->get(this->addrs, &lookup);
+
+		if (up)
+		{
+			host_t *nh;
+
+			if (entry || !(
+				(this->proxy_ipv6 &&
+				 lookup.ip->get_family(lookup.ip) == AF_INET6) ||
+				(this->proxy_ipv4 &&
+				 lookup.ip->get_family(lookup.ip) == AF_INET)
+				) || !local_ts_includes(child_sa, lookup.ip))
+			{
+				lookup.ip->destroy(lookup.ip);
+				continue;
+			}
+
+			nh = charon->kernel->get_nexthop(charon->kernel, lookup.ip, -1,
+											 NULL, &lookup.iface);
+			/* Install proxy if we have a route to the proxy address
+			 * but no gateway. In that case get_nexthop returns the
+			 * proxy address. */
+			if (nh && nh->ip_equals(nh, lookup.ip) && lookup.iface)
+			{
+				proxy_addr_entry_t *proxy;
+
+				DBG1(DBG_NET, "installing proxy for %H on interface %s",
+					 lookup.ip, lookup.iface);
+				nh->destroy(nh);
+
+				INIT(proxy,
+					.ip = lookup.ip,
+					.iface = lookup.iface,
+					.installed = this->netlink->install_proxy(this->netlink,
+															  lookup.ip,
+															  lookup.iface),
+				);
+				this->addrs->put(this->addrs, proxy, proxy);
+				continue;
+			}
+			DESTROY_IF(nh);
+			free(lookup.iface);
+			lookup.ip->destroy(lookup.ip);
+		}
+		else
+		{
+			lookup.ip->destroy(lookup.ip);
+
+			if (!entry)
+			{
+				continue;
+			}
+
+			if (entry->installed)
+			{
+				DBG1(DBG_NET, "removing proxy for %H on interface %s",
+					 entry->ip, entry->iface);
+				this->netlink->remove_proxy(this->netlink,
+											entry->ip, entry->iface);
+			}
+
+			entry = this->addrs->remove(this->addrs, entry);
+			free(entry->iface);
+			entry->ip->destroy(entry->ip);
+			free(entry);
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	return TRUE;
+}
+
+METHOD(fndp_netlink_listener_t, reload, bool,
+	private_fndp_netlink_listener_t *this)
+{
+	this->proxy_ipv6 = lib->settings->get_bool(lib->settings,
+											   "%s.plugins.fndp-netlink.ipv6",
+											   TRUE, lib->ns);
+	this->proxy_ipv4 = lib->settings->get_bool(lib->settings,
+											   "%s.plugins.fndp-netlink.ipv4",
+											   FALSE, lib->ns);
+	return TRUE;
+}
+
+METHOD(fndp_netlink_listener_t, destroy, void,
+	private_fndp_netlink_listener_t *this)
+{
+	DESTROY_IF(this->addrs);
+	DESTROY_IF(this->netlink);
+	free(this);
+}
+
+/**
+ * See header
+ */
+fndp_netlink_listener_t *fndp_netlink_listener_create()
+{
+	private_fndp_netlink_listener_t *this;
+
+	INIT(this,
+		.public = {
+			.listener = {
+				.child_updown = _child_updown,
+			},
+			.reload = _reload,
+			.destroy = _destroy,
+		},
+		.netlink = fndp_netlink_interface_create(),
+		.addrs = hashtable_create((hashtable_hash_t)proxy_addr_entry_hash,
+								  (hashtable_equals_t)proxy_addr_entry_equals,
+								  16),
+	);
+
+	if (!this->netlink || !this->addrs)
+	{
+		destroy(this);
+		return NULL;
+	}
+
+	reload(this);
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/fndp_netlink/fndp_netlink_listener.h b/src/libcharon/plugins/fndp_netlink/fndp_netlink_listener.h
new file mode 100644
index 0000000..23b639d
--- /dev/null
+++ b/src/libcharon/plugins/fndp_netlink/fndp_netlink_listener.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 Volker Rümelin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @defgroup fndp_netlink_listener fndp_netlink_listener
+ * @{ @ingroup fndp_netlink
+ */
+
+#ifndef FNDP_NETLINK_LISTENER_H_
+#define FNDP_NETLINK_LISTENER_H_
+
+#include <bus/listeners/listener.h>
+
+typedef struct fndp_netlink_listener_t fndp_netlink_listener_t;
+
+/**
+ * Listener to register and manage proxy host addresses.
+ */
+struct fndp_netlink_listener_t {
+
+	/**
+	 * Implements listener_t interface.
+	 */
+	listener_t listener;
+
+	/**
+	 * Reload configuration.
+	 */
+	bool (*reload)(fndp_netlink_listener_t *this);
+
+	/**
+	 * Destroy this fndp_netlink_listener instance.
+	 */
+	void (*destroy)(fndp_netlink_listener_t *this);
+};
+
+/**
+ * Create a fndp_netlink_listener instance.
+ */
+fndp_netlink_listener_t *fndp_netlink_listener_create();
+
+#endif /** FNDP_NETLINK_LISTENER_H_ @}*/
diff --git a/src/libcharon/plugins/fndp_netlink/fndp_netlink_plugin.c b/src/libcharon/plugins/fndp_netlink/fndp_netlink_plugin.c
new file mode 100644
index 0000000..e0f8ea4
--- /dev/null
+++ b/src/libcharon/plugins/fndp_netlink/fndp_netlink_plugin.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2016 Volker Rümelin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "fndp_netlink_plugin.h"
+
+#include "fndp_netlink_listener.h"
+#include <daemon.h>
+
+typedef struct private_fndp_netlink_plugin_t private_fndp_netlink_plugin_t;
+
+/**
+ * Private data of fndp-netlink plugin
+ */
+struct private_fndp_netlink_plugin_t {
+
+	/**
+	 * Implements plugin interface
+	 */
+	fndp_netlink_plugin_t public;
+
+	/**
+	 * Listener registering active virtual IPs
+	 */
+	fndp_netlink_listener_t *listener;
+};
+
+METHOD(plugin_t, get_name, char *,
+	private_fndp_netlink_plugin_t *this)
+{
+	return "fndp-netlink";
+}
+
+/**
+ * Register listener
+ */
+static bool plugin_cb(private_fndp_netlink_plugin_t *this,
+					  plugin_feature_t *feature, bool reg, void *cb_data)
+{
+	if (reg)
+	{
+		charon->bus->add_listener(charon->bus, &this->listener->listener);
+	}
+	else
+	{
+		charon->bus->remove_listener(charon->bus, &this->listener->listener);
+	}
+	return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+	private_fndp_netlink_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
+			PLUGIN_PROVIDE(CUSTOM, "fndp-netlink"),
+	};
+	*features = f;
+	return countof(f);
+}
+
+METHOD(plugin_t, reload, bool,
+	private_fndp_netlink_plugin_t *this)
+{
+	return this->listener->reload(this->listener);
+}
+
+METHOD(plugin_t, destroy, void,
+	private_fndp_netlink_plugin_t *this)
+{
+	DESTROY_IF(this->listener);
+	free(this);
+}
+
+/**
+ * Plugin constructor
+ */
+plugin_t *fndp_netlink_plugin_create()
+{
+	private_fndp_netlink_plugin_t *this;
+
+	INIT(this,
+		.public = {
+			.plugin = {
+				.get_name = _get_name,
+				.get_features = _get_features,
+				.reload = _reload,
+				.destroy = _destroy,
+			},
+		},
+		.listener = fndp_netlink_listener_create(),
+	);
+
+	if (!this->listener)
+	{
+		destroy(this);
+		return NULL;
+	}
+
+	return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/fndp_netlink/fndp_netlink_plugin.h b/src/libcharon/plugins/fndp_netlink/fndp_netlink_plugin.h
new file mode 100644
index 0000000..0042cd7
--- /dev/null
+++ b/src/libcharon/plugins/fndp_netlink/fndp_netlink_plugin.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 Volker Rümelin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @defgroup fndp_netlink fndp_netlink
+ * @ingroup cplugins
+ *
+ * @defgroup fndp_netlink_plugin fndp_netlink_plugin
+ * @{ @ingroup fndp_netlink
+ */
+
+#ifndef FNDP_NETLINK_PLUGIN_H_
+#define FNDP_NETLINK_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct fndp_netlink_plugin_t fndp_netlink_plugin_t;
+
+/**
+ * NDP and ARP faking plugin that responds to neighbour discovery
+ * and address resolution requests for peers virtual IP.
+ */
+struct fndp_netlink_plugin_t {
+
+	/**
+	 * Implements plugin interface.
+	 */
+	plugin_t plugin;
+};
+
+#endif /** FNDP_NETLINK_PLUGIN_H_ @}*/
-- 
1.8.4.5



More information about the Dev mailing list