[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