From 31f772c7d8db888df7fd62683d99b8513738bca0 Mon Sep 17 00:00:00 2001
From: Bhushan Narkhede <bnarkhede@marvell.com>
Date: Wed, 30 Nov 2022 03:24:08 -0800
References: jsc#PED-1539
Upstream: no
Subject: [PATCH] Marvell core changes and dummy plugin v5.9.7

---
 conf/Makefile.am                              |   1 +
 conf/options/charon.opt                       |   3 +
 conf/plugins/auth-els.opt                     |   5 +
 configure.ac                                  |  27 ++
 src/charon-cmd/cmd/cmd_connection.c           |  24 +-
 src/charon-nm/nm/nm_service.c                 |  24 +-
 src/charon/Makefile.am                        |   4 +
 src/libcharon/Makefile.am                     |   8 +
 src/libcharon/config/ike_cfg.c                |  58 ++-
 src/libcharon/config/peer_cfg.c               |  29 ++
 src/libcharon/config/peer_cfg.h               |  31 ++
 src/libcharon/encoding/parser.c               |  35 ++
 .../payloads/traffic_selector_substructure.c  |  82 +++-
 .../payloads/traffic_selector_substructure.h  |  17 +
 src/libcharon/kernel/kernel_fc_sp.c           |  61 +++
 src/libcharon/kernel/kernel_fc_sp.h           | 366 ++++++++++++++++++
 src/libcharon/kernel/kernel_interface.c       | 188 ++++++++-
 src/libcharon/kernel/kernel_interface.h       |  50 ++-
 src/libcharon/kernel/kernel_ipsec.h           |  23 ++
 src/libcharon/network/sender.c                |  53 ++-
 src/libcharon/network/socket.h                |  27 ++
 src/libcharon/network/socket_manager.c        | 151 ++++++--
 src/libcharon/network/socket_manager.h        |  24 +-
 src/libcharon/plugins/auth_els/Makefile.am    |  25 ++
 .../plugins/auth_els/auth_els_configs.c       | 183 +++++++++
 .../plugins/auth_els/auth_els_configs.h       |  41 ++
 src/libcharon/plugins/auth_els/auth_els_ike.c | 270 +++++++++++++
 src/libcharon/plugins/auth_els/auth_els_ike.h |  42 ++
 .../plugins/auth_els/auth_els_kernel_fc_sp.c  | 235 +++++++++++
 .../plugins/auth_els/auth_els_kernel_fc_sp.h  |  35 ++
 .../plugins/auth_els/auth_els_plugin.c        | 213 ++++++++++
 .../plugins/auth_els/auth_els_plugin.h        |  46 +++
 .../plugins/auth_els/auth_els_socket.c        | 114 ++++++
 .../plugins/auth_els/auth_els_socket.h        |  29 ++
 .../plugins/auth_els/auth_els_utils.h         |  60 +++
 src/libcharon/plugins/ha/ha_tunnel.c          |  24 +-
 .../kernel_netlink/kernel_netlink_net.c       |   2 +-
 .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c |  24 +-
 .../plugins/kernel_wfp/kernel_wfp_ipsec.c     |  23 ++
 .../plugins/load_tester/load_tester_config.c  |  24 +-
 src/libcharon/plugins/medcli/medcli_config.c  |  26 +-
 src/libcharon/plugins/medsrv/medsrv_config.c  |  24 +-
 src/libcharon/plugins/sql/sql_config.c        |  24 +-
 .../plugins/stroke/stroke_attribute.c         |  23 ++
 src/libcharon/plugins/stroke/stroke_config.c  |  28 +-
 src/libcharon/plugins/stroke/stroke_list.c    |  30 ++
 src/libcharon/plugins/uci/uci_config.c        |  26 +-
 src/libcharon/plugins/vici/vici_attribute.c   |  25 +-
 src/libcharon/plugins/vici/vici_config.c      |  39 +-
 src/libcharon/plugins/vici/vici_control.c     |  24 +-
 src/libcharon/processing/jobs/migrate_job.c   |  24 +-
 src/libcharon/sa/child_sa.c                   |  38 +-
 src/libcharon/sa/child_sa.h                   |  32 ++
 src/libcharon/sa/ike_sa.c                     |  49 ++-
 src/libcharon/sa/ike_sa.h                     |  25 ++
 src/libcharon/sa/ike_sa_manager.c             |  48 ++-
 src/libcharon/sa/ike_sa_manager.h             |  36 ++
 src/libcharon/sa/ikev1/tasks/informational.c  |  24 +-
 src/libcharon/sa/ikev1/tasks/isakmp_natd.c    |  24 +-
 src/libcharon/sa/ikev2/task_manager_v2.c      |  26 +-
 src/libcharon/sa/ikev2/tasks/child_create.c   |  27 +-
 src/libcharon/sa/ikev2/tasks/ike_mobike.c     |  27 +-
 src/libcharon/sa/ikev2/tasks/ike_natd.c       |  37 +-
 src/libstrongswan/networking/host.c           |  46 ++-
 src/libstrongswan/networking/host.h           |  31 ++
 .../selectors/traffic_selector.c              |  90 ++++-
 .../selectors/traffic_selector.h              |  49 +++
 src/libstrongswan/utils/identification.c      |  35 +-
 src/libstrongswan/utils/identification.h      |  28 ++
 src/libstrongswan/utils/parser_helper.c       | 114 +++++-
 src/libstrongswan/utils/utils.h               |  29 ++
 src/swanctl/swanctl.c                         |  94 +++++
 74 files changed, 3816 insertions(+), 115 deletions(-)
 create mode 100644 conf/plugins/auth-els.opt
 create mode 100644 src/libcharon/kernel/kernel_fc_sp.c
 create mode 100644 src/libcharon/kernel/kernel_fc_sp.h
 create mode 100644 src/libcharon/plugins/auth_els/Makefile.am
 create mode 100644 src/libcharon/plugins/auth_els/auth_els_configs.c
 create mode 100644 src/libcharon/plugins/auth_els/auth_els_configs.h
 create mode 100644 src/libcharon/plugins/auth_els/auth_els_ike.c
 create mode 100644 src/libcharon/plugins/auth_els/auth_els_ike.h
 create mode 100644 src/libcharon/plugins/auth_els/auth_els_kernel_fc_sp.c
 create mode 100644 src/libcharon/plugins/auth_els/auth_els_kernel_fc_sp.h
 create mode 100644 src/libcharon/plugins/auth_els/auth_els_plugin.c
 create mode 100644 src/libcharon/plugins/auth_els/auth_els_plugin.h
 create mode 100644 src/libcharon/plugins/auth_els/auth_els_socket.c
 create mode 100644 src/libcharon/plugins/auth_els/auth_els_socket.h
 create mode 100644 src/libcharon/plugins/auth_els/auth_els_utils.h

diff --git a/conf/Makefile.am b/conf/Makefile.am
index 74fb63680..540a3b563 100644
--- a/conf/Makefile.am
+++ b/conf/Makefile.am
@@ -32,6 +32,7 @@ plugins = \
 	plugins/android_log.opt \
 	plugins/attr.opt \
 	plugins/attr-sql.opt \
+	plugins/auth-els.opt \
 	plugins/bliss.opt \
 	plugins/botan.opt \
 	plugins/bypass-lan.opt \
diff --git a/conf/options/charon.opt b/conf/options/charon.opt
index 7d00e1a8c..3fef9d35b 100644
--- a/conf/options/charon.opt
+++ b/conf/options/charon.opt
@@ -420,6 +420,9 @@ charon.send_delay_request = yes
 charon.send_delay_type = 0
 	Specific IKEv2 message type to delay, 0 for any.
 
+charon.sender_thread_count = 1
+        For applications that require connection scaling, this allows creation of multiples threads to do sends.
+
 charon.send_vendor_id = no
 	Send strongSwan vendor ID payload
 
diff --git a/conf/plugins/auth-els.opt b/conf/plugins/auth-els.opt
new file mode 100644
index 000000000..38b670c94
--- /dev/null
+++ b/conf/plugins/auth-els.opt
@@ -0,0 +1,5 @@
+charon.plugins.auth-els.disabled_remotes.remote_1.wwpn = 21:00:00:24:ff:78:30:c5
+	WWPN of remote port.
+
+charon.plugins.auth-els.disabled_remotes.remote_1.wwpn_separator = . : -
+	WWPN separated by : . -.
diff --git a/configure.ac b/configure.ac
index dd9d128c1..06a9ad284 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,6 +16,28 @@
 # for more details.
 #
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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.
+ */
+
 # ============================
 #  initialize & set some vars
 # ============================
@@ -215,6 +237,7 @@ ARG_ENABL_SET([eap-tnc],        [enable EAP TNC trusted network connect module.]
 ARG_ENABL_SET([eap-dynamic],    [enable dynamic EAP proxy module.])
 ARG_ENABL_SET([eap-radius],     [enable RADIUS proxy authentication module.])
 ARG_ENABL_SET([ext-auth],       [enable plugin calling an external authorization script.])
+ARG_ENABL_SET([auth-els],       [enable auth els plugin authorization module.])
 ARG_ENABL_SET([ipseckey],       [enable IPSECKEY authentication plugin.])
 ARG_ENABL_SET([keychain],       [enables OS X Keychain Services credential set.])
 ARG_ENABL_SET([pkcs11],         [enables the PKCS11 token support plugin.])
@@ -1571,6 +1594,7 @@ ADD_PLUGIN([kernel-wfp],           [c charon])
 ADD_PLUGIN([kernel-iph],           [c charon])
 ADD_PLUGIN([kernel-pfkey],         [c charon starter nm cmd])
 ADD_PLUGIN([kernel-pfroute],       [c charon starter nm cmd])
+ADD_PLUGIN([auth-els],             [c charon])
 ADD_PLUGIN([kernel-netlink],       [c charon starter nm cmd])
 ADD_PLUGIN([selinux],              [c charon starter nm cmd])
 ADD_PLUGIN([resolve],              [c charon cmd])
@@ -1755,6 +1779,8 @@ AM_CONDITIONAL(USE_KERNEL_WFP, test x$kernel_wfp = xtrue)
 AM_CONDITIONAL(USE_KERNEL_IPH, test x$kernel_iph = xtrue)
 AM_CONDITIONAL(USE_WHITELIST, test x$whitelist = xtrue)
 AM_CONDITIONAL(USE_EXT_AUTH, test x$ext_auth = xtrue)
+AM_CONDITIONAL(USE_AUTH_ELS, test x$auth_els = xtrue)
+AM_CONDITIONAL(USE_DISABLE_SIGNAL_HANDLER, test x$auth_els = xtrue)
 AM_CONDITIONAL(USE_LOOKIP, test x$lookip = xtrue)
 AM_CONDITIONAL(USE_ERROR_NOTIFY, test x$error_notify = xtrue)
 AM_CONDITIONAL(USE_CERTEXPIRE, test x$certexpire = xtrue)
@@ -2102,6 +2128,7 @@ AC_CONFIG_FILES([
 	src/libcharon/plugins/kernel_iph/Makefile
 	src/libcharon/plugins/whitelist/Makefile
 	src/libcharon/plugins/ext_auth/Makefile
+	src/libcharon/plugins/auth_els/Makefile
 	src/libcharon/plugins/lookip/Makefile
 	src/libcharon/plugins/error_notify/Makefile
 	src/libcharon/plugins/certexpire/Makefile
diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c
index 8c09cac89..0467882da 100644
--- a/src/charon-cmd/cmd/cmd_connection.c
+++ b/src/charon-cmd/cmd/cmd_connection.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "cmd_connection.h"
 
 #include <signal.h>
@@ -180,7 +202,7 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
 			break;
 	}
 
-	ike.local_port = charon->socket->get_port(charon->socket, FALSE);
+	ike.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE);
 	if (ike.local_port != IKEV2_UDP_PORT)
 	{
 		ike.remote_port = IKEV2_NATT_PORT;
diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c
index 5d6d32950..07c3ab049 100644
--- a/src/charon-nm/nm/nm_service.c
+++ b/src/charon-nm/nm/nm_service.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "nm_service.h"
 
 #include <daemon.h>
@@ -614,7 +636,7 @@ static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
 	ike_cfg_create_t ike = {
 		.version = IKEV2,
 		.local = "%any",
-		.local_port = charon->socket->get_port(charon->socket, FALSE),
+		.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE),
 		.remote_port = IKEV2_UDP_PORT,
 		.fragmentation = FRAGMENTATION_YES,
 	};
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am
index b78bbd757..f490be6e6 100644
--- a/src/charon/Makefile.am
+++ b/src/charon/Makefile.am
@@ -17,4 +17,8 @@ charon_LDADD = \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	-lm $(PTHREADLIB) $(ATOMICLIB) $(DLLIB)
 
+if USE_DISABLE_SIGNAL_HANDLER
+  AM_CPPFLAGS += -DDISABLE_SIGNAL_HANDLER
+endif
+
 EXTRA_DIST = Android.mk
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index fb6de8ebd..af68e1d56 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -47,6 +47,7 @@ encoding/payloads/hash_payload.c encoding/payloads/hash_payload.h \
 encoding/payloads/fragment_payload.c encoding/payloads/fragment_payload.h \
 kernel/kernel_interface.c kernel/kernel_interface.h \
 kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
+kernel/kernel_fc_sp.c kernel/kernel_fc_sp.h \
 kernel/kernel_net.c kernel/kernel_net.h \
 kernel/kernel_listener.h kernel/kernel_handler.c kernel/kernel_handler.h \
 network/receiver.c network/receiver.h network/sender.c network/sender.h \
@@ -327,6 +328,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_AUTH_ELS
+  SUBDIRS += plugins/auth_els
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/auth_els/libstrongswan-auth-els.la
+endif
+endif
+
 if USE_EAP_IDENTITY
   SUBDIRS += plugins/eap_identity
 if MONOLITHIC
diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c
index 792f8022a..79cb0b53a 100644
--- a/src/libcharon/config/ike_cfg.c
+++ b/src/libcharon/config/ike_cfg.c
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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.
+ */
+
 #define _GNU_SOURCE /* for stdndup() */
 #include <string.h>
 
@@ -120,6 +142,11 @@ struct private_ike_cfg_t {
 	 * List of proposals to use
 	 */
 	linked_list_t *proposals;
+	
+	/**
+	 * Indicates that this config is for FC_ADDR 
+	 */
+	bool fc_addr;
 };
 
 METHOD(ike_cfg_t, get_version, ike_version_t,
@@ -198,7 +225,7 @@ METHOD(ike_cfg_t, resolve_other, host_t*,
 /**
  * Common function for match_me/other
  */
-static u_int match(linked_list_t *hosts, linked_list_t *ranges, host_t *cand)
+static u_int match(linked_list_t *hosts, linked_list_t *ranges, host_t *cand, bool fc_addr)
 {
 	enumerator_t *enumerator;
 	traffic_selector_t *ts;
@@ -211,6 +238,11 @@ static u_int match(linked_list_t *hosts, linked_list_t *ranges, host_t *cand)
 	enumerator = hosts->create_enumerator(hosts);
 	while (enumerator->enumerate(enumerator, &str))
 	{
+		if (cand->get_family(cand) == AF_NETLINK && !fc_addr)
+		{
+			DBG1 (DBG_IKE, "ike_cfg.c: Looking for FC addr but this ike_cfg is not for FC");
+			continue;
+		}
 		host = host_create_from_dns(str, cand->get_family(cand), 0);
 		if (host)
 		{
@@ -252,13 +284,13 @@ static u_int match(linked_list_t *hosts, linked_list_t *ranges, host_t *cand)
 METHOD(ike_cfg_t, match_me, u_int,
 	private_ike_cfg_t *this, host_t *host)
 {
-	return match(this->my_hosts, this->my_ranges, host);
+	return match(this->my_hosts, this->my_ranges, host, this->fc_addr);
 }
 
 METHOD(ike_cfg_t, match_other, u_int,
 	private_ike_cfg_t *this, host_t *host)
 {
-	return match(this->other_hosts, this->other_ranges, host);
+	return match(this->other_hosts, this->other_ranges, host, this->fc_addr);
 }
 
 METHOD(ike_cfg_t, get_my_addr, char*,
@@ -451,7 +483,7 @@ static traffic_selector_t* make_range(char *str)
 	{
 		return NULL;
 	}
-	if (to->get_family(to) == AF_INET)
+	if (to->get_family(to) == AF_INET || to->get_family(to) == AF_NETLINK)
 	{
 		type = TS_IPV4_ADDR_RANGE;
 	}
@@ -507,6 +539,12 @@ int ike_cfg_get_family(ike_cfg_t *cfg, bool local)
 	char *str;
 	int family = AF_UNSPEC;
 
+	// If this config is for FC, then we don't have to look any further.
+	if (this->fc_addr)
+	{
+		return AF_NETLINK;
+	}
+
 	if (local)
 	{
 		enumerator = this->my_hosts->create_enumerator(this->my_hosts);
@@ -553,6 +591,12 @@ bool ike_cfg_has_address(ike_cfg_t *cfg, host_t *addr, bool local)
 	char *str;
 	bool found = FALSE;
 
+	// If this config is for FC then make sure that is what they are looking for
+	if ((addr->get_family (addr) == AF_NETLINK) && !this->fc_addr)
+	{
+		return false;
+	}
+
 	if (local)
 	{
 		enumerator = this->my_hosts->create_enumerator(this->my_hosts);
@@ -626,6 +670,12 @@ ike_cfg_t *ike_cfg_create(ike_cfg_create_t *data)
 		.proposals = linked_list_create(),
 	);
 
+	if (strstr (data->local, "-fcsp") && strstr (data->remote, "-fcsp"))
+	{
+		this->fc_addr = true;
+		data->local[strlen (data->local) - 5] = '\0';
+		data->remote[strlen (data->remote) - 5] = '\0';
+	}
 	parse_addresses(data->local, this->my_hosts, this->my_ranges);
 	parse_addresses(data->remote, this->other_hosts, this->other_ranges);
 
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
index f08eef502..0c2da66cd 100644
--- a/src/libcharon/config/peer_cfg.c
+++ b/src/libcharon/config/peer_cfg.c
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 <string.h>
 
 #include "peer_cfg.h"
@@ -213,6 +235,12 @@ METHOD(peer_cfg_t, get_ike_cfg, ike_cfg_t*,
 	return this->ike_cfg;
 }
 
+METHOD(peer_cfg_t, set_ike_cfg, void,
+	private_peer_cfg_t *this, ike_cfg_t* ike_cfg)
+{
+	this->ike_cfg = ike_cfg;
+}
+
 METHOD(peer_cfg_t, add_child_cfg, void,
 	private_peer_cfg_t *this, child_cfg_t *child_cfg)
 {
@@ -822,6 +850,7 @@ peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
 			.get_name = _get_name,
 			.get_ike_version = _get_ike_version,
 			.get_ike_cfg = _get_ike_cfg,
+			.set_ike_cfg = _set_ike_cfg,
 			.add_child_cfg = _add_child_cfg,
 			.remove_child_cfg = (void*)_remove_child_cfg,
 			.replace_child_cfgs = _replace_child_cfgs,
diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h
index 6b0834339..24783a7e3 100644
--- a/src/libcharon/config/peer_cfg.h
+++ b/src/libcharon/config/peer_cfg.h
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 peer_cfg peer_cfg
  * @{ @ingroup config
@@ -141,6 +163,15 @@ struct peer_cfg_t {
 	 */
 	ike_cfg_t* (*get_ike_cfg) (peer_cfg_t *this);
 
+	/**
+	 * Set the IKE config to use for initiation.
+         * This is needed for FCSP2 because the ike_cfg is not created
+         * correctly by vici as it doesn't have all of the information.
+	 *
+	 * @param				the IKE config to use
+	 */
+        void (*set_ike_cfg) (peer_cfg_t *this, ike_cfg_t* ike_cfg);
+
 	/**
 	 * Attach a CHILD config.
 	 *
diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c
index 546d39931..38d81cc48 100644
--- a/src/libcharon/encoding/parser.c
+++ b/src/libcharon/encoding/parser.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 <stdlib.h>
 #include <string.h>
 
@@ -369,9 +391,11 @@ METHOD(parser_t, parse_payload, status_t,
 	payload_t *pld;
 	void *output;
 	int payload_length = 0, spi_size = 0, attribute_length = 0, header_length;
+	uint8_t ts_type = 0;
 	bool attribute_format = FALSE;
 	int rule_number, rule_count;
 	encoding_rule_t *rule;
+	payload_type_t pld_type = 0;
 
 	/* create instance of the payload to parse */
 	if (payload_is_known(payload_type, this->major_version))
@@ -389,6 +413,7 @@ METHOD(parser_t, parse_payload, status_t,
 	DBG3(DBG_ENC, "parsing payload from %b",
 		 this->byte_pos, (u_int)(this->input_roof - this->byte_pos));
 
+	pld_type = pld->get_type(pld);
 	/* base pointer for output, avoids casting in every rule */
 	output = pld;
 	/* parse the payload with its own rules */
@@ -420,6 +445,16 @@ METHOD(parser_t, parse_payload, status_t,
 					pld->destroy(pld);
 					return PARSE_ERROR;
 				}
+				if (pld_type == PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE)
+				{
+					ts_type = *(uint8_t*)(output + rule->offset);
+					if(ts_type == TS_FC_ADDR_RANGE)
+					{
+						traffic_selector_substructure_t *tsstruct = (traffic_selector_substructure_t*)pld;
+						tsstruct->set_ts_type(tsstruct, TS_FC_ADDR_RANGE);
+						rule_count = pld->get_encoding_rules(pld, &this->rules);
+					}
+				}
 				break;
 			}
 			case U_INT_16:
diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.c b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
index 8fbcdf98c..ed1caad08 100644
--- a/src/libcharon/encoding/payloads/traffic_selector_substructure.c
+++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "traffic_selector_substructure.h"
 
 #include <encoding/payloads/encodings.h>
@@ -122,6 +144,9 @@ static bool parse_ts_data(private_traffic_selector_substructure_t *this,
 		case TS_IPV6_ADDR_RANGE:
 			addr_len = 16;
 			break;
+		case TS_FC_ADDR_RANGE:
+			addr_len = 3;
+			break;
 		default:
 			return FALSE;
 	}
@@ -166,6 +191,32 @@ METHOD(payload_t, verify, status_t,
 			}
 			break;
 		}
+		case TS_FC_ADDR_RANGE:
+		{
+			uint16_t start_port, end_port;
+			chunk_t start_addr, end_addr;
+
+			if (!parse_ts_data(this, &start_port, &end_port, &start_addr,
+							   &end_addr))
+			{
+				return FAILED;
+			}
+
+			if (start_port > end_port)
+			{
+				/* OPAQUE ports are the only exception */
+				if (start_port != 0xffff && end_port != 0)
+				{
+					return FAILED;
+				}
+			}
+			if ((start_addr.len != 3) ||
+				(start_addr.len != 3))
+			{
+				return FAILED;
+			}
+			break;
+		}
 		case TS_SECLABEL:
 			if (!this->ts_data.len)
 			{
@@ -215,9 +266,26 @@ METHOD(payload_t, get_length, size_t,
 	return this->payload_length;
 }
 
+METHOD(traffic_selector_substructure_t, set_ts_type, void,
+	private_traffic_selector_substructure_t *this, ts_type_t ts_type)
+{
+	this->ts_type = ts_type;
+	if (this->ts_type == TS_FC_ADDR_RANGE)
+	{
+		this->payload_length = get_header_length(this) + 10; //starting address(3), ending address(3)
+	}
+}
+
+METHOD(traffic_selector_substructure_t, get_ts_type, ts_type_t,
+	private_traffic_selector_substructure_t *this)
+{
+	return this->ts_type;
+}
+
 METHOD(traffic_selector_substructure_t, get_traffic_selector, traffic_selector_t*,
 	private_traffic_selector_substructure_t *this)
 {
+	traffic_selector_t* ts = NULL;
 	uint16_t start_port, end_port;
 	chunk_t start_addr, end_addr;
 
@@ -225,9 +293,18 @@ METHOD(traffic_selector_substructure_t, get_traffic_selector, traffic_selector_t
 	{
 		return NULL;
 	}
+	if (this->ts_type == TS_FC_ADDR_RANGE)
+	{
+		ts = traffic_selector_create_from_fcsp2_format(start_addr, start_port,
+				end_addr, end_port);
+	}
+	else
+	{
 	return traffic_selector_create_from_bytes(
 									this->ip_protocol_id, this->ts_type,
 									start_addr, start_port, end_addr, end_port);
+    }
+    return ts;
 }
 
 METHOD(traffic_selector_substructure_t, get_sec_label, sec_label_t*,
@@ -266,6 +343,8 @@ traffic_selector_substructure_t *traffic_selector_substructure_create()
 				.get_type = _get_type,
 				.destroy = _destroy,
 			},
+			.get_ts_type = _get_ts_type,
+			.set_ts_type = _set_ts_type,
 			.get_traffic_selector = _get_traffic_selector,
 			.get_sec_label = _get_sec_label,
 			.destroy = _destroy,
@@ -290,7 +369,8 @@ traffic_selector_substructure_t *traffic_selector_substructure_create_from_traff
 	this->ts_type = ts->get_type(ts);
 	this->ip_protocol_id = ts->get_protocol(ts);
 
-	writer = bio_writer_create(this->ts_type == TS_IPV4_ADDR_RANGE ? 12 : 36);
+	writer = bio_writer_create(this->ts_type == TS_IPV4_ADDR_RANGE ? 12 : 
+        (this->ts_type == TS_FC_ADDR_RANGE) ? 14 : 36);
 	writer->write_uint16(writer, ts->get_from_port(ts));
 	writer->write_uint16(writer, ts->get_to_port(ts));
 	writer->write_data(writer, ts->get_from_address(ts));
diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.h b/src/libcharon/encoding/payloads/traffic_selector_substructure.h
index 57d940043..c8bf58815 100644
--- a/src/libcharon/encoding/payloads/traffic_selector_substructure.h
+++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.h
@@ -44,6 +44,23 @@ struct traffic_selector_substructure_t {
 	 */
 	payload_t payload_interface;
 
+	/**
+	 * Get the type of Traffic selector.
+	 *
+	 * @return			type of traffic selector
+	 *
+	 */
+	ts_type_t (*get_ts_type) (traffic_selector_substructure_t *this);
+
+	/**
+	 * Set the type of Traffic selector.
+	 *
+	 * @param ts_type	type of traffic selector
+	 */
+	void (*set_ts_type) (traffic_selector_substructure_t *this,
+						 ts_type_t ts_type);
+
+
 	/**
 	 * Get a traffic_selector_t from this substructure if possible.
 	 *
diff --git a/src/libcharon/kernel/kernel_fc_sp.c b/src/libcharon/kernel/kernel_fc_sp.c
new file mode 100644
index 000000000..947684c0f
--- /dev/null
+++ b/src/libcharon/kernel/kernel_fc_sp.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ * 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "kernel_fc_sp.h"
+
+#include <daemon.h>
+
+/**
+ * See header
+ */
+bool kernel_fc_sp_register(plugin_t *plugin, plugin_feature_t *feature,
+						   bool reg, void *data)
+{
+	if (reg)
+	{
+		return charon->kernel->add_fc_sp_interface(charon->kernel,
+											(kernel_fc_sp_constructor_t)data);
+	}
+	else
+	{
+		return charon->kernel->remove_fc_sp_interface(charon->kernel,
+											(kernel_fc_sp_constructor_t)data);
+	}
+}
+
+
diff --git a/src/libcharon/kernel/kernel_fc_sp.h b/src/libcharon/kernel/kernel_fc_sp.h
new file mode 100644
index 000000000..9e1339432
--- /dev/null
+++ b/src/libcharon/kernel/kernel_fc_sp.h
@@ -0,0 +1,366 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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.
+ */
+ 
+/* 
+ * File:   kernel_fc_sp.h
+ * Author: cwinkler
+ *
+ * Created on October 20, 2020, 2:19 PM
+ */
+
+#ifndef KERNEL_FC_SP_H
+#define KERNEL_FC_SP_H
+
+typedef struct kernel_fc_sp_t kernel_fc_sp_t;
+typedef struct kernel_fc_sp_sa_id_t kernel_fc_sp_sa_id_t;
+typedef struct kernel_fc_sp_add_sa_t kernel_fc_sp_add_sa_t;
+typedef struct kernel_fc_sp_update_sa_t kernel_fc_sp_update_sa_t;
+typedef struct kernel_fc_sp_query_sa_t kernel_fc_sp_query_sa_t;
+typedef struct kernel_fc_sp_del_sa_t kernel_fc_sp_del_sa_t;
+typedef struct kernel_fc_sp_policy_id_t kernel_fc_sp_policy_id_t;
+typedef struct kernel_fc_sp_manage_policy_t kernel_fc_sp_manage_policy_t;
+typedef struct kernel_fc_sp_query_policy_t kernel_fc_sp_query_policy_t;
+
+#include <networking/host.h>
+#include <ipsec/ipsec_types.h>
+#include <selectors/traffic_selector.h>
+#include <selectors/sec_label.h>
+#include <plugins/plugin.h>
+#include <kernel/kernel_interface.h>
+
+/**
+ * Data required to identify an SA in the kernel
+ */
+struct kernel_fc_sp_sa_id_t {
+	/** Source address */
+	host_t *src;
+	/** Destination address */
+	host_t *dst;
+	/** SPI */
+	uint32_t spi;
+	/** Protocol (ESP/AH) */
+	uint8_t proto;
+	/** Optional mark */
+	mark_t mark;
+	/** Optional interface ID */
+	uint32_t if_id;
+};
+
+/**
+ * Data required to add an SA to the kernel
+ */
+struct kernel_fc_sp_add_sa_t {
+	/** Reqid */
+	uint32_t reqid;
+	/** Mode (tunnel, transport...) */
+	ipsec_mode_t mode;
+	/** List of source traffic selectors */
+	linked_list_t *src_ts;
+	/** List of destination traffic selectors */
+	linked_list_t *dst_ts;
+	/** Network interface restricting policy */
+	char *interface;
+	/** Lifetime configuration */
+	lifetime_cfg_t *lifetime;
+	/** Encryption algorithm */
+	uint16_t enc_alg;
+	/** Encryption key */
+	chunk_t enc_key;
+	/** Integrity protection algorithm */
+	uint16_t int_alg;
+	/** Integrity protection key */
+	chunk_t int_key;
+	/** Anti-replay window size */
+	uint32_t replay_window;
+	/** Traffic Flow Confidentiality padding */
+	uint32_t tfc;
+	/** IPComp transform */
+	uint16_t ipcomp;
+	/** CPI for IPComp */
+	uint16_t cpi;
+	/** TRUE to enable UDP encapsulation for NAT traversal */
+	bool encap;
+	/** no (disabled), yes (enabled), auto (enabled if supported) */
+	hw_offload_t hw_offload;
+	/** Mark the SA should apply to packets after processing */
+	mark_t mark;
+	/** Security label to match or apply */
+	sec_label_t *label;
+	/** TRUE to use Extended Sequence Numbers */
+	bool esn;
+	/** TRUE to copy the DF bit to the outer IPv4 header in tunnel mode */
+	bool copy_df;
+	/** TRUE to copy the ECN header field to/from the outer header */
+	bool copy_ecn;
+	/** Whether to copy the DSCP header field to/from the outer header */
+	dscp_copy_t copy_dscp;
+	/** TRUE if initiator of the exchange creating the SA */
+	bool initiator;
+	/** TRUE if this is an inbound SA */
+	bool inbound;
+	/** TRUE if an SPI has already been allocated for this SA */
+	bool update;
+};
+
+/**
+ * Data required to update the hosts of an SA in the kernel
+ */
+struct kernel_fc_sp_update_sa_t {
+	/** CPI in case IPComp is used */
+	uint16_t cpi;
+	/** New source address */
+	host_t *new_src;
+	/** New destination address */
+	host_t *new_dst;
+	/** TRUE if UDP encapsulation is currently enabled */
+	bool encap;
+	/** TRUE to enable UDP encapsulation */
+	bool new_encap;
+};
+
+/**
+ * Data required to query an SA in the kernel
+ */
+struct kernel_fc_sp_query_sa_t {
+	uint16_t cpi;
+};
+
+/**
+ * Data required to delete an SA in the kernel
+ */
+struct kernel_fc_sp_del_sa_t {
+	/** CPI in case IPComp is used */
+	uint16_t cpi;
+};
+
+/**
+ * Data identifying a policy in the kernel
+ */
+struct kernel_fc_sp_policy_id_t {
+	/** Direction of traffic */
+	policy_dir_t dir;
+	/** Source traffic selector */
+	traffic_selector_t *src_ts;
+	/** Destination traffic selector */
+	traffic_selector_t *dst_ts;
+	/** Optional mark */
+	mark_t mark;
+	/** Optional interface ID */
+	uint32_t if_id;
+	/** Network interface restricting policy */
+	char *interface;
+};
+
+/**
+ * Data required to add/delete a policy to/from the kernel
+ */
+struct kernel_fc_sp_manage_policy_t {
+	/** Type of policy */
+	policy_type_t type;
+	/** Priority class */
+	policy_priority_t prio;
+	/** Manually-set priority (automatic if set to 0) */
+	uint32_t manual_prio;
+	/** Source address of the SA(s) tied to this policy */
+	host_t *src;
+	/** Destination address of the SA(s) tied to this policy */
+	host_t *dst;
+	/** Details about the SA(s) tied to this policy */
+	ipsec_sa_cfg_t *sa;
+};
+
+/**
+ * Data required to query a policy in the kernel
+ */
+struct kernel_fc_sp_query_policy_t {
+};
+
+
+/**
+ * Interface to the fc-sp subsystem.
+ *
+ * The kernel fc-sp interface handles the communication with the FC-SP 
+ * module that will communicate to the lower level that handles the SAs.
+ * FC-SP does not currently use policies so they are not provided in this
+ * implementation of the interface.
+ */
+struct kernel_fc_sp_t {
+
+	/**
+	 * Get the feature set supported by this kernel backend.
+	 *
+	 * @return				ORed feature-set of backend
+	 */
+	kernel_feature_t (*get_features)(kernel_fc_sp_t *this);
+
+	/**
+	 * Get a SPI from the kernel.
+	 *
+	 * @param src		source address of SA
+	 * @param dst		destination address of SA
+	 * @param protocol	protocol for SA (ESP/AH)
+	 * @param spi		allocated spi
+	 * @return			SUCCESS if operation completed
+	 */
+	status_t (*get_spi)(kernel_fc_sp_t *this, host_t *src, host_t *dst,
+						uint8_t protocol, uint32_t *spi);
+        
+        /**
+	 * Get a Compression Parameter Index (CPI) from the kernel.
+	 *
+	 * @param src		source address of SA
+	 * @param dst		destination address of SA
+	 * @param cpi		allocated cpi
+	 * @return			SUCCESS if operation completed
+	 */
+	status_t (*get_cpi)(kernel_fc_sp_t *this, host_t *src, host_t *dst,
+						uint16_t *cpi);
+
+	/**
+	 * Add an SA to the SAD.
+	 *
+	 * This function does install a single SA for a single protocol in one
+	 * direction.
+	 *
+	 * @param id			data identifying this SA
+	 * @param data			data for this SA
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*add_sa)(kernel_fc_sp_t *this, kernel_fc_sp_sa_id_t *id,
+					   kernel_fc_sp_add_sa_t *data);
+        
+        /**
+	 * Update the hosts on an installed SA.
+	 *
+	 * We cannot directly update the destination address as the kernel
+	 * requires the spi, the protocol AND the destination address (and family)
+	 * to identify SAs. Therefore if the destination address changed we
+	 * create a new SA and delete the old one.
+	 *
+	 * @param id			data identifying this SA
+	 * @param data			updated data for this SA
+	 * @return				SUCCESS if operation completed, NOT_SUPPORTED if
+	 *						the kernel interface can't update the SA
+	 */
+	status_t (*update_sa)(kernel_fc_sp_t *this, kernel_fc_sp_sa_id_t *id,
+						  kernel_fc_sp_update_sa_t *data);
+
+	/**
+	 * Query the number of bytes processed by an SA from the SAD.
+	 *
+	 * @param id			data identifying this SA
+	 * @param data			data to query the SA
+	 * @param[out] bytes	the number of bytes processed by SA
+	 * @param[out] packets	number of packets processed by SA
+	 * @param[out] time		last (monotonic) time of SA use
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*query_sa)(kernel_fc_sp_t *this, kernel_fc_sp_sa_id_t *id,
+						 kernel_fc_sp_query_sa_t *data, uint64_t *bytes,
+						 uint64_t *packets, time_t *time);
+
+	/**
+	 * Delete a previously installed SA from the SAD.
+	 *
+	 * @param id			data identifying this SA
+	 * @param data			data to delete the SA
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*del_sa)(kernel_fc_sp_t *this, kernel_fc_sp_sa_id_t *id,
+					   kernel_fc_sp_del_sa_t *data);
+        
+        /**
+	 * Add a policy to the SPD.
+	 *
+	 * @param id			data identifying this policy
+	 * @param data			data for this policy
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*add_policy)(kernel_fc_sp_t *this,
+						   kernel_fc_sp_policy_id_t *id,
+						   kernel_fc_sp_manage_policy_t *data);
+
+	/**
+	 * Query the use time of a policy.
+	 *
+	 * The use time of a policy is the time the policy was used for the last
+	 * time. It is not the system time, but a monotonic timestamp as returned
+	 * by time_monotonic.
+	 *
+	 * @param id			data identifying this policy
+	 * @param data			data to query the policy
+	 * @param[out] use_time	the monotonic timestamp of this SA's last use
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*query_policy)(kernel_fc_sp_t *this,
+							 kernel_fc_sp_policy_id_t *id,
+							 kernel_fc_sp_query_policy_t *data,
+							 time_t *use_time);
+
+	/**
+	 * Remove a policy from the SPD.
+	 *
+	 * @param id			data identifying this policy
+	 * @param data			data for this policy
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*del_policy)(kernel_fc_sp_t *this,
+						   kernel_fc_sp_policy_id_t *id,
+						   kernel_fc_sp_manage_policy_t *data);
+
+	/**
+	 * Install a bypass policy for the given socket.
+	 *
+	 * @param fd			socket file descriptor to setup policy for
+	 * @param family		protocol family of the socket
+	 * @return				TRUE of policy set up successfully
+	 */
+	bool (*bypass_socket)(kernel_fc_sp_t *this, int fd, int family);
+
+	/**
+	 * Enable decapsulation of ESP-in-UDP packets for the given port/socket.
+	 *
+	 * @param fd			socket file descriptor
+	 * @param family		protocol family of the socket
+	 * @param port			the UDP port
+	 * @return				TRUE if UDP decapsulation was enabled successfully
+	 */
+	bool (*enable_udp_decap)(kernel_fc_sp_t *this, int fd, int family,
+							 uint16_t port);
+
+	/**
+	 * Destroy the implementation.
+	 */
+	void (*destroy)(kernel_fc_sp_t *this);
+};
+
+bool kernel_fc_sp_register(plugin_t *plugin, plugin_feature_t *feature,
+						   bool reg, void *data);
+
+#endif /* KERNEL_FC_SP_H */
+
diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c
index 4f4a99731..e54f2acd8 100644
--- a/src/libcharon/kernel/kernel_interface.c
+++ b/src/libcharon/kernel/kernel_interface.c
@@ -37,6 +37,28 @@
  * THE SOFTWARE.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "kernel_interface.h"
 
 #include <utils/debug.h>
@@ -90,6 +112,11 @@ struct private_kernel_interface_t {
 	 */
 	kernel_ipsec_constructor_t ipsec_constructor;
 
+	/**
+	 * Registered FC-SP constructor
+	 */
+	kernel_fc_sp_constructor_t fc_sp_constructor;
+
 	/**
 	 * Registered net constructor
 	 */
@@ -100,6 +127,11 @@ struct private_kernel_interface_t {
 	 */
 	kernel_ipsec_t *ipsec;
 
+	/**
+	 * fc-sp interface
+	 */
+	kernel_fc_sp_t *fc_sp;
+
 	/**
 	 * network interface
 	 */
@@ -154,17 +186,27 @@ struct private_kernel_interface_t {
 };
 
 METHOD(kernel_interface_t, get_features, kernel_feature_t,
-	private_kernel_interface_t *this)
+	private_kernel_interface_t *this, int family)
 {
 	kernel_feature_t features = 0;
 
-	if (this->ipsec && this->ipsec->get_features)
+	if (family == AF_NETLINK)
 	{
-		features |= this->ipsec->get_features(this->ipsec);
+		if (this->fc_sp && this->fc_sp->get_features)
+		{
+			features |= this->fc_sp->get_features(this->fc_sp);
+		}
 	}
-	if (this->net && this->net->get_features)
+	else
 	{
-		features |= this->net->get_features(this->net);
+      	if (this->ipsec && this->ipsec->get_features)
+      	{
+      		features |= this->ipsec->get_features(this->ipsec);
+      	}
+      	if (this->net && this->net->get_features)
+      	{
+      		features |= this->net->get_features(this->net);
+      	}
 	}
 	return features;
 }
@@ -173,6 +215,19 @@ METHOD(kernel_interface_t, get_spi, status_t,
 	private_kernel_interface_t *this, host_t *src, host_t *dst,
 	uint8_t protocol, uint32_t *spi)
 {
+	
+	int family = src->get_family (src);
+	
+	if (family == AF_NETLINK)
+	{
+		if (!this->fc_sp)
+		{
+			return NOT_SUPPORTED;
+		}
+		
+		return this->fc_sp->get_spi (this->fc_sp, src, dst, protocol, spi);
+	}
+	
 	if (!this->ipsec)
 	{
 		return NOT_SUPPORTED;
@@ -184,6 +239,17 @@ METHOD(kernel_interface_t, get_cpi, status_t,
 	private_kernel_interface_t *this, host_t *src, host_t *dst,
 	uint16_t *cpi)
 {
+	int family = src->get_family (src);
+	
+	if (family == AF_NETLINK)
+	{
+		if (!this->fc_sp)
+		{
+			return NOT_SUPPORTED;
+		}
+		this->fc_sp->get_cpi (this->fc_sp, src, dst, cpi);
+	}
+	
 	if (!this->ipsec)
 	{
 		return NOT_SUPPORTED;
@@ -474,6 +540,18 @@ METHOD(kernel_interface_t, add_sa, status_t,
 	private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
 	kernel_ipsec_add_sa_t *data)
 {
+	int family = id->src->get_family (id->src);
+	
+	if (family == AF_NETLINK)
+	{
+		if (!this->fc_sp)
+		{
+			return NOT_SUPPORTED;
+		}
+		
+		return this->fc_sp->add_sa (this->fc_sp, (kernel_fc_sp_sa_id_t*) id, (kernel_fc_sp_add_sa_t*) data);
+	}
+	
 	if (!this->ipsec)
 	{
 		return NOT_SUPPORTED;
@@ -497,6 +575,18 @@ METHOD(kernel_interface_t, query_sa, status_t,
 	kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
 	time_t *time)
 {
+	int family = id->src->get_family (id->src);
+	
+	if (family == AF_NETLINK)
+	{
+		if (!this->fc_sp)
+		{
+			return NOT_SUPPORTED;
+		}
+		
+		return this->fc_sp->query_sa (this->fc_sp, (kernel_fc_sp_sa_id_t*) id, (kernel_fc_sp_query_sa_t*) data, bytes, packets, time);
+	}
+	
 	if (!this->ipsec)
 	{
 		return NOT_SUPPORTED;
@@ -508,6 +598,18 @@ METHOD(kernel_interface_t, del_sa, status_t,
 	private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
 	kernel_ipsec_del_sa_t *data)
 {
+	int family = id->src->get_family (id->src);
+	
+	if (family == AF_NETLINK)
+	{
+		if (!this->fc_sp)
+		{
+			return NOT_SUPPORTED;
+		}
+		
+		return this->fc_sp->del_sa (this->fc_sp, (kernel_fc_sp_sa_id_t*) id, (kernel_fc_sp_del_sa_t*) data);
+	}
+	
 	if (!this->ipsec)
 	{
 		return NOT_SUPPORTED;
@@ -529,6 +631,17 @@ METHOD(kernel_interface_t, add_policy, status_t,
 	private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
 	kernel_ipsec_manage_policy_t *data)
 {
+	int family = data->src->get_family (data->src);
+	
+	if (family == AF_NETLINK)
+	{
+		if (!this->fc_sp)
+		{
+			return NOT_SUPPORTED;
+		}
+		return this->fc_sp->add_policy(this->fc_sp, (kernel_fc_sp_policy_id_t*) id, (kernel_fc_sp_manage_policy_t*) data);
+	}
+	
 	if (!this->ipsec)
 	{
 		return NOT_SUPPORTED;
@@ -540,6 +653,14 @@ METHOD(kernel_interface_t, query_policy, status_t,
 	private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
 	kernel_ipsec_query_policy_t *data, time_t *use_time)
 {
+	if (data->family == AF_NETLINK)
+	{
+		if (!this->fc_sp)
+		{
+			return NOT_SUPPORTED;
+		}
+		return this->fc_sp->query_policy(this->fc_sp, (kernel_fc_sp_policy_id_t*) id, (kernel_fc_sp_query_policy_t*) data, use_time);
+	}
 	if (!this->ipsec)
 	{
 		return NOT_SUPPORTED;
@@ -551,6 +672,17 @@ METHOD(kernel_interface_t, del_policy, status_t,
 	private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
 	kernel_ipsec_manage_policy_t *data)
 {
+	int family = data->src->get_family (data->src);
+	
+	if (family == AF_NETLINK)
+	{
+		if (!this->fc_sp)
+		{
+			return NOT_SUPPORTED;
+		}
+		return this->fc_sp->del_policy (this->fc_sp, (kernel_fc_sp_policy_id_t*) id, (kernel_fc_sp_manage_policy_t*) data);
+	}
+	
 	if (!this->ipsec)
 	{
 		return NOT_SUPPORTED;
@@ -669,6 +801,15 @@ METHOD(kernel_interface_t, del_route, status_t,
 METHOD(kernel_interface_t, bypass_socket, bool,
 	private_kernel_interface_t *this, int fd, int family)
 {
+	if (family == AF_NETLINK)
+	{
+		if (!this->fc_sp)
+		{
+			return NOT_SUPPORTED;
+		}
+		return this->fc_sp->bypass_socket(this->fc_sp, fd, family);
+	}
+	
 	if (!this->ipsec)
 	{
 		return FALSE;
@@ -679,6 +820,15 @@ METHOD(kernel_interface_t, bypass_socket, bool,
 METHOD(kernel_interface_t, enable_udp_decap, bool,
 	private_kernel_interface_t *this, int fd, int family, uint16_t port)
 {
+	if (family == AF_NETLINK)
+	{
+		if (!this->fc_sp)
+		{
+			return NOT_SUPPORTED;
+		}
+		return this->fc_sp->enable_udp_decap(this->fc_sp, fd, family, port);
+	}
+	
 	if (!this->ipsec)
 	{
 		return FALSE;
@@ -813,6 +963,31 @@ METHOD(kernel_interface_t, remove_ipsec_interface, bool,
 	return FALSE;
 }
 
+
+METHOD(kernel_interface_t, add_fc_sp_interface, bool,
+	private_kernel_interface_t *this, kernel_fc_sp_constructor_t constructor)
+{
+	if (!this->fc_sp)
+	{
+		this->fc_sp_constructor = constructor;
+		this->fc_sp = constructor();
+		return this->fc_sp != NULL;
+	}
+	return FALSE;
+}
+
+METHOD(kernel_interface_t, remove_fc_sp_interface, bool,
+	private_kernel_interface_t *this, kernel_fc_sp_constructor_t constructor)
+{
+	if (constructor == this->fc_sp_constructor && this->fc_sp)
+	{
+		this->fc_sp->destroy(this->fc_sp);
+		this->fc_sp = NULL;
+		return TRUE;
+	}
+	return FALSE;
+}
+
 METHOD(kernel_interface_t, add_net_interface, bool,
 	private_kernel_interface_t *this, kernel_net_constructor_t constructor)
 {
@@ -1031,6 +1206,7 @@ METHOD(kernel_interface_t, destroy, void,
 	this->algorithms->destroy(this->algorithms);
 	this->mutex_algs->destroy(this->mutex_algs);
 	DESTROY_IF(this->ipsec);
+	DESTROY_IF(this->fc_sp);
 	DESTROY_IF(this->net);
 	DESTROY_FUNCTION_IF(this->ifaces_filter, (void*)free);
 	this->reqids->destroy(this->reqids);
@@ -1082,6 +1258,8 @@ kernel_interface_t *kernel_interface_create()
 			.get_address_by_ts = _get_address_by_ts,
 			.add_ipsec_interface = _add_ipsec_interface,
 			.remove_ipsec_interface = _remove_ipsec_interface,
+			.add_fc_sp_interface = _add_fc_sp_interface,
+			.remove_fc_sp_interface = _remove_fc_sp_interface,
 			.add_net_interface = _add_net_interface,
 			.remove_net_interface = _remove_net_interface,
 
diff --git a/src/libcharon/kernel/kernel_interface.h b/src/libcharon/kernel/kernel_interface.h
index 21b777ae9..c85d8df9f 100644
--- a/src/libcharon/kernel/kernel_interface.h
+++ b/src/libcharon/kernel/kernel_interface.h
@@ -39,6 +39,28 @@
  * THE SOFTWARE.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 kernel_interface kernel_interface
  * @{ @ingroup kernel
@@ -55,6 +77,7 @@ typedef enum kernel_feature_t kernel_feature_t;
 #include <kernel/kernel_listener.h>
 #include <kernel/kernel_ipsec.h>
 #include <kernel/kernel_net.h>
+#include <kernel/kernel_fc_sp.h>
 
 /**
  * Default range for SPIs requested from kernels
@@ -86,6 +109,11 @@ enum kernel_feature_t {
  */
 typedef kernel_ipsec_t* (*kernel_ipsec_constructor_t)(void);
 
+/**
+ * Constructor function for fc-sp kernel interface
+ */
+typedef kernel_fc_sp_t* (*kernel_fc_sp_constructor_t)(void);
+
 /**
  * Constructor function for network kernel interface
  */
@@ -104,7 +132,7 @@ struct kernel_interface_t {
 	 *
 	 * @return				ORed feature-set of backends
 	 */
-	kernel_feature_t (*get_features)(kernel_interface_t *this);
+	kernel_feature_t (*get_features)(kernel_interface_t *this, int family);
 
 	/**
 	 * Get a SPI from the kernel.
@@ -476,6 +504,26 @@ struct kernel_interface_t {
 	bool (*remove_ipsec_interface)(kernel_interface_t *this,
 								   kernel_ipsec_constructor_t create);
 
+	/**
+	 * Register an fc-sp interface constructor on the manager.
+	 *
+	 * @param create		constructor to register
+	 * @return				TRUE if the fc-sp kernel interface was registered
+	 *						successfully, FALSE if an interface was already
+	 *						registered or the registration failed
+	 */
+        bool (*add_fc_sp_interface) (kernel_interface_t *this, kernel_fc_sp_constructor_t constructor);
+        
+        /**
+	 * Unregister an fc-sp interface constructor.
+	 *
+	 * @param create		constructor to unregister
+	 * @return				TRUE if the ipsec kernel interface was unregistered
+	 *						successfully, FALSE otherwise
+	 */
+	bool (*remove_fc_sp_interface)(kernel_interface_t *this,
+								   kernel_fc_sp_constructor_t create);
+
 	/**
 	 * Register a network kernel interface constructor on the manager.
 	 *
diff --git a/src/libcharon/kernel/kernel_ipsec.h b/src/libcharon/kernel/kernel_ipsec.h
index ae8b82a40..968d8b868 100644
--- a/src/libcharon/kernel/kernel_ipsec.h
+++ b/src/libcharon/kernel/kernel_ipsec.h
@@ -18,6 +18,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 kernel_ipsec kernel_ipsec
  * @{ @ingroup kernel
@@ -192,6 +214,7 @@ struct kernel_ipsec_manage_policy_t {
  * Data required to query a policy in the kernel
  */
 struct kernel_ipsec_query_policy_t {
+    int family;
 };
 
 /**
diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c
index 4543766d6..d1745059c 100644
--- a/src/libcharon/network/sender.c
+++ b/src/libcharon/network/sender.c
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 <unistd.h>
 #include <stdlib.h>
 
@@ -50,6 +72,10 @@ struct private_sender_t {
 	 */
 	mutex_t *mutex;
 
+	mutex_t *wakeup_mutex;
+	
+	int	sender_thread_count;
+
 	/**
 	 * condvar to signal for packets added to list
 	 */
@@ -98,8 +124,8 @@ METHOD(sender_t, send_, void,
 	src = packet->get_source(packet);
 	dst = packet->get_destination(packet);
 
-	DBG1(DBG_NET, "sending packet: from %#H to %#H (%zu bytes)", src, dst,
-		 packet->get_data(packet).len);
+	DBG1(DBG_NET, "sending packet: from %#H to %#H (%zu bytes), src family: %d", src, dst,
+		 packet->get_data(packet).len, src->get_family (src));
 
 	if (this->send_delay)
 	{
@@ -142,6 +168,7 @@ static job_requeue_t send_packets(private_sender_t *this)
 {
 	packet_t *packet;
 	bool oldstate;
+	bool got_wakeup_mutex = false;
 
 	this->mutex->lock(this->mutex);
 	while (this->list->get_count(this->list) == 0)
@@ -151,12 +178,27 @@ static job_requeue_t send_packets(private_sender_t *this)
 		oldstate = thread_cancelability(TRUE);
 
 		this->got->wait(this->got, this->mutex);
+		this->wakeup_mutex->lock (this->wakeup_mutex);
+		got_wakeup_mutex = true;
 
 		thread_cancelability(oldstate);
 		thread_cleanup_pop(FALSE);
+		
+		// If there is a spurious wakeup and we are the second ones to be awoken,
+		// there may be no send to service.  So double check after we get the wakeup lock
+		// that there is still something to be serviced
+		if (this->list->get_count(this->list) == 0)
+		{
+			this->wakeup_mutex->unlock (this->wakeup_mutex);
+			got_wakeup_mutex = false;
+		}
 	}
 	this->list->remove_first(this->list, (void**)&packet);
 	this->sent->signal(this->sent);
+	if (got_wakeup_mutex)
+	{
+		this->wakeup_mutex->unlock (this->wakeup_mutex);
+	}
 	this->mutex->unlock(this->mutex);
 
 	charon->socket->send(charon->socket, packet);
@@ -192,6 +234,7 @@ METHOD(sender_t, destroy, void,
 sender_t * sender_create()
 {
 	private_sender_t *this;
+	int i;
 
 	INIT(this,
 		.public = {
@@ -202,6 +245,9 @@ sender_t * sender_create()
 		},
 		.list = linked_list_create(),
 		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+		.wakeup_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+		.sender_thread_count = lib->settings->get_int(lib->settings,
+									"%s.sender_thread_count", 1, lib->ns),
 		.got = condvar_create(CONDVAR_TYPE_DEFAULT),
 		.sent = condvar_create(CONDVAR_TYPE_DEFAULT),
 		.send_delay = lib->settings->get_int(lib->settings,
@@ -214,9 +260,12 @@ sender_t * sender_create()
 									"%s.send_delay_response", TRUE, lib->ns),
 	);
 
+	for (i = 0; i < this->sender_thread_count; i++)
+	{
 	lib->processor->queue_job(lib->processor,
 		(job_t*)callback_job_create_with_prio((callback_job_cb_t)send_packets,
 			this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
+	}
 
 	return &this->public;
 }
diff --git a/src/libcharon/network/socket.h b/src/libcharon/network/socket.h
index b4062f8a0..cc3b1beca 100644
--- a/src/libcharon/network/socket.h
+++ b/src/libcharon/network/socket.h
@@ -17,6 +17,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 socket socket
  * @{ @ingroup network
@@ -61,6 +83,11 @@ enum socket_family_t {
 	 * Both address families supported
 	 */
 	SOCKET_FAMILY_BOTH = (1 << 2) - 1,
+
+	/**
+	 * FC BSG
+	 */
+	SOCKET_FAMILY_FC = (1 << 2),
 };
 
 /**
diff --git a/src/libcharon/network/socket_manager.c b/src/libcharon/network/socket_manager.c
index 2b2a05702..f495a1455 100644
--- a/src/libcharon/network/socket_manager.c
+++ b/src/libcharon/network/socket_manager.c
@@ -15,12 +15,35 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "socket_manager.h"
 
 #include <daemon.h>
 #include <threading/thread.h>
 #include <threading/rwlock.h>
 #include <collections/linked_list.h>
+#include <collections/hashtable.h>
 
 typedef struct private_socket_manager_t private_socket_manager_t;
 
@@ -35,15 +58,20 @@ struct private_socket_manager_t {
 	socket_manager_t public;
 
 	/**
-	 * List of registered socket constructors
+	 * List of socket constructors used during shutdown.
 	 */
-	linked_list_t *sockets;
+	hashtable_t *socket_constructors;
 
 	/**
-	 * Instantiated socket implementation
+	 * Instantiated socket implementation for IP
 	 */
 	socket_t *socket;
 
+	/**
+	 * Instantiated socket implementation for FC
+	 */
+	socket_t *fc_socket;
+
 	/**
 	 * The constructor used to create the current socket
 	 */
@@ -77,26 +105,51 @@ METHOD(socket_manager_t, sender, status_t,
 	private_socket_manager_t *this, packet_t *packet)
 {
 	status_t status;
+	socket_t *selected_socket = NULL;
+	
 	this->lock->read_lock(this->lock);
-	if (!this->socket)
+	host_t *src = packet->get_source (packet);
+	int family = src->get_family (src);
+	
+	if (family == AF_NETLINK)
 	{
-		DBG1(DBG_NET, "no socket implementation registered, sending failed");
+		selected_socket = this->fc_socket;
+	}
+	else
+	{
+		selected_socket = this->socket;
+	}
+	
+	if (!selected_socket)
+	{
+		DBG1(DBG_NET, "no socket implementation registered for family %d, sending failed", family);
 		this->lock->unlock(this->lock);
 		return NOT_SUPPORTED;
 	}
-	status = this->socket->send(this->socket, packet);
+	status = selected_socket->send(selected_socket, packet);
 	this->lock->unlock(this->lock);
 	return status;
 }
 
 METHOD(socket_manager_t, get_port, uint16_t,
-	private_socket_manager_t *this, bool nat_t)
+	private_socket_manager_t *this, socket_family_t family, bool nat_t)
 {
 	uint16_t port = 0;
+	socket_t *selected_socket;
+	
 	this->lock->read_lock(this->lock);
-	if (this->socket)
+	if (family == SOCKET_FAMILY_FC)
+	{
+		selected_socket = this->fc_socket;
+	}
+	else
 	{
-		port = this->socket->get_port(this->socket, nat_t);
+		selected_socket = this->socket;
+	}
+	
+	if (selected_socket)
+	{
+		port = selected_socket->get_port(selected_socket, nat_t);
 	}
 	this->lock->unlock(this->lock);
 	return port;
@@ -106,40 +159,58 @@ METHOD(socket_manager_t, supported_families, socket_family_t,
 	private_socket_manager_t *this)
 {
 	socket_family_t families = SOCKET_FAMILY_NONE;
-	this->lock->read_lock(this->lock);
-	if (this->socket)
+
+	// Supported families is not needed for fc_socket because there is only one
+	// family for FC, i.e. no IPv4 and IPv6.
+	if (this->socket != NULL)
 	{
+	this->lock->read_lock(this->lock);
 		families = this->socket->supported_families(this->socket);
+	    this->lock->unlock(this->lock);
 	}
-	this->lock->unlock(this->lock);
 	return families;
 }
 
-static void create_socket(private_socket_manager_t *this)
+METHOD(socket_manager_t, add_socket, void,
+	private_socket_manager_t *this, socket_constructor_t create)
 {
-	socket_constructor_t create;
-	/* remove constructors in order to avoid trying to create broken ones
-	 * multiple times */
-	while (this->sockets->remove_first(this->sockets,
-									   (void**)&create) == SUCCESS)
+	socket_t *new_socket;
+	socket_family_t family;
+	
+	this->lock->write_lock(this->lock);
+	new_socket = create();
+	family = new_socket->supported_families (new_socket);
+	
+	if (family == SOCKET_FAMILY_FC)
+	{
+		if (this->fc_socket)
+		{
+			DBG0(DBG_NET, "Attempting to create second FC-SP socket!  Ignoring second socket.");
+			DESTROY_IF (new_socket);
+			new_socket = NULL;
+		}
+		else
+		{
+			this->fc_socket = new_socket;
+		}
+	}
+	else
 	{
-		this->socket = create();
 		if (this->socket)
 		{
-			this->create = create;
-			break;
+			DBG0(DBG_NET, "Attempting to create second IPsec-SP socket!  Ignoring second socket.");
+			DESTROY_IF (new_socket);
+			new_socket = NULL;
+		}
+		else
+		{
+			this->socket = new_socket;
 		}
 	}
-}
 
-METHOD(socket_manager_t, add_socket, void,
-	private_socket_manager_t *this, socket_constructor_t create)
-{
-	this->lock->write_lock(this->lock);
-	this->sockets->insert_last(this->sockets, create);
-	if (!this->socket)
+	if (new_socket)
 	{
-		create_socket(this);
+		this->socket_constructors->put (this->socket_constructors, (void*) create, (void*) family);
 	}
 	this->lock->unlock(this->lock);
 }
@@ -148,14 +219,20 @@ METHOD(socket_manager_t, remove_socket, void,
 	private_socket_manager_t *this, socket_constructor_t create)
 {
 	this->lock->write_lock(this->lock);
-	this->sockets->remove(this->sockets, create, NULL);
-	if (this->create == create)
+	
+	socket_family_t family = (socket_family_t) this->socket_constructors->get (this->socket_constructors, (void*) create);
+	
+	if (family == SOCKET_FAMILY_FC)
+	{
+		this->fc_socket->destroy (this->fc_socket);
+		this->fc_socket = NULL;
+	}
+	else
 	{
-		this->socket->destroy(this->socket);
+		this->socket->destroy (this->socket);
 		this->socket = NULL;
-		this->create = NULL;
-		create_socket(this);
 	}
+	this->socket_constructors->remove (this->socket_constructors, (void*) create);
 	this->lock->unlock(this->lock);
 }
 
@@ -163,7 +240,7 @@ METHOD(socket_manager_t, destroy, void,
 	private_socket_manager_t *this)
 {
 	DESTROY_IF(this->socket);
-	this->sockets->destroy(this->sockets);
+	DESTROY_IF(this->fc_socket);
 	this->lock->destroy(this->lock);
 	free(this);
 }
@@ -185,8 +262,10 @@ socket_manager_t *socket_manager_create()
 			.remove_socket = _remove_socket,
 			.destroy = _destroy,
 		},
-		.sockets = linked_list_create(),
+		.socket_constructors = hashtable_create (hashtable_hash_ptr, hashtable_equals_ptr, 8),
 		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+		.socket = NULL,
+		.fc_socket = NULL,
 	);
 
 	return &this->public;
diff --git a/src/libcharon/network/socket_manager.h b/src/libcharon/network/socket_manager.h
index add3ffa2c..ee6d1235f 100644
--- a/src/libcharon/network/socket_manager.h
+++ b/src/libcharon/network/socket_manager.h
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 socket_manager socket_manager
  * @{ @ingroup network
@@ -58,7 +80,7 @@ struct socket_manager_t {
 	 * @param nat_t			TRUE to get the port used to float in case of NAT-T
 	 * @return				the port, or 0, if no socket is registered
 	 */
-	uint16_t (*get_port)(socket_manager_t *this, bool nat_t);
+	uint16_t (*get_port)(socket_manager_t *this, socket_family_t family, bool nat_t);
 
 	/**
 	 * Get the address families the registered socket is listening on.
diff --git a/src/libcharon/plugins/auth_els/Makefile.am b/src/libcharon/plugins/auth_els/Makefile.am
new file mode 100644
index 000000000..5bb04d3da
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/Makefile.am
@@ -0,0 +1,25 @@
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libhydra \
+	-I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-auth-els.la
+else
+plugin_LTLIBRARIES = libstrongswan-auth-els.la
+endif
+
+libstrongswan_auth_els_la_SOURCES = \
+	auth_els_configs.h auth_els_configs.c \
+	auth_els_kernel_fc_sp.h auth_els_kernel_fc_sp.c \
+	auth_els_ike.h auth_els_ike.c \
+	auth_els_socket.h auth_els_socket.c \
+	auth_els_plugin.h auth_els_plugin.c \
+	auth_els_utils.h
+
+libstrongswan_auth_els_la_LDFLAGS = -module -avoid-version
+
+
diff --git a/src/libcharon/plugins/auth_els/auth_els_configs.c b/src/libcharon/plugins/auth_els/auth_els_configs.c
new file mode 100644
index 000000000..5a0a0e9c6
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_configs.c
@@ -0,0 +1,183 @@
+/* Copyright (C) 2019-2022 Marvell */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <signal.h>
+#include <errno.h>
+
+#ifdef AUTH_ELS_KMIP	// If we are not compiling KMIP, then don't want these
+#include <openssl/bio.h>
+#endif
+
+#include <collections/linked_list.h>
+#include <threading/thread.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+#include <processing/jobs/callback_job.h>
+#include <credentials/keys/shared_key.h>
+#include <utils/identification.h>
+#include <collections/hashtable.h>
+
+#include <config/child_cfg.h>
+
+#include "auth_els_configs.h"
+#include "auth_els_utils.h"
+
+#define DEFAULT_REAUTH_REKEY_JITTER 30 // minimum time between reauth and rekey
+#define CONFIG_LIMIT_OVERRIDE_LIMITS_COOKIE 18652001
+
+enum shared_secret_type_t {
+	SHARED_SECRET_TYPE_WWPN,
+	SHARED_SECRET_TYPE_CONFIG_FILE,
+	SHARED_SECRET_TYPE_KMIP,
+};
+
+struct private_auth_els_configs_t {
+
+	auth_els_configs_t public;
+
+	unsigned int reauth_rekey_jitter;
+	bool override_limits;				// Allows overriding of minimum reauth_time and rekey_time
+	
+	chunk_t shared_secret;
+	enum shared_secret_type_t secret_type;
+	
+	proposal_t *esp_proposal;
+	proposal_t *ike_proposal;
+	bool vmware;
+};
+typedef struct private_auth_els_configs_t private_auth_els_configs_t;
+
+METHOD(auth_els_configs_t, reload_config, bool,
+	private_auth_els_configs_t *this)
+{
+	char *remote, *wwpn, *disabled_remote;
+	int wwpn_len = 0, index = 0, j = 0;
+	int cookie;
+	char *rekey;
+
+	enumerator_t* enumerator = lib->settings->create_section_enumerator(lib->settings,
+									"%s.plugins.auth-els.disabled_remotes", lib->ns);
+
+	while (enumerator->enumerate(enumerator, &remote))
+	{
+		DBG2(DBG_CFG, "disabled remotes: %s", remote);
+		wwpn = lib->settings->get_str(lib->settings,
+							"%s.plugins.auth-els.disabled_remotes.%s.wwpn", NULL,
+							lib->ns, remote);
+		if (wwpn == NULL)
+		{
+			DBG2(DBG_CFG, "disabled remotes NOT found in auth-els.conf");
+			continue;
+		}
+		DBG2(DBG_CFG, "disabled remote port for auth from conf '%s'", wwpn);
+		wwpn_len = strlen(wwpn) + 1;
+		disabled_remote = (char*)malloc(wwpn_len);
+		memset(disabled_remote, 0, wwpn_len);
+		for (index = 0, j = 0; index < strlen(wwpn); index++)
+		{
+			if (wwpn[index] == ':')
+				continue;
+			if (wwpn[index] == '-')
+				continue;
+			if (wwpn[index] == '.')
+				continue;
+			if (wwpn[index] == ' ')
+				continue;
+
+			disabled_remote[j++] = wwpn[index];
+			if (index == (strlen(wwpn) - 1))
+				disabled_remote[j] = '\0';
+		}
+
+
+		if(j > 0)
+		{
+
+		}
+		else
+		{
+			free (disabled_remote);
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	enumerator = lib->settings->create_section_enumerator(lib->settings,
+			"%s.plugins.auth-els.rekey_config", lib->ns);
+
+	while (enumerator->enumerate(enumerator, &rekey))
+	{
+		this->reauth_rekey_jitter = lib->settings->get_int(lib->settings,
+				"%s.plugins.auth-els.rekey_config.%s.reauth_rekey_jitter", DEFAULT_REAUTH_REKEY_JITTER,
+				lib->ns, rekey);
+		
+		cookie = lib->settings->get_int(lib->settings,
+				"%s.plugins.auth-els.rekey_config.%s.override_lower_limits", 0,
+				lib->ns, rekey);
+		
+		if (cookie == CONFIG_LIMIT_OVERRIDE_LIMITS_COOKIE)
+		{
+			this->override_limits = true;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	int sender_thread_count = lib->settings->get_int(lib->settings,
+									"%s.sender_thread_count", 1, lib->ns);
+	
+	this->vmware = lib->settings->get_bool(lib->settings,
+					"%s.plugins.auth-els.vmware", FALSE, lib->ns);
+
+	DBG_STD ("config setting of reauth_rekey_jitter: %d, override_limits: %d, sender_thread_count: %d",
+					this->reauth_rekey_jitter, this->override_limits, sender_thread_count);
+	
+	return TRUE;
+}
+
+METHOD(auth_els_configs_t, get_vmware, bool,
+	private_auth_els_configs_t *this)
+{
+	return this->vmware;
+}
+
+METHOD(auth_els_configs_t, get_reauth_rekey_jitter, unsigned int,
+	private_auth_els_configs_t *this)
+{
+	return this->reauth_rekey_jitter;
+}
+
+METHOD(auth_els_configs_t, get_override_limits, bool,
+	private_auth_els_configs_t *this)
+{
+	return this->override_limits;
+}
+
+METHOD(auth_els_configs_t, destroy, void,
+	private_auth_els_configs_t *this)
+{
+	DBG_ENTER;
+	
+	free(this);
+}
+
+auth_els_configs_t *auth_els_configs_create()
+{
+	private_auth_els_configs_t *this;
+
+	INIT(this,
+		.public = {
+			.destroy = _destroy,
+			.reload_config = _reload_config,
+			.get_reauth_rekey_jitter = _get_reauth_rekey_jitter,
+			.get_override_limits = _get_override_limits,
+			.get_vmware = _get_vmware,
+		},
+		.override_limits = false,
+		.vmware = false,
+	);
+	
+	return &(this->public);
+}
diff --git a/src/libcharon/plugins/auth_els/auth_els_configs.h b/src/libcharon/plugins/auth_els/auth_els_configs.h
new file mode 100644
index 000000000..184651da2
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_configs.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2019-2020 Marvell */
+
+/**
+ * @defgroup auth_els auth_els
+ * @ingroup cplugins
+ *
+ * @defgroup auth_els_configs auth_els_configs
+ * @{ @ingroup auth_els
+ */
+
+#ifndef AUTH_ELS_CONFIGS_H_
+#define AUTH_ELS_CONFIGS_H_
+
+#include <credentials/credential_set.h>
+#include <daemon.h>
+
+// ESP proposal default
+#define ESP_ENCR_PROPOSAL_DEFAULT_128_BIT    "aes128gcm16"
+
+// IKE proposal default
+#define IKE_PROPOSAL_DEFAULT_128_BIT         "aes128gcm16-prfsha256-curve25519"
+
+#define HOST_NAME_SIZE          16
+#define HOST_ID_SIZE            4
+#define REMOTE_PORT_ID_SIZE     4
+#define PEER_NAME_SIZE          33
+
+typedef struct auth_els_configs_t auth_els_configs_t;
+struct auth_els_configs_t {
+
+	bool (*reload_config)(auth_els_configs_t *this);
+    unsigned int (*get_reauth_rekey_jitter)(auth_els_configs_t *this);
+    bool (*get_override_limits)(auth_els_configs_t *this);
+    bool (*get_vmware) (auth_els_configs_t *this);
+        
+	void (*destroy)(auth_els_configs_t *this);
+};
+
+auth_els_configs_t *auth_els_configs_create();
+
+#endif /** AUTH_ELS_CONFIGS_H_ @}*/
diff --git a/src/libcharon/plugins/auth_els/auth_els_ike.c b/src/libcharon/plugins/auth_els/auth_els_ike.c
new file mode 100644
index 000000000..2640469ca
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_ike.c
@@ -0,0 +1,270 @@
+/* Copyright (C) 2019-2020 Marvell */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <scsi/scsi.h>
+#include <scsi/sg.h>
+#include <linux/types.h>
+
+#include <linux/bsg.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_bsg_fc.h>
+
+#include <sa/ikev2/keymat_v2.h>
+#include <sa/ikev1/keymat_v1.h>
+#include <sa/ikev2/tasks/child_create.h>
+#include <encoding/payloads/nonce_payload.h>
+#include <encoding/payloads/cert_payload.h>
+#include <encoding/payloads/auth_payload.h>
+#include <encoding/payloads/id_payload.h>
+#include <encoding/payloads/sa_payload.h>
+#include <encoding/payloads/ts_payload.h>
+#include <encoding/payloads/ke_payload.h>
+#include <encoding/payloads/notify_payload.h>
+#include <threading/rwlock.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+#include <processing/jobs/rekey_ike_sa_job.h>
+#include <processing/jobs/rekey_child_sa_job.h>
+#include <processing/jobs/delete_ike_sa_job.h>
+
+#include "auth_els_ike.h"
+#include "auth_els_socket.h"
+#include "auth_els_utils.h"
+
+/**
+ * Private data of an auth_els_ike_t object.
+ */
+typedef struct private_auth_els_ike_t private_auth_els_ike_t;
+struct private_auth_els_ike_t {
+
+	/**
+	 * Public auth_els_ike_t interface.
+	 */
+	auth_els_ike_t public;
+
+	hashtable_t *fchosts;
+
+};
+
+
+
+METHOD(listener_t, ike_keys, bool,
+	private_auth_els_ike_t *this, ike_sa_t *ike_sa, key_exchange_t *dh,
+	chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey,
+	shared_key_t *shared, auth_method_t method)
+{    
+	DBG_ENTER;
+
+	return TRUE;
+}
+
+METHOD(listener_t, ike_updown, bool,
+	private_auth_els_ike_t *this, ike_sa_t *ike_sa, bool up)
+{
+	DBG_STD ("enter: up=%s", (up? "yes" : "no"));
+
+	return TRUE;
+}
+
+METHOD(listener_t, ike_rekey, bool,
+	private_auth_els_ike_t *this, ike_sa_t *old, ike_sa_t *new)
+{
+	return TRUE;
+}
+
+
+METHOD(listener_t, child_keys, bool,
+		private_auth_els_ike_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+	bool initiator, key_exchange_t *dh, chunk_t nonce_i, chunk_t nonce_r)
+{
+	DBG_STD ("ike_sa: %p, child_sa: %p", ike_sa, child_sa);
+	
+	return TRUE;
+}
+
+METHOD(listener_t, child_state_change, bool,
+		private_auth_els_ike_t *this, ike_sa_t *ike_sa,
+	child_sa_t *child_sa, child_sa_state_t state)
+{
+	
+	DBG_STD ("ike_sa: %p, child_sa: %p, new state: %N", ike_sa, child_sa, child_sa_state_names, state);
+
+	return TRUE;
+}
+
+METHOD(listener_t, child_updown, bool,
+		private_auth_els_ike_t *this, ike_sa_t *ike_sa,
+		child_sa_t *child_sa,  bool up)
+{
+	DBG_ENTER;
+	
+	return TRUE;
+}
+
+METHOD(listener_t, child_rekey, bool,
+		private_auth_els_ike_t *this, ike_sa_t *ike_sa,
+		child_sa_t *old, child_sa_t *new)
+{
+	DBG_STD ("ike_sa: %p, child_sa old: %p, new: %p", ike_sa, old, new);
+
+	return TRUE;
+}
+
+METHOD(listener_t, narrow, bool,
+		private_auth_els_ike_t *this, ike_sa_t *ike_sa,
+		child_sa_t *child_sa, narrow_hook_t type,
+		linked_list_t *local, linked_list_t *remote)
+{
+	DBG_ENTER;
+
+	return TRUE;
+}
+
+METHOD(listener_t, ike_reestablish_pre, bool,
+		private_auth_els_ike_t *this, ike_sa_t *old, ike_sa_t *new)
+{
+	DBG_ENTER;
+	return TRUE;
+}
+
+METHOD(listener_t, ike_reestablish_post, bool,
+		private_auth_els_ike_t *this, ike_sa_t *old, ike_sa_t *new,
+		 bool initiated)
+{
+	DBG_ENTER;
+	return TRUE;
+}
+
+METHOD(listener_t, ike_state_change, bool,
+	private_auth_els_ike_t *this, ike_sa_t *ike_sa, ike_sa_state_t new)
+{
+	DBG_STD ("ike_sa: %p, new_state=%N", ike_sa, ike_sa_state_names, new);
+
+	return TRUE;
+}
+
+METHOD(listener_t, message_hook, bool,
+	private_auth_els_ike_t *this, ike_sa_t *ike_sa, message_t *message,
+	bool incoming, bool plain)
+{
+	DBG_STD ("plain=%s - incoming=%s - request=%s message=%N, message_id initiate: %x, respond: %x",
+			(plain?"true":"false"),
+			(incoming?"true":"false"),
+			(message->get_request(message)?"true":"false"),
+			exchange_type_names, message->get_exchange_type(message), 
+			ike_sa->get_message_id(ike_sa, true), ike_sa->get_message_id(ike_sa, false));
+	
+	return true;
+}
+
+METHOD(listener_t, authorize, bool,
+	private_auth_els_ike_t *this, ike_sa_t *ike_sa,
+	bool final, bool *success)
+{
+	DBG2(DBG_CFG, "auth_els - entering authorize event");
+
+	if (final)
+	{
+		DBG_STD ("final event");
+	}
+
+	*success = TRUE;
+
+	return TRUE; /* stay registered */
+}
+
+
+METHOD(listener_t, alert_hook, bool,
+		private_auth_els_ike_t *this, ike_sa_t *ike_sa, alert_t alert, va_list args)
+{
+	DBG_STD ("enter: alert=%d, ike_sa: %p", alert, ike_sa);
+
+	switch(alert)
+	{
+	case ALERT_SHUTDOWN_SIGNAL:
+		DBG_STD ("AUTH_ELS Plugin shutdown: send app_stop to all hosts now.");
+		break;
+		
+	case ALERT_KEEP_ON_CHILD_SA_FAILURE:
+	case ALERT_RETRANSMIT_SEND_TIMEOUT:
+	case ALERT_HALF_OPEN_TIMEOUT:		
+	case ALERT_PEER_INIT_UNREACHABLE:
+	case ALERT_LOCAL_AUTH_FAILED:
+	case ALERT_PEER_AUTH_FAILED:
+	case ALERT_PEER_ADDR_FAILED:
+	case ALERT_PARSE_ERROR_HEADER:
+	case ALERT_PARSE_ERROR_BODY:
+	case ALERT_PROPOSAL_MISMATCH_IKE:
+	case ALERT_PROPOSAL_MISMATCH_CHILD:
+	case ALERT_TS_MISMATCH:
+	case ALERT_INSTALL_CHILD_SA_FAILED:
+	case ALERT_INSTALL_CHILD_POLICY_FAILED:
+	case ALERT_AUTHORIZATION_FAILED:
+	case ALERT_RETRANSMIT_RECEIVE:
+	
+	case ALERT_INVALID_IKE_SPI:
+	case ALERT_TS_NARROWED:
+	case ALERT_RETRANSMIT_SEND:
+	case ALERT_IKE_SA_EXPIRED:
+	default:
+		break;
+	};
+
+	return TRUE;
+}
+
+METHOD(auth_els_ike_t, destroy, void,
+	private_auth_els_ike_t *this)
+{
+	DBG2(DBG_CFG, "auth_els_ike: destroy");
+
+	free(this);
+}
+
+/**
+ * See header
+ */
+auth_els_ike_t *auth_els_ike_create()
+{
+	DBG2(DBG_CFG, "In auth_els_ike_create");
+
+	private_auth_els_ike_t *this;
+
+	INIT(this,
+		.public = {
+			.listener = {
+				.ike_keys = _ike_keys,
+				.ike_updown = _ike_updown,
+				.ike_rekey = _ike_rekey,
+				.ike_state_change = _ike_state_change,
+				.message = _message_hook,
+				.authorize = _authorize,
+				.alert = _alert_hook,
+				.ike_reestablish_pre = _ike_reestablish_pre,
+				.ike_reestablish_post = _ike_reestablish_post,
+				.child_keys = _child_keys,
+				.child_state_change = _child_state_change,
+				.child_updown = _child_updown,
+				.child_rekey = _child_rekey,
+				.narrow = _narrow,
+			},
+			.destroy = _destroy,
+		},
+	);
+
+	return &(this->public);
+}
diff --git a/src/libcharon/plugins/auth_els/auth_els_ike.h b/src/libcharon/plugins/auth_els/auth_els_ike.h
new file mode 100644
index 000000000..39e53c09e
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_ike.h
@@ -0,0 +1,42 @@
+/* Copyright (C) 2019-2020 Marvell */
+
+/**
+ * @defgroup auth_els_ike auth_els_ike
+ * @{ @ingroup auth_els
+ */
+
+#ifndef AUTH_ELS_IKE_H_
+#define AUTH_ELS_IKE_H_
+
+#include <collections/hashtable.h>
+#include <sa/ike_sa.h>
+#include <daemon.h>
+
+typedef struct auth_els_ike_t auth_els_ike_t;
+/**
+ * Listener to synchronize IKE_SAs.
+ */
+struct auth_els_ike_t {
+
+	/**
+	 * Implements bus listener interface.
+	 */
+	listener_t listener;
+
+	/**
+	 * Destroy a auth_els_ike_t.
+	 */
+	void (*destroy)(auth_els_ike_t *this);
+
+};
+
+/**
+ * Create a auth_els_ike instance.
+ *
+ * @param cache			message cache
+ * @param cache			List of rport sockets
+ * @return				IKE listener
+ */
+auth_els_ike_t *auth_els_ike_create();
+
+#endif /** AUTH_ELS_IKE_ @}*/
diff --git a/src/libcharon/plugins/auth_els/auth_els_kernel_fc_sp.c b/src/libcharon/plugins/auth_els/auth_els_kernel_fc_sp.c
new file mode 100644
index 000000000..3d3544e3f
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_kernel_fc_sp.c
@@ -0,0 +1,235 @@
+/* Copyright (C) 2019-2020 Marvell */
+
+#include "auth_els_kernel_fc_sp.h"
+
+#include <collections/hashtable.h>
+#include <collections/linked_list.h>
+#include <processing/jobs/delete_ike_sa_job.h>
+#include <threading/rwlock.h>
+#include <threading/mutex.h>
+#include <daemon.h>
+
+#include "auth_els_utils.h"
+
+#include <errno.h>
+#include <linux/xfrm.h>
+#include <utils/debug.h>
+#include <utils/chunk.h>
+
+typedef struct private_auth_els_kernel_fc_sp_t private_auth_els_kernel_fc_sp_t;
+
+/**
+ * Private variables and functions of auth_els kernel fc_sp instance.
+ */
+struct private_auth_els_kernel_fc_sp_t {
+
+	/**
+	 * Public auth_els_kernel_fc_sp interface.
+	 */
+	auth_els_kernel_fc_sp_t public;
+
+	/**
+	 * RNG used for SPI generation.
+	 */
+	rng_t *rng;
+	/**
+	 * Lock to access the RNG instance and the callback for getting spi
+	 */
+	rwlock_t *spi_lock;
+};
+
+
+METHOD(kernel_fc_sp_t, get_features, kernel_feature_t,
+	private_auth_els_kernel_fc_sp_t *this)
+{
+	DBG2 (DBG_CFG, "auth_els - auth_els_kernel_fc_sp - get_features callback, ignoring");
+	return KERNEL_POLICY_SPI;
+}
+
+METHOD(kernel_fc_sp_t, get_spi, status_t,
+	private_auth_els_kernel_fc_sp_t *this, host_t *src, host_t *dst,
+	uint8_t protocol, uint32_t *spi)
+{
+	DBG_ENTER;
+	
+	bool result = FALSE;
+
+	this->spi_lock->read_lock(this->spi_lock);
+
+	if (!this->rng)
+	{
+		DBG_FATAL ("unable to create RNG");
+		*spi = 0;
+		this->spi_lock->unlock(this->spi_lock);
+		return FAILED;
+	}
+
+	result = this->rng->get_bytes(this->rng, sizeof(uint32_t),
+								  (uint8_t *)spi);
+	if (!result)
+	{
+		DBG_FATAL ("get_spi failed, set to 0");
+		*spi = 0;
+	}
+	this->spi_lock->unlock(this->spi_lock);
+
+	DBG_STD ("src port_number %d dest port_number %d, spi provided: %x", src->get_port(src), dst->get_port(dst), *spi);
+
+	return result ? SUCCESS : FAILED;
+}
+
+METHOD(kernel_fc_sp_t, get_cpi, status_t,
+	private_auth_els_kernel_fc_sp_t *this, host_t *src, host_t *dst,
+	uint16_t *cpi)
+{
+	DBG_ENTER;
+	(void) this;
+	(void) src;
+	(void) dst;
+	(void) cpi;
+	
+	return NOT_SUPPORTED;
+}
+
+METHOD(kernel_fc_sp_t, add_sa, status_t,
+	private_auth_els_kernel_fc_sp_t *this, kernel_fc_sp_sa_id_t *id,
+	kernel_fc_sp_add_sa_t *data)
+{
+	DBG_ENTER;
+
+	uint32_t key_size;
+	uint16_t remote_port_number;
+	status_t final_status = FAILED;
+
+	key_size = data->enc_key.len - 4;
+
+	if (data->inbound)
+	{
+		remote_port_number = id->src->get_port(id->src);
+	}
+	else
+	{
+		remote_port_number = id->dst->get_port(id->dst);
+	}
+	
+	DBG_STD ("remote_port_number: %d, enc_alg: %N, key_size: %d", 
+				remote_port_number, encryption_algorithm_names, data->enc_alg, key_size);
+	
+	return final_status;
+}
+
+METHOD(kernel_fc_sp_t, query_sa, status_t,
+	private_auth_els_kernel_fc_sp_t *this, kernel_fc_sp_sa_id_t *id,
+	kernel_fc_sp_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
+	time_t *time)
+{
+	DBG_ENTER;
+	
+	int ret_status = SUCCESS;
+	
+	*bytes = 0;
+	*packets = 0;		// Driver only provides bytes for now.
+	
+	return ret_status;
+}
+
+METHOD(kernel_fc_sp_t, del_sa, status_t,
+		private_auth_els_kernel_fc_sp_t *this,
+		kernel_fc_sp_sa_id_t *id,
+		kernel_fc_sp_del_sa_t *data) 
+{
+	status_t final_status = FAILED;
+	
+	DBG_STD ("start: spi: %x", id->spi);
+	
+	return final_status;
+}
+
+METHOD(kernel_fc_sp_t, update_sa, status_t,
+	private_auth_els_kernel_fc_sp_t *this, kernel_fc_sp_sa_id_t *id,
+	kernel_fc_sp_update_sa_t *data)
+{
+	DBG_ENTER;
+	DBG_STD ("child_sa: me: %d, other: %d", 
+				id->src->get_port(id->src), id->dst->get_port(id->dst));
+	
+	return SUCCESS;
+}
+
+METHOD(kernel_fc_sp_t, add_policy, status_t,
+	private_auth_els_kernel_fc_sp_t *this, kernel_fc_sp_policy_id_t *id,
+	kernel_fc_sp_manage_policy_t *data)
+{
+	DBG_ENTER;
+	return SUCCESS;
+}
+
+METHOD(kernel_fc_sp_t, query_policy, status_t,
+	private_auth_els_kernel_fc_sp_t *this, kernel_fc_sp_policy_id_t *id,
+	kernel_fc_sp_query_policy_t *data, time_t *use_time)
+{
+	DBG_ENTER;
+	return NOT_SUPPORTED;
+}
+
+METHOD(kernel_fc_sp_t, del_policy, status_t,
+	private_auth_els_kernel_fc_sp_t *this, kernel_fc_sp_policy_id_t *id,
+	kernel_fc_sp_manage_policy_t *data)
+{
+	DBG_ENTER;
+	return SUCCESS;
+}
+
+METHOD(kernel_fc_sp_t, bypass_socket, bool,
+	private_auth_els_kernel_fc_sp_t *this, int fd, int family)
+{
+	DBG_ENTER;
+	return TRUE;
+}
+
+METHOD(kernel_fc_sp_t, enable_udp_decap, bool,
+	private_auth_els_kernel_fc_sp_t *this, int fd, int family, uint16_t port)
+{
+	DBG_ENTER;
+	return TRUE;
+}
+
+METHOD(kernel_fc_sp_t, destroy, void,
+	private_auth_els_kernel_fc_sp_t *this)
+{
+	DESTROY_IF(this->rng);
+	DESTROY_IF(this->spi_lock);
+	free(this);
+}
+
+/*
+ * Described in header.
+ */
+auth_els_kernel_fc_sp_t *auth_els_kernel_fc_sp_create()
+{
+	private_auth_els_kernel_fc_sp_t *this;
+
+	INIT(this,
+		.public = {
+			.interface = {
+				.get_features = _get_features,
+				.get_spi = _get_spi,
+				.get_cpi = _get_cpi,
+				.add_sa  = _add_sa,
+				.update_sa = _update_sa,
+				.query_sa = _query_sa,
+				.del_sa = _del_sa,
+				.add_policy = _add_policy,
+				.query_policy = _query_policy,
+				.del_policy = _del_policy,
+				.bypass_socket = _bypass_socket,
+				.enable_udp_decap = _enable_udp_decap,
+				.destroy = _destroy,
+			},
+		},
+		.rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
+		.spi_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+	);
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/auth_els/auth_els_kernel_fc_sp.h b/src/libcharon/plugins/auth_els/auth_els_kernel_fc_sp.h
new file mode 100644
index 000000000..3a1ab787e
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_kernel_fc_sp.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 2019-2020 Marvell */
+
+/**
+ * @defgroup auth_els-kernel-ipsec kernel ipsec
+ * @{ @ingroup auth_els
+ */
+
+#ifndef AUTH_ELS_KERNEL_IPSEC_H_
+#define AUTH_ELS_KERNEL_IPSEC_H_
+
+#include <kernel/kernel_fc_sp.h>
+#include <sa/ike_sa.h>
+
+typedef struct auth_els_kernel_fc_sp_t auth_els_kernel_fc_sp_t;
+
+/**
+ * auth_els implementation of the kernel ipsec interface.
+ */
+struct auth_els_kernel_fc_sp_t {
+
+	/**
+	 * Implements kernel_fc_sp_t interface
+	 */
+	kernel_fc_sp_t interface;
+
+};
+
+/**
+ * Create a auth_els kernel ipsec interface instance.
+ *
+ * @return			auth_els_kernel_fc_sp_t instance
+ */
+auth_els_kernel_fc_sp_t *auth_els_kernel_fc_sp_create();
+
+#endif /** AUTH_ELS_KERNEL_IPSEC_H_ @}*/
diff --git a/src/libcharon/plugins/auth_els/auth_els_plugin.c b/src/libcharon/plugins/auth_els/auth_els_plugin.c
new file mode 100644
index 000000000..e59722622
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_plugin.c
@@ -0,0 +1,213 @@
+/* Copyright (C) 2019-2020 Marvell */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <signal.h>
+#include <errno.h>
+#include <linux/netlink.h>
+#include <scsi/scsi_netlink_fc.h>
+#include <scsi/scsi_netlink.h>
+#include <pthread.h>
+
+#include <collections/linked_list.h>
+
+#include <processing/jobs/callback_job.h>
+#include <credentials/credential_set.h>
+#include <credentials/keys/shared_key.h>
+#include <utils/identification.h>
+#include <utils/backtrace.h>
+#include <threading/thread.h>
+#include <daemon.h>
+
+#include "auth_els_utils.h"
+#include "auth_els_plugin.h"
+#include "auth_els_ike.h"
+#include "auth_els_socket.h"
+#include "auth_els_kernel_fc_sp.h"
+#include "auth_els_configs.h"
+
+/**
+ * private data of auth_els plugin
+ */
+struct private_auth_els_plugin_t {
+
+	auth_els_plugin_t public;
+	auth_els_configs_t *configs;
+
+	auth_els_ike_t *ike;
+	
+	int apidev_fd;
+};
+typedef struct private_auth_els_plugin_t private_auth_els_plugin_t;
+
+// This plugin reference is being used for handling of signals because retreiving
+// a context is too complicated.  Use with caution otherwise.
+private_auth_els_plugin_t *plugin_ref;
+
+
+static void handle_system_fault(int sig_type, siginfo_t* si, void* arg)
+{
+	DBG_STD ("thread %u received %d", thread_current_id(), sig_type);
+	
+	backtrace_t *backtrace;
+
+	backtrace = backtrace_create(2);
+	backtrace->log(backtrace, NULL, TRUE);
+	backtrace->log(backtrace, stderr, TRUE);
+	backtrace->destroy(backtrace);
+	
+	DBG_STD ("killing ourself, received critical signal");
+	abort();
+}
+
+static void setup_signal_handlers (private_auth_els_plugin_t *plugin)
+{
+    struct sigaction sa;
+	
+	// fault handler
+    memset (&sa, 0, sizeof (struct sigaction));  // struct
+    sigemptyset(&sa.sa_mask);
+    sa.sa_sigaction = handle_system_fault;
+    sa.sa_flags = SA_SIGINFO;
+    sigaction(SIGSEGV, &sa, NULL);
+    sigaction(SIGFPE, &sa, NULL);
+    sigaction(SIGILL, &sa, NULL);
+
+	sigaction(SIGINT, &sa, NULL);
+	sigaction(SIGQUIT, &sa, NULL);
+	sigaction(SIGABRT, &sa, NULL);
+	sigaction(SIGTERM, &sa, NULL);
+	sigaction(SIGHUP, &sa, NULL);
+	//sigaction(SIGTSTP, &sa, NULL);
+}
+
+/**
+ * Initialize plugin
+ */
+static bool initialize_plugin(private_auth_els_plugin_t *this)
+{
+	if (this->configs)
+	{
+		if (this->configs->reload_config(this->configs) == FALSE)
+		{
+			return FALSE;
+		}
+	}
+
+	this->ike = auth_els_ike_create();
+	
+	setup_signal_handlers (this);
+	
+	if (this->configs->get_vmware (this->configs))
+	{
+		// VMWare does not need a reference because having the VMWare powered on
+		// provides the reference when the fake scsi device is created.
+		DBG_STD ("VMware setup: Skipping reference set for driver.");
+	}
+
+	return TRUE;
+}
+
+/**
+ * Initialize plugin and register listener
+ */
+static bool plugin_cb(private_auth_els_plugin_t *this,
+					  plugin_feature_t *feature, bool reg, void *cb_data)
+{
+	if (reg)
+	{
+		if (!initialize_plugin(this))
+		{
+			return FALSE;
+		}
+		charon->bus->add_listener(charon->bus, &this->ike->listener);
+	}
+
+	return TRUE;
+}
+
+METHOD(plugin_t, get_name, char*,
+	private_auth_els_plugin_t *this)
+{
+	return "auth-els";
+}
+
+METHOD(plugin_t, get_features, int,
+	private_auth_els_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_CALLBACK(kernel_fc_sp_register, auth_els_kernel_fc_sp_create),
+			PLUGIN_PROVIDE(CUSTOM, "kernel-fc-sp"),
+		PLUGIN_CALLBACK(socket_register, auth_els_socket_create),
+			PLUGIN_PROVIDE(CUSTOM, "socket"),
+				PLUGIN_DEPENDS(CUSTOM, "kernel-fc-sp"),
+		PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
+			PLUGIN_PROVIDE(CUSTOM, "auth_els"),
+	};
+	*features = f;
+	
+	return countof(f);
+}
+
+METHOD(plugin_t, reload, bool,
+	private_auth_els_plugin_t *this)
+{
+	if (this->configs->reload_config(this->configs) == FALSE)
+	{
+		return FALSE;
+	}
+    
+	return TRUE;
+}
+
+METHOD(plugin_t, destroy, void,
+	private_auth_els_plugin_t *this)
+{
+	DBG_ENTER;
+	DESTROY_IF(this->ike);
+	
+	DESTROY_IF(this->configs);
+	free(this);
+	
+	DBG_STD ("Plugin destroy complete");
+}
+
+/**
+ * Plugin constructor
+ */
+plugin_t *auth_els_plugin_create()
+{
+	private_auth_els_plugin_t *this;
+
+	if (!lib->caps->keep(lib->caps, CAP_CHOWN))
+	{
+		DBG_FATAL ("creation failed");
+		return NULL;
+	}
+
+	INIT(this,
+		.public = {
+			.plugin = {
+				.get_name = _get_name,
+				.get_features = _get_features,
+				.reload = _reload,
+				.destroy = _destroy,
+			},
+		},
+		.apidev_fd = -1,
+		.configs = auth_els_configs_create(),
+	);
+	
+	char auth_els_plugin_version[AUTH_MAX_STRING_VERSION_LEN + 1];
+
+	sprintf(auth_els_plugin_version, "%d.%02d.%04d%s",
+		AUTH_MAJOR_VERSION, AUTH_MINOR_VERSION, AUTH_BUILD_VERSION, AUTH_STRING_SUFFIX_VERSION);
+	DBG1(DBG_CFG, "auth_els version is %s.", 
+					auth_els_plugin_version);
+	
+	return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/auth_els/auth_els_plugin.h b/src/libcharon/plugins/auth_els/auth_els_plugin.h
new file mode 100644
index 000000000..584607abb
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_plugin.h
@@ -0,0 +1,46 @@
+/* Copyright (C) 2019-2020 Marvell */
+
+/**
+ * @defgroup auth_els auth_els
+ * @ingroup cplugins
+ *
+ * @defgroup auth_els_plugin auth_els_plugin
+ * @{ @ingroup auth_els
+ */
+
+#ifndef AUTH_ELS_PLUGIN_H_
+#define AUTH_ELS_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+#define AUTH_MAJOR_VERSION             1
+#define AUTH_MINOR_VERSION             5
+#define AUTH_BUILD_VERSION             2
+#define AUTH_STRING_SUFFIX_VERSION     "-125-alpha1"
+#define AUTH_MAX_STRING_VERSION_LEN    32
+
+#define APIDEV_DEVICE	"/dev/ql2xapidev"
+#define MEMTRACE_MAX_BACKTRACE_DEPTH   (64)
+#define CHARON_EXECUTABLE   "charon"
+#define SHELL_BUF_SIZE      512
+
+#define HOST_NO_UNASSIGNED      0xffff
+
+#define SWANCTL_LOAD_CERTS      "swanctl -q"
+
+
+/**
+ * Plugin to synchronize state in a high availability cluster.
+ */
+typedef struct auth_els_plugin_t auth_els_plugin_t;
+struct auth_els_plugin_t {
+
+	/**
+	 * implements plugin interface
+	 */
+	plugin_t plugin;
+    
+};
+typedef struct auth_els_plugin_t auth_els_plugin_t;
+
+#endif /** AUTH_ELS_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/auth_els/auth_els_socket.c b/src/libcharon/plugins/auth_els/auth_els_socket.c
new file mode 100644
index 000000000..a87e03aa1
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_socket.c
@@ -0,0 +1,114 @@
+/* Copyright (C) 2019-2020 Marvell */
+
+#include <utils/chunk.h>
+#include <config/child_cfg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <scsi/scsi.h>
+#include <scsi/sg.h>
+#include <linux/types.h>
+
+#include <linux/bsg.h>
+#include <scsi/scsi_bsg_fc.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <unistd.h>
+
+/* "readdir" etc. are defined here. */
+#include <dirent.h>
+/* limits.h defines "PATH_MAX". */
+#include <limits.h>
+
+#include <daemon.h>
+#include <networking/host.h>
+#include <processing/jobs/callback_job.h>
+
+#include <pthread.h>
+
+#include "auth_els_socket.h"
+#include "auth_els_utils.h"
+
+/**
+ * Data to pass to the send_message() callback job
+ */
+typedef struct {
+	chunk_t chunk;
+	int fd;
+} job_data_t;
+
+typedef struct private_auth_els_socket_t private_auth_els_socket_t;
+/**
+ * Private data of an auth_els_socket_t object.
+ */
+struct private_auth_els_socket_t {
+
+	auth_els_socket_t public;
+
+};
+
+METHOD(socket_t, supported_families, socket_family_t,
+	private_auth_els_socket_t *this)
+{
+	return SOCKET_FAMILY_FC;
+}
+
+METHOD(socket_t, destroy, void,
+	private_auth_els_socket_t *this)
+{
+	free(this);
+}
+
+METHOD(socket_t, receiver, status_t,
+		private_auth_els_socket_t *this, packet_t **packet)
+{
+	DBG_ENTER;
+
+	// We don't use the receiver function, so just tell the core to stop trying.
+	// Receives are done when the driver gives us an ELS_RECV AEN.
+	return NOT_SUPPORTED;
+}
+
+METHOD(socket_t, sender, status_t,
+		private_auth_els_socket_t *this, packet_t *packet)
+{
+	DBG_ENTER;
+
+	return NOT_SUPPORTED;
+}
+
+METHOD(socket_t, get_port, uint16_t, 
+	private_auth_els_socket_t *this, bool nat_t)
+{
+	return 77;  // dummy host number
+}
+
+auth_els_socket_t *auth_els_socket_create()
+{
+	private_auth_els_socket_t *this;
+
+	INIT(this,
+		.public = {
+			.socket = {
+				.send = _sender,
+				.receive = _receiver,
+				.supported_families = _supported_families,
+				.get_port = _get_port,
+				.destroy = _destroy,
+			},
+		},
+	);
+	
+	return &this->public;
+}
\ No newline at end of file
diff --git a/src/libcharon/plugins/auth_els/auth_els_socket.h b/src/libcharon/plugins/auth_els/auth_els_socket.h
new file mode 100644
index 000000000..efef65723
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_socket.h
@@ -0,0 +1,29 @@
+/* Copyright (C) 2019-2020 Marvell */
+
+/**
+ * @defgroup auth_els_socket auth_els_socket
+ * @{ @ingroup auth_els
+ */
+
+#ifndef AUTH_ELS_SOCKET_H_
+#define AUTH_ELS_SOCKET_H_
+
+#include <sa/ike_sa.h>
+#include <collections/hashtable.h>
+#include <network/socket.h>
+
+/**
+ * Socket to send/received SA synchronization data
+ */
+typedef struct auth_els_socket_t auth_els_socket_t;
+struct auth_els_socket_t {
+
+	socket_t socket;
+};
+
+/**
+ * Create a default auth_els_socket instance.
+ */
+auth_els_socket_t *auth_els_socket_create();
+
+#endif /** AUTH_ELS_SOCKET_ @}*/
diff --git a/src/libcharon/plugins/auth_els/auth_els_utils.h b/src/libcharon/plugins/auth_els/auth_els_utils.h
new file mode 100644
index 000000000..97aa8ef60
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_utils.h
@@ -0,0 +1,60 @@
+/* Copyright (C) 2019-2020 Marvell */
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/* 
+ * File:   auth_els_utils.h
+ * Author: cwinkler
+ *
+ * Created on February 19, 2020, 8:02 AM
+ */
+
+#ifndef AUTH_ELS_UTILS_H
+#define AUTH_ELS_UTILS_H
+
+#include <pthread.h>
+
+#define DBG_ENTER { \
+    char final_format[1024]; \
+    sprintf (final_format, "%s: %s: %d: enter, thread_id: %lx", __FILE__, __func__, __LINE__, pthread_self()); \
+    DBG1 (DBG_CFG, final_format); \
+}
+
+#define DBG_STD(format, ...) { \
+    char final_format[1024]; \
+    sprintf (final_format, "%s: %s: %d: %s, thread_id: %lx", __FILE__, __func__, __LINE__, format, pthread_self()); \
+    DBG1 (DBG_CFG, final_format, ##__VA_ARGS__); \
+}
+
+#define DBG_FATAL(format, ...) { \
+    char final_format[1024]; \
+    sprintf (final_format, "%s: %s: %d: FATAL_ERROR: %s, thread_id: %lx", __FILE__, __func__, __LINE__, format, pthread_self()); \
+    DBG0 (DBG_CFG, final_format, ##__VA_ARGS__); \
+}
+
+#define DBG_DRIVER(format, ...) { \
+    char final_format[1024]; \
+    sprintf (final_format, "%s: %s: %d: DRIVER ERROR: %s, thread_id: %lx", __FILE__, __func__, __LINE__, format, pthread_self()); \
+    DBG0 (DBG_CFG, final_format, ##__VA_ARGS__); \
+}
+
+#define DBG_HOST(fchost, rport, format, ...) { \
+    char final_format[1024]; \
+    sprintf (final_format, "%s: %s: %d: host_no: %d, pid: %06x: rport_index: %d: %s,  thread_id: %lx", \
+            __FILE__, __func__, __LINE__, fchost->get_host_no(fchost), rport->port_id.b24, rport->rport_index, \
+             format, pthread_self()); \
+    DBG1 (DBG_CFG, final_format, ##__VA_ARGS__); \
+}
+
+#define DBG_HOST1(fchost_dispatcher, rport, format, ...) { \
+    char final_format[1024]; \
+    sprintf (final_format, "%s: %s: %d: host_no: %d, rport_index: %d: %s, thread_id: %lx", \
+            __FILE__, __func__, __LINE__, fchost_dispatcher->host_no, rport->rport_index, format, pthread_self()); \
+    DBG1 (DBG_CFG, final_format, ##__VA_ARGS__); \
+}
+#endif /* AUTH_ELS_UTILS_H */
+
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index d7e83a06b..80f3a23f0 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -14,6 +14,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "ha_tunnel.h"
 #include "ha_plugin.h"
 
@@ -194,7 +216,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
 	ike_cfg_create_t ike = {
 		.version = IKEV2,
 		.local = local,
-		.local_port = charon->socket->get_port(charon->socket, FALSE),
+		.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE),
 		.remote = remote,
 		.remote_port = IKEV2_UDP_PORT,
 		.no_certreq = TRUE,
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
index 97309a6d2..7dcb15676 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
@@ -1126,7 +1126,7 @@ static void process_link(private_kernel_netlink_net_t *this,
 				);
 				this->ifaces->insert_last(this->ifaces, entry);
 			}
-			strncpy(entry->ifname, name, IFNAMSIZ);
+			strncpy(entry->ifname, name, IFNAMSIZ-1);
 			entry->ifname[IFNAMSIZ-1] = '\0';
 			entry->usable = charon->kernel->is_interface_usable(charon->kernel,
 																name);
diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index fe36885c1..7b1c9e517 100644
--- a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -36,6 +36,28 @@
  * THE SOFTWARE.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 <stdint.h>
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -2525,7 +2547,7 @@ static bool install_route(private_kernel_pfkey_ipsec_t *this,
 	/* if we don't route via outbound interface and the remote traffic selector
 	 * covers the IKE peer, add an exclude route */
 	if (!streq(route->if_name, out_interface) &&
-		charon->kernel->get_features(charon->kernel) & KERNEL_REQUIRE_EXCLUDE_ROUTE)
+		charon->kernel->get_features(charon->kernel, AF_INET) & KERNEL_REQUIRE_EXCLUDE_ROUTE)
 	{
 		if (out->dst_ts->is_host(out->dst_ts, dst))
 		{
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
index df533810c..b5c2cb25e 100644
--- a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
@@ -14,6 +14,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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.
+ */
+
 /* Windows 7, for some fwpmu.h functionality */
 #define _WIN32_WINNT 0x0601
 
@@ -816,6 +838,7 @@ static bool install_sps(private_kernel_wfp_ipsec_t *this,
 		switch (sp->src->get_type(sp->src))
 		{
 			case TS_IPV4_ADDR_RANGE:
+			case TS_FC_ADDR_RANGE:
 				has_v4 = TRUE;
 				break;
 			case TS_IPV6_ADDR_RANGE:
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index 58e1cd98a..6fd2fd978 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -14,6 +14,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "load_tester_config.h"
 
 #include <netdb.h>
@@ -748,7 +770,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, u_int num
 	}
 	else
 	{
-		ike.local_port = charon->socket->get_port(charon->socket, FALSE);
+		ike.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE);
 	}
 	ike_cfg = ike_cfg_create(&ike);
 	ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal, 0));
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index f50f79d8b..90e482c99 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -14,6 +14,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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.
+ */
+
 #define _GNU_SOURCE
 #include <string.h>
 
@@ -91,7 +113,7 @@ static peer_cfg_t *build_mediation_config(private_medcli_config_t *this,
 	ike_cfg_create_t ike = {
 		.version = IKEV2,
 		.local = "0.0.0.0",
-		.local_port = charon->socket->get_port(charon->socket, FALSE),
+		.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE),
 		.remote_port = IKEV2_UDP_PORT,
 		.no_certreq = TRUE,
 	};
@@ -405,7 +427,7 @@ medcli_config_t *medcli_config_create(database_t *db)
 	ike_cfg_create_t ike = {
 		.version = IKEV2,
 		.local = "0.0.0.0",
-		.local_port = charon->socket->get_port(charon->socket, FALSE),
+		.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE),
 		.remote = "0.0.0.0",
 		.remote_port = IKEV2_UDP_PORT,
 		.no_certreq = TRUE,
diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c
index 4dd69f2d4..beac903b4 100644
--- a/src/libcharon/plugins/medsrv/medsrv_config.c
+++ b/src/libcharon/plugins/medsrv/medsrv_config.c
@@ -14,6 +14,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 <string.h>
 
 #include "medsrv_config.h"
@@ -134,7 +156,7 @@ medsrv_config_t *medsrv_config_create(database_t *db)
 	ike_cfg_create_t ike = {
 		.version = IKEV2,
 		.local = "0.0.0.0",
-		.local_port = charon->socket->get_port(charon->socket, FALSE),
+		.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE),
 		.remote = "0.0.0.0",
 		.remote_port = IKEV2_UDP_PORT,
 		.no_certreq = TRUE,
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index aef1e1c34..72d18bf1f 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 <string.h>
 
 #include "sql_config.h"
@@ -276,7 +298,7 @@ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e,
 		ike_cfg_create_t ike = {
 			.version = IKEV2,
 			.local = local,
-			.local_port = charon->socket->get_port(charon->socket, FALSE),
+			.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE),
 			.remote = remote,
 			.remote_port = IKEV2_UDP_PORT,
 			.no_certreq = !certreq,
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.c b/src/libcharon/plugins/stroke/stroke_attribute.c
index 0381beba1..6bed5d374 100644
--- a/src/libcharon/plugins/stroke/stroke_attribute.c
+++ b/src/libcharon/plugins/stroke/stroke_attribute.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "stroke_attribute.h"
 
 #include <daemon.h>
@@ -193,6 +215,7 @@ CALLBACK(attr_filter, bool,
 		switch (host->get_family(host))
 		{
 			case AF_INET:
+			case AF_NETLINK:
 				*type = INTERNAL_IP4_DNS;
 				break;
 			case AF_INET6:
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index 55db379ff..b7b11c536 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "stroke_config.h"
 
 #include <daemon.h>
@@ -65,6 +87,8 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
 	private_stroke_config_t *this, identification_t *me, identification_t *other)
 {
 	this->mutex->lock(this->mutex);
+	DBG1 (DBG_CFG, "stroke: %p: create peer_cfg enum: list: %p, list count: %d", 
+					this, this->list, this->list->get_count (this->list));
 	return enumerator_create_cleaner(this->list->create_enumerator(this->list),
 									 (void*)this->mutex->unlock, this->mutex);
 }
@@ -292,7 +316,7 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg
 	}
 	if (ike.local_port == IKEV2_UDP_PORT)
 	{
-		ike.local_port = charon->socket->get_port(charon->socket, FALSE);
+		ike.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE);
 	}
 	ike_cfg = ike_cfg_create(&ike);
 
@@ -1179,7 +1203,7 @@ METHOD(stroke_config_t, add, void,
 	else
 	{
 		/* add config to backend */
-		DBG1(DBG_CFG, "added configuration '%s'", msg->add_conn.name);
+		DBG1(DBG_CFG, "stroke: %p: added configuration '%s', peer_cfg: %p, list: %p", this, msg->add_conn.name, peer_cfg, this->list);
 		this->mutex->lock(this->mutex);
 		this->list->insert_last(this->list, peer_cfg);
 		this->mutex->unlock(this->mutex);
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index 4c9f75cf7..c36d1e1d2 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "stroke_list.h"
 
 #include <inttypes.h>
@@ -657,11 +679,14 @@ METHOD(stroke_list_t, status, void,
 		half_open);
 	enumerator = charon->controller->create_ike_sa_enumerator(
 													charon->controller, wait);
+	int ike_num = 0, child_num = 0;
 	while (enumerator->enumerate(enumerator, &ike_sa) && ferror(out) == 0)
 	{
 		bool ike_printed = FALSE;
 		enumerator_t *children = ike_sa->create_child_sa_enumerator(ike_sa);
 
+		fprintf(out, "ike_sa %d\n--------\n", ike_num);
+
 		if (name == NULL || streq(name, ike_sa->get_name(ike_sa)))
 		{
 			log_ike_sa(out, ike_sa, all);
@@ -669,8 +694,10 @@ METHOD(stroke_list_t, status, void,
 			ike_printed = TRUE;
 		}
 
+		child_num = 0;
 		while (children->enumerate(children, (void**)&child_sa))
 		{
+			fprintf(out, "\nchild_sa %d-%d\n------------\n", ike_num, child_num++);
 			if (name == NULL || streq(name, child_sa->get_name(child_sa)))
 			{
 				if (!ike_printed)
@@ -680,9 +707,12 @@ METHOD(stroke_list_t, status, void,
 					ike_printed = TRUE;
 				}
 				log_child_sa(out, child_sa, all);
+				fprintf(out, "\n\n");
 			}
 		}
 		children->destroy(children);
+		
+		ike_num++;
 	}
 	enumerator->destroy(enumerator);
 
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
index 3a7fc7a63..afbf644bf 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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.
+ */
+
 #define _GNU_SOURCE
 #include <string.h>
 
@@ -130,7 +152,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
 	ike_cfg_create_t ike = {
 		.version = IKEV2,
 		.local = "0.0.0.0",
-		.local_port = charon->socket->get_port(charon->socket, FALSE),
+		.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE),
 		.remote = "0.0.0.0",
 		.remote_port = IKEV2_UDP_PORT,
 		.no_certreq = TRUE,
@@ -255,7 +277,7 @@ METHOD(enumerator_t, ike_enumerator_enumerate, bool,
 	ike_cfg_create_t ike = {
 		.version = IKEV2,
 		.local = "0.0.0.0",
-		.local_port = charon->socket->get_port(charon->socket, FALSE),
+		.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE),
 		.remote = "0.0.0.0",
 		.remote_port = IKEV2_UDP_PORT,
 		.no_certreq = TRUE,
diff --git a/src/libcharon/plugins/vici/vici_attribute.c b/src/libcharon/plugins/vici/vici_attribute.c
index 97fe5d2a4..88c632db3 100644
--- a/src/libcharon/plugins/vici/vici_attribute.c
+++ b/src/libcharon/plugins/vici/vici_attribute.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "vici_attribute.h"
 #include "vici_builder.h"
 
@@ -466,6 +488,7 @@ CALLBACK(pool_li, bool,
 			switch (host->get_family(host))
 			{
 				case AF_INET:
+				case AF_NETLINK:
 					type = keys[index].v4;
 					break;
 				case AF_INET6:
@@ -480,7 +503,7 @@ CALLBACK(pool_li, bool,
 		}
 		else
 		{
-			if (host->get_family(host) == AF_INET)
+			if (host->get_family(host) == AF_INET || host->get_family(host) == AF_NETLINK)
 			{	/* IPv4 attributes contain a subnet mask */
 				uint32_t netmask = 0;
 
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index ab382eca5..f778310bf 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -38,6 +38,28 @@
  * THE SOFTWARE.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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.
+ */
+
 #define _GNU_SOURCE
 
 #include "vici_config.h"
@@ -761,7 +783,7 @@ CALLBACK(parse_ts, bool,
 
 		if (host_create_from_range(buf, &lower, &upper))
 		{
-			type = (lower->get_family(lower) == AF_INET) ?
+			type = (lower->get_family(lower) == AF_INET || lower->get_family(lower) == AF_NETLINK) ?
 								TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
 			ts = traffic_selector_create_from_bytes(proto, type,
 								lower->get_address(lower), from,
@@ -1710,7 +1732,18 @@ CALLBACK(parse_hosts, bool,
 	{
 		return FALSE;
 	}
-	host = host_create_from_string(buf, 0);
+	
+	if (strstr (buf, "-fcsp"))
+	{
+		buf[strlen(buf) - 5] = '\0';
+		host = host_create_from_string_fc(buf, 0);
+		DBG1 (DBG_CFG, "Found FC host: %p", host);
+	}
+	else
+	{
+	   host = host_create_from_string(buf, 0);
+	}
+	
 	if (!host)
 	{
 		return FALSE;
@@ -2527,7 +2560,7 @@ CALLBACK(config_sn, bool,
 	}
 	if (!peer.local_port)
 	{
-		peer.local_port = charon->socket->get_port(charon->socket, FALSE);
+		peer.local_port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE);
 	}
 
 	if (peer.rekey_time == LFT_UNDEFINED && peer.reauth_time == LFT_UNDEFINED)
diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c
index 7b8ff1215..67d929989 100644
--- a/src/libcharon/plugins/vici/vici_control.c
+++ b/src/libcharon/plugins/vici/vici_control.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "vici_control.h"
 #include "vici_builder.h"
 
@@ -479,7 +501,7 @@ static traffic_selector_t *parse_peer_ip(char *ip)
 
 	if (host_create_from_range(ip, &from, &to))
 	{
-		if (to->get_family(to) == AF_INET)
+		if (to->get_family(to) == AF_INET || to->get_family(to) == AF_NETLINK)
 		{
 			type = TS_IPV4_ADDR_RANGE;
 		}
diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c
index 8cc43a099..2f8ac535a 100644
--- a/src/libcharon/processing/jobs/migrate_job.c
+++ b/src/libcharon/processing/jobs/migrate_job.c
@@ -14,6 +14,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "migrate_job.h"
 
 #include <daemon.h>
@@ -104,7 +126,7 @@ METHOD(job_t, execute, job_requeue_t,
 		ike_sa->set_kmaddress(ike_sa, this->local, this->remote);
 
 		host = this->local->clone(this->local);
-		host->set_port(host, charon->socket->get_port(charon->socket, FALSE));
+		host->set_port(host, charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE));
 		ike_sa->set_my_host(ike_sa, host);
 
 		host = this->remote->clone(this->remote);
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 2c77ee2c6..253822326 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -18,6 +18,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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.
+ */
+
 #define _GNU_SOURCE
 #include "child_sa.h"
 
@@ -702,6 +724,7 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
 				.label = label_for(this, LABEL_USE_POLICY),
 			};
 			kernel_ipsec_query_policy_t query = {};
+			query.family = this->my_addr->get_family (this->my_addr);
 
 			if (charon->kernel->query_policy(charon->kernel, &id, &query,
 											 &in) == SUCCESS)
@@ -729,7 +752,8 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
 				.interface = this->config->get_interface(this->config),
 				.label = label_for(this, LABEL_USE_POLICY),
 			};
-			kernel_ipsec_query_policy_t query = {};
+			kernel_ipsec_query_policy_t query;
+			query.family = this->my_addr->get_family (this->my_addr);
 
 			if (charon->kernel->query_policy(charon->kernel, &id, &query,
 											 &out) == SUCCESS)
@@ -811,6 +835,12 @@ METHOD(child_sa_t, get_lifetime, time_t,
 	return hard ? this->expire_time : this->rekey_time;
 }
 
+METHOD(child_sa_t, set_rekey_time, void,
+	   private_child_sa_t *this, time_t rekey_time)
+{
+	this->rekey_time = rekey_time;
+}
+
 METHOD(child_sa_t, get_installtime, time_t,
 	private_child_sa_t *this)
 {
@@ -1025,7 +1055,7 @@ static bool require_policy_update()
 {
 	kernel_feature_t f;
 
-	f = charon->kernel->get_features(charon->kernel);
+	f = charon->kernel->get_features(charon->kernel, AF_INET);
 	return !(f & KERNEL_NO_POLICY_UPDATES);
 }
 
@@ -1412,7 +1442,8 @@ METHOD(child_sa_t, install_policies, status_t,
  */
 static bool install_outbound_immediately(private_child_sa_t *this)
 {
-	if (charon->kernel->get_features(charon->kernel) & KERNEL_POLICY_SPI)
+    int family = this->my_addr->get_family (this->my_addr);
+	if (charon->kernel->get_features(charon->kernel, family) & KERNEL_POLICY_SPI)
 	{
 		if (this->config->get_label_mode(this->config) == SEC_LABEL_MODE_SELINUX)
 		{
@@ -2028,6 +2059,7 @@ child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
 			.get_proposal = _get_proposal,
 			.set_proposal = _set_proposal,
 			.get_lifetime = _get_lifetime,
+			.set_rekey_time = _set_rekey_time,
 			.get_installtime = _get_installtime,
 			.get_usestats = _get_usestats,
 			.get_mark = _get_mark,
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
index 37f00277e..79c7b78f7 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 child_sa child_sa
  * @{ @ingroup sa
@@ -335,6 +357,16 @@ struct child_sa_t {
 	 */
 	time_t (*get_lifetime)(child_sa_t *this, bool hard);
 
+	/**
+	 * Set the absolute time when the CHILD_SA  gets rekeyed.
+         * Note: since the rekeying is actually controlled in the kernel,
+         * this api is here to report what is expected, not to actually affect the rekey action.
+	 *
+	 * @param rekey_time            absolute time when rekey should happen.
+	 * @return			void
+	 */
+	void (*set_rekey_time)(child_sa_t *this, time_t rekey_time);
+
 	/**
 	 * Get the absolute time when this SA has been installed.
 	 *
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 0d554204d..47fb037c4 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -39,6 +39,28 @@
  * THE SOFTWARE.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 <string.h>
 #include <sys/stat.h>
 #include <errno.h>
@@ -1131,10 +1153,10 @@ METHOD(ike_sa_t, float_ports, void,
 		this->other_host->set_port(this->other_host, IKEV2_NATT_PORT);
 	}
 	if (this->my_host->get_port(this->my_host) ==
-			charon->socket->get_port(charon->socket, FALSE))
+			charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE))
 	{
 		this->my_host->set_port(this->my_host,
-								charon->socket->get_port(charon->socket, TRUE));
+								charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, TRUE));
 	}
 }
 
@@ -1447,6 +1469,7 @@ static void resolve_hosts(private_ike_sa_t *this)
 	switch (charon->socket->supported_families(charon->socket))
 	{
 		case SOCKET_FAMILY_IPV4:
+		case SOCKET_FAMILY_FC:
 			family = AF_INET;
 			break;
 		case SOCKET_FAMILY_IPV6:
@@ -1498,7 +1521,7 @@ static void resolve_hosts(private_ike_sa_t *this)
 	if (this->local_host)
 	{
 		host = this->local_host->clone(this->local_host);
-		host->set_port(host, charon->socket->get_port(charon->socket, FALSE));
+		host->set_port(host, charon->socket->get_port(charon->socket, host->get_family (host), FALSE));
 	}
 	else
 	{
@@ -2652,6 +2675,7 @@ static bool is_any_path_valid(private_ike_sa_t *this)
 	switch (charon->socket->supported_families(charon->socket))
 	{
 		case SOCKET_FAMILY_IPV4:
+		case SOCKET_FAMILY_FC:
 			family = AF_INET;
 			break;
 		case SOCKET_FAMILY_IPV6:
@@ -3106,8 +3130,8 @@ METHOD(ike_sa_t, destroy, void,
 /*
  * Described in header.
  */
-ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
-						 ike_version_t version)
+ike_sa_t * ike_sa_create_with_family(ike_sa_id_t *ike_sa_id, bool initiator,
+						 ike_version_t version, int family)
 {
 	private_ike_sa_t *this;
 	static refcount_t unique_id = 0;
@@ -3219,8 +3243,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
 		},
 		.ike_sa_id = ike_sa_id->clone(ike_sa_id),
 		.version = version,
-		.my_host = host_create_any(AF_INET),
-		.other_host = host_create_any(AF_INET),
+		.my_host = host_create_any(family),
+		.other_host = host_create_any(family),
 		.my_id = identification_create_from_encoding(ID_ANY, chunk_empty),
 		.other_id = identification_create_from_encoding(ID_ANY, chunk_empty),
 		.keymat = keymat_create(version, initiator),
@@ -3254,7 +3278,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
 
 	this->task_manager = task_manager_create(&this->public);
 	this->my_host->set_port(this->my_host,
-							charon->socket->get_port(charon->socket, FALSE));
+							charon->socket->get_port(charon->socket, this->my_host->get_family (this->my_host), FALSE));
 
 	if (!this->task_manager || !this->keymat)
 	{
@@ -3265,6 +3289,15 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
 	return &this->public;
 }
 
+/*
+ * Described in header.
+ */
+ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
+						 ike_version_t version)
+{
+	return ike_sa_create_with_family (ike_sa_id, initiator, version, AF_INET);
+}
+
 /**
  * Check if we have a an address pool configured.
  */
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index 58b1f9f3d..ebcd3738a 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -17,6 +17,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 ike_sa ike_sa
  * @{ @ingroup sa
@@ -1256,6 +1278,9 @@ struct ike_sa_t {
 ike_sa_t *ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
 						ike_version_t version);
 
+ike_sa_t * ike_sa_create_with_family(ike_sa_id_t *ike_sa_id, bool initiator,
+						 ike_version_t version, int family);
+
 /**
  * Check if the given IKE_SA can be reauthenticated actively or if config
  * parameters or the authentication method prevent it.
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index e860784de..f7a6f3023 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 <string.h>
 #include <inttypes.h>
 
@@ -1238,8 +1260,8 @@ METHOD(ike_sa_manager_t, checkout, ike_sa_t*,
 	return ike_sa;
 }
 
-METHOD(ike_sa_manager_t, create_new, ike_sa_t*,
-	private_ike_sa_manager_t* this, ike_version_t version, bool initiator)
+METHOD(ike_sa_manager_t, create_new_with_family, ike_sa_t*,
+	private_ike_sa_manager_t* this, ike_version_t version, bool initiator, int family)
 {
 	ike_sa_id_t *ike_sa_id;
 	ike_sa_t *ike_sa;
@@ -1263,7 +1285,7 @@ METHOD(ike_sa_manager_t, create_new, ike_sa_t*,
 	{
 		ike_sa_id = ike_sa_id_create(ike_version, 0, spi, FALSE);
 	}
-	ike_sa = ike_sa_create(ike_sa_id, initiator, version);
+	ike_sa = ike_sa_create_with_family(ike_sa_id, initiator, version, family);
 	ike_sa_id->destroy(ike_sa_id);
 
 	if (ike_sa)
@@ -1274,6 +1296,12 @@ METHOD(ike_sa_manager_t, create_new, ike_sa_t*,
 	return ike_sa;
 }
 
+METHOD(ike_sa_manager_t, create_new, ike_sa_t*,
+	private_ike_sa_manager_t* this, ike_version_t version, bool initiator)
+{
+	return create_new_with_family (this, version, initiator, AF_INET);
+}
+
 METHOD(ike_sa_manager_t, checkout_new, void,
 	private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
 {
@@ -1303,8 +1331,8 @@ static uint32_t get_message_id_or_hash(message_t *message)
 	return message->get_message_id(message);
 }
 
-METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
-	private_ike_sa_manager_t* this, message_t *message)
+METHOD(ike_sa_manager_t, checkout_by_message_with_family, ike_sa_t*,
+	private_ike_sa_manager_t* this, message_t *message, int family)
 {
 	u_int segment;
 	entry_t *entry;
@@ -1376,7 +1404,7 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
 					this->public.get_count(&this->public) < this->ikesa_limit)
 				{
 					id->set_responder_spi(id, our_spi);
-					ike_sa = ike_sa_create(id, FALSE, ike_version);
+					ike_sa = ike_sa_create_with_family(id, FALSE, ike_version, family);
 					if (ike_sa)
 					{
 						entry = entry_create();
@@ -1493,6 +1521,12 @@ typedef struct {
 	bool working;
 } config_entry_t;
 
+METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
+	private_ike_sa_manager_t* this, message_t *message)
+{
+	return checkout_by_message_with_family (this, message, AF_INET);
+}
+
 METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
 	private_ike_sa_manager_t *this, peer_cfg_t *peer_cfg)
 {
@@ -2506,7 +2540,9 @@ ike_sa_manager_t *ike_sa_manager_create()
 			.create_new = _create_new,
 			.checkout_new = _checkout_new,
 			.checkout = _checkout,
+			.create_new_with_family = _create_new_with_family,
 			.checkout_by_message = _checkout_by_message,
+			.checkout_by_message_with_family = _checkout_by_message_with_family,
 			.checkout_by_config = _checkout_by_config,
 			.checkout_by_id = _checkout_by_id,
 			.checkout_by_name = _checkout_by_name,
diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h
index 004cc2216..5361765e7 100644
--- a/src/libcharon/sa/ike_sa_manager.h
+++ b/src/libcharon/sa/ike_sa_manager.h
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 ike_sa_manager ike_sa_manager
  * @{ @ingroup sa
@@ -86,6 +108,18 @@ struct ike_sa_manager_t {
 	 */
 	ike_sa_t* (*checkout) (ike_sa_manager_t* this, ike_sa_id_t *sa_id);
 
+	/**
+	 * Create and check out a new IKE_SA.
+	 *
+	 * @param version			IKE version of this SA
+	 * @param initiator			TRUE for initiator, FALSE otherwise
+         * @param family                        Address family (AF_xx)
+	 * @returns 				created and checked out IKE_SA
+	 */
+        ike_sa_t* (*create_new_with_family) (ike_sa_manager_t* this, ike_version_t version, 
+                                                            bool initiator, int family);
+
+
 	/**
 	 * Track an initial IKE message as responder by increasing the number of
 	 * half-open IKE_SAs.
@@ -122,6 +156,8 @@ struct ike_sa_manager_t {
 	 */
 	ike_sa_t* (*checkout_by_message) (ike_sa_manager_t* this, message_t *message);
 
+	ike_sa_t* (*checkout_by_message_with_family) (ike_sa_manager_t* this, message_t *message, int family);
+
 	/**
 	 * Checkout an IKE_SA for initiation by a peer_config.
 	 *
diff --git a/src/libcharon/sa/ikev1/tasks/informational.c b/src/libcharon/sa/ikev1/tasks/informational.c
index f89770753..b507a3a4a 100644
--- a/src/libcharon/sa/ikev1/tasks/informational.c
+++ b/src/libcharon/sa/ikev1/tasks/informational.c
@@ -14,6 +14,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "informational.h"
 
 #include <daemon.h>
@@ -118,7 +140,7 @@ METHOD(task_t, process_r, status_t,
 						/* Cisco boxes reject the first message from 4500 */
 						me = this->ike_sa->get_my_host(this->ike_sa);
 						me->set_port(me, charon->socket->get_port(
-														charon->socket, FALSE));
+														charon->socket, SOCKET_FAMILY_BOTH, FALSE));
 						this->ike_sa->set_other_host(this->ike_sa, redirect);
 						status = this->ike_sa->reauth(this->ike_sa);
 						enumerator->destroy(enumerator);
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
index 01bfabf95..a00d20281 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
@@ -38,6 +38,28 @@
  * THE SOFTWARE.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "isakmp_natd.h"
 
 #include <string.h>
@@ -104,7 +126,7 @@ static bool force_encap(ike_cfg_t *ike_cfg)
 {
 	if (!ike_cfg->force_encap(ike_cfg))
 	{
-		return charon->kernel->get_features(charon->kernel) &
+		return charon->kernel->get_features(charon->kernel, AF_INET) &
 					KERNEL_REQUIRE_UDP_ENCAPSULATION;
 	}
 	return TRUE;
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index f1228ab07..bf5fdf469 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "task_manager_v2.h"
 
 #include <math.h>
@@ -2365,13 +2387,13 @@ METHOD(task_manager_t, queue_child, void,
 
 	if (args)
 	{
-		task = child_create_create(this->ike_sa, cfg, FALSE, args->src, args->dst);
+		task = child_create_create(this->ike_sa, cfg->get_ref(cfg), FALSE, args->src, args->dst);
 		task->use_reqid(task, args->reqid);
 		task->use_label(task, args->label);
 	}
 	else
 	{
-		task = child_create_create(this->ike_sa, cfg, FALSE, NULL, NULL);
+		task = child_create_create(this->ike_sa, cfg->get_ref(cfg), FALSE, NULL, NULL);
 	}
 	queue_task(this, &task->task);
 }
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index 1c0d7cc77..cdf59911f 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "child_create.h"
 
 #include <daemon.h>
@@ -869,7 +891,10 @@ static bool build_payloads(private_child_create_t *this, message_t *message)
 			break;
 	}
 
-	features = charon->kernel->get_features(charon->kernel);
+	host_t *my_host = this->ike_sa->get_my_host (this->ike_sa);
+	int family = my_host->get_family (my_host);
+
+	features = charon->kernel->get_features(charon->kernel, family);
 	if (!(features & KERNEL_ESP_V3_TFC))
 	{
 		message->add_notify(message, FALSE, ESP_TFC_PADDING_NOT_SUPPORTED,
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
index 5cfc72d78..bc82d3ce3 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "ike_mobike.h"
 
 #include <string.h>
@@ -279,9 +301,9 @@ static void apply_port(host_t *host, host_t *old, uint16_t port, bool local)
 	{
 		port = old->get_port(old);
 	}
-	else if (local && port == charon->socket->get_port(charon->socket, FALSE))
+	else if (local && port == charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, FALSE))
 	{
-		port = charon->socket->get_port(charon->socket, TRUE);
+		port = charon->socket->get_port(charon->socket, SOCKET_FAMILY_BOTH, TRUE);
 	}
 	else if (!local && port == IKEV2_UDP_PORT)
 	{
@@ -327,6 +349,7 @@ METHOD(ike_mobike_t, transmit, bool,
 	switch (charon->socket->supported_families(charon->socket))
 	{
 		case SOCKET_FAMILY_IPV4:
+		case SOCKET_FAMILY_FC:
 			family = AF_INET;
 			break;
 		case SOCKET_FAMILY_IPV6:
diff --git a/src/libcharon/sa/ikev2/tasks/ike_natd.c b/src/libcharon/sa/ikev2/tasks/ike_natd.c
index 72d057e62..8f43a73bc 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_natd.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_natd.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "ike_natd.h"
 
 #include <string.h>
@@ -91,7 +113,7 @@ static bool force_encap(ike_cfg_t *ike_cfg)
 {
 	if (!ike_cfg->force_encap(ike_cfg))
 	{
-		return charon->kernel->get_features(charon->kernel) &
+		return charon->kernel->get_features(charon->kernel, AF_INET) &
 					KERNEL_REQUIRE_UDP_ENCAPSULATION;
 	}
 	return TRUE;
@@ -108,6 +130,18 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this,
 	uint64_t spi_i, spi_r;
 	uint16_t port;
 
+	// For FC, the port is not a valid comparison point because that port
+	// is not used to make the address tuple.  It is only used as a local host identifier.
+	socket_family_t family = charon->socket->supported_families(charon->socket);
+	if (family != SOCKET_FAMILY_FC)
+	{
+		port = htons(host->get_port(host));
+	}
+	else
+	{
+		port = 0;
+	}
+
 	/* prepare all required chunks */
 	spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
 	spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
@@ -115,7 +149,6 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this,
 	spi_i_chunk.len = sizeof(spi_i);
 	spi_r_chunk.ptr = (void*)&spi_r;
 	spi_r_chunk.len = sizeof(spi_r);
-	port = htons(host->get_port(host));
 	port_chunk.ptr = (void*)&port;
 	port_chunk.len = sizeof(port);
 	addr_chunk = host->get_address(host);
diff --git a/src/libstrongswan/networking/host.c b/src/libstrongswan/networking/host.c
index f2768dc10..386bfdde3 100644
--- a/src/libstrongswan/networking/host.c
+++ b/src/libstrongswan/networking/host.c
@@ -17,6 +17,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "host.h"
 
 #include <utils/debug.h>
@@ -85,6 +107,7 @@ METHOD(host_t, is_anyaddr, bool,
 	switch (this->address.sa_family)
 	{
 		case AF_INET:
+		case AF_NETLINK:
 		{
 			return memeq(zeroes, &(this->address4.sin_addr.s_addr), IPV4_LEN);
 		}
@@ -122,19 +145,23 @@ int host_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
 		void *address;
 		uint16_t port;
 		int len;
+		int family;
 
 		address = &this->address6.sin6_addr;
 		port = this->address6.sin6_port;
+		family = this->address.sa_family;
 
 		switch (this->address.sa_family)
 		{
 			case AF_INET:
+			case AF_NETLINK:
 				address = &this->address4.sin_addr;
 				port = this->address4.sin_port;
+				family = AF_INET;		// inet_ntop does not recognize AF_NETLINK
 				/* fall */
 			case AF_INET6:
 
-				if (inet_ntop(this->address.sa_family, address,
+				if (inet_ntop(family, address,
 							  buffer, sizeof(buffer)) == NULL)
 				{
 					snprintf(buffer, sizeof(buffer),
@@ -167,6 +194,7 @@ METHOD(host_t, get_address, chunk_t,
 	switch (this->address.sa_family)
 	{
 		case AF_INET:
+		case AF_NETLINK:
 		{
 			address.ptr = (char*)&(this->address4.sin_addr.s_addr);
 			address.len = IPV4_LEN;
@@ -198,6 +226,7 @@ METHOD(host_t, get_port, uint16_t,
 	switch (this->address.sa_family)
 	{
 		case AF_INET:
+		case AF_NETLINK:
 		{
 			return ntohs(this->address4.sin_port);
 		}
@@ -218,6 +247,7 @@ METHOD(host_t, set_port, void,
 	switch (this->address.sa_family)
 	{
 		case AF_INET:
+		case AF_NETLINK:
 		{
 			this->address4.sin_port = htons(port);
 			break;
@@ -259,6 +289,7 @@ static bool ip_equals(private_host_t *this, private_host_t *other)
 	switch (this->address.sa_family)
 	{
 		case AF_INET:
+		case AF_NETLINK:
 		{
 			return memeq(&this->address4.sin_addr, &other->address4.sin_addr,
 						 sizeof(this->address4.sin_addr));
@@ -287,6 +318,7 @@ static bool equals(private_host_t *this, private_host_t *other)
 	switch (this->address.sa_family)
 	{
 		case AF_INET:
+		case AF_NETLINK:
 		{
 			return (this->address4.sin_port == other->address4.sin_port);
 		}
@@ -395,6 +427,7 @@ host_t *host_create_from_string_and_family(char *string, int family,
 			addr.v6.sin6_family = AF_INET6;
 			return host_create_from_sockaddr((sockaddr_t*)&addr);
 		case AF_INET:
+		case AF_NETLINK:
 			if (strchr(string, ':'))
 			{	/* do not try to convert v6 addresses for v4 family */
 				return NULL;
@@ -406,7 +439,7 @@ host_t *host_create_from_string_and_family(char *string, int family,
 				return NULL;
 			}
 			addr.v4.sin_port = htons(port);
-			addr.v4.sin_family = AF_INET;
+			addr.v4.sin_family = family == AF_NETLINK ? AF_NETLINK : AF_INET;
 			return host_create_from_sockaddr((sockaddr_t*)&addr);
 		default:
 			return NULL;
@@ -421,6 +454,11 @@ host_t *host_create_from_string(char *string, uint16_t port)
 	return host_create_from_string_and_family(string, AF_UNSPEC, port);
 }
 
+host_t *host_create_from_string_fc(char *string, uint16_t port)
+{
+	return host_create_from_string_and_family(string, AF_NETLINK, port);
+}
+
 /*
  * Described in header.
  */
@@ -431,6 +469,7 @@ host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
 	switch (sockaddr->sa_family)
 	{
 		case AF_INET:
+		case AF_NETLINK:
 		{
 			memcpy(&this->address4, (struct sockaddr_in*)sockaddr,
 				   sizeof(struct sockaddr_in));
@@ -482,6 +521,7 @@ host_t *host_create_from_chunk(int family, chunk_t address, uint16_t port)
 	switch (family)
 	{
 		case AF_INET:
+		case AF_NETLINK:
 			if (address.len < IPV4_LEN)
 			{
 				return NULL;
@@ -516,6 +556,7 @@ host_t *host_create_from_chunk(int family, chunk_t address, uint16_t port)
 	switch (family)
 	{
 		case AF_INET:
+		case AF_NETLINK:
 			memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len);
 			this->address4.sin_port = htons(port);
 			this->socklen = sizeof(struct sockaddr_in);
@@ -665,6 +706,7 @@ host_t *host_create_any(int family)
 	switch (family)
 	{
 		case AF_INET:
+		case AF_NETLINK:
 		{
 			this->socklen = sizeof(struct sockaddr_in);
 			update_sa_len(this);
diff --git a/src/libstrongswan/networking/host.h b/src/libstrongswan/networking/host.h
index 6abd93743..a129ddc67 100644
--- a/src/libstrongswan/networking/host.h
+++ b/src/libstrongswan/networking/host.h
@@ -17,6 +17,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 host host
  * @{ @ingroup networking
@@ -140,6 +162,15 @@ struct host_t {
  */
 host_t *host_create_from_string(char *string, uint16_t port);
 
+/**
+ * Constructor to create a host_t object from an address string and set family to AF_NETLINK.
+ *
+ * @param string		string of an address, such as "152.96.193.130"
+ * @param port			port number
+ * @return				host_t, NULL if string not an address.
+ */
+host_t *host_create_from_string_fc(char *string, uint16_t port);
+
 /**
  * Same as host_create_from_string(), but with the option to enforce a family.
  *
diff --git a/src/libstrongswan/selectors/traffic_selector.c b/src/libstrongswan/selectors/traffic_selector.c
index fe61e3768..6dbcc15e2 100644
--- a/src/libstrongswan/selectors/traffic_selector.c
+++ b/src/libstrongswan/selectors/traffic_selector.c
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 <string.h>
 #include <stdio.h>
 
@@ -28,14 +50,15 @@
 
 #define IPV4_LEN	4
 #define IPV6_LEN	16
-#define TS_IP_LEN(this) ({ ((this)->type == TS_IPV4_ADDR_RANGE) ? IPV4_LEN : IPV6_LEN; })
+#define PORTID_LEN  3
+#define TS_IP_LEN(this) ({ (((this)->type == TS_IPV4_ADDR_RANGE) ? IPV4_LEN : (((this)->type == TS_FC_ADDR_RANGE) ? PORTID_LEN: IPV6_LEN) ); })
 
 #define NON_SUBNET_ADDRESS_RANGE	255
 
-ENUM_BEGIN(ts_type_name, TS_IPV4_ADDR_RANGE, TS_IPV6_ADDR_RANGE,
+ENUM_BEGIN(ts_type_name, TS_IPV4_ADDR_RANGE, TS_SECLABEL,
 	"TS_IPV4_ADDR_RANGE",
-	"TS_IPV6_ADDR_RANGE");
-ENUM_NEXT(ts_type_name, TS_SECLABEL, TS_SECLABEL, TS_IPV6_ADDR_RANGE,
+	"TS_IPV6_ADDR_RANGE",
+	"TS_FC_ADDR_RANGE",
 	"TS_SECLABEL");
 ENUM_END(ts_type_name, TS_SECLABEL);
 
@@ -241,7 +264,7 @@ int traffic_selector_printf_hook(printf_hook_data_t *data,
 	len = TS_IP_LEN(this);
 	memset(from, 0, len);
 	memset(to, 0xFF, len);
-	if (this->dynamic &&
+	if (this->dynamic && (this->type != TS_FC_ADDR_RANGE) &&
 		memeq(this->from, from, len) &&	memeq(this->to, to, len))
 	{
 		written += print_in_hook(data, "dynamic");
@@ -252,6 +275,11 @@ int traffic_selector_printf_hook(printf_hook_data_t *data,
 		{
 			inet_ntop(AF_INET, &this->from, from_str, sizeof(from_str));
 		}
+		else if (this->type == TS_FC_ADDR_RANGE)
+		{
+			written += print_in_hook(data, "%x%x%x..%x%x%x", this->from[0], this->from[1], this->from[2],
+					this->to[0], this->to[1], this->to[2]);
+		}
 		else
 		{
 			inet_ntop(AF_INET6, &this->from, from_str, sizeof(from_str));
@@ -319,6 +347,12 @@ int traffic_selector_printf_hook(printf_hook_data_t *data,
 			{
 				written += print_icmp(data, this->from_port);
 			}
+			else if (this->type == TS_FC_ADDR_RANGE)
+			{
+				written += print_in_hook(data, "%d-%d",
+										 this->from_port, this->to_port);
+
+			}
 			else
 			{
 				serv = getservbyport(htons(this->from_port), serv_proto);
@@ -486,7 +520,8 @@ METHOD(traffic_selector_t, is_host, bool,
 		int family = host->get_family(host);
 
 		if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
-			(family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
+			(family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE) ||
+			(family == AF_NETLINK && this->type == TS_IPV6_ADDR_RANGE))
 		{
 			addr = host->get_address(host);
 			if (memeq(addr.ptr, this->from, addr.len) &&
@@ -522,8 +557,11 @@ METHOD(traffic_selector_t, is_dynamic, bool,
 METHOD(traffic_selector_t, set_address, void,
 	private_traffic_selector_t *this, host_t *host)
 {
-	this->type = host->get_family(host) == AF_INET ? TS_IPV4_ADDR_RANGE
+	if (this->type != TS_FC_ADDR_RANGE)
+	{
+	   this->type = host->get_family(host) == AF_INET ? TS_IPV4_ADDR_RANGE
 												   : TS_IPV6_ADDR_RANGE;
+    }
 
 	if (host->is_anyaddr(host))
 	{
@@ -536,8 +574,11 @@ METHOD(traffic_selector_t, set_address, void,
 		chunk_t from = host->get_address(host);
 		memcpy(this->from, from.ptr, from.len);
 		memcpy(this->to, from.ptr, from.len);
+		if (this->type != TS_FC_ADDR_RANGE)
+		{
 		this->netbits = from.len * 8;
 	}
+	}
 	this->dynamic = FALSE;
 }
 
@@ -547,6 +588,15 @@ METHOD(traffic_selector_t, is_contained_in, bool,
 	private_traffic_selector_t *subset;
 	bool contained_in = FALSE;
 
+	if (this->type == TS_FC_ADDR_RANGE)
+	{
+		if (equals(this, other))
+		{
+			contained_in = TRUE;
+		}
+		return contained_in;
+	}
+
 	subset = (private_traffic_selector_t*)get_subset(this, other);
 
 	if (subset)
@@ -565,6 +615,7 @@ METHOD(traffic_selector_t, includes, bool,
 {
 	chunk_t addr;
 	int family = host->get_family(host);
+	uint16_t port_index = 0;
 
 	if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
 		(family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
@@ -575,6 +626,13 @@ METHOD(traffic_selector_t, includes, bool,
 				memcmp(this->to, addr.ptr, addr.len) >= 0;
 	}
 
+	if (this->type == TS_FC_ADDR_RANGE)
+	{
+		port_index = host->get_port(host);
+
+		return ((this->from_port == port_index) || (this->to_port == port_index));
+	}
+
 	return FALSE;
 }
 
@@ -889,7 +947,7 @@ static private_traffic_selector_t *traffic_selector_create(uint8_t protocol,
 	private_traffic_selector_t *this;
 
 	/* sanity check */
-	if (type != TS_IPV4_ADDR_RANGE && type != TS_IPV6_ADDR_RANGE)
+	if (type != TS_IPV4_ADDR_RANGE && type != TS_IPV6_ADDR_RANGE && type != TS_FC_ADDR_RANGE)
 	{
 		return NULL;
 	}
@@ -926,3 +984,19 @@ static private_traffic_selector_t *traffic_selector_create(uint8_t protocol,
 	}
 	return this;
 }
+
+traffic_selector_t *traffic_selector_create_from_fcsp2_format(chunk_t start_address, uint16_t start_port,
+												chunk_t end_address, uint16_t end_port)
+{
+	ts_type_t type = TS_FC_ADDR_RANGE;
+	private_traffic_selector_t *this = traffic_selector_create(IPPROTO_RAW, type,
+			start_port, end_port);
+
+	memset(this->from, 0x0, start_address.len);
+	memcpy(this->from, start_address.ptr, start_address.len);
+
+	memset(this->to, 0x0, end_address.len);
+	memcpy(this->to, end_address.ptr, end_address.len);
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/selectors/traffic_selector.h b/src/libstrongswan/selectors/traffic_selector.h
index 367b4fff9..2197246e7 100644
--- a/src/libstrongswan/selectors/traffic_selector.h
+++ b/src/libstrongswan/selectors/traffic_selector.h
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 traffic_selector traffic_selector
  * @{ @ingroup selectors
@@ -53,6 +75,15 @@ enum ts_type_t {
 	 */
 	TS_IPV6_ADDR_RANGE = 8,
 
+	/**
+	 * A range of FC addresses, represented by two three (3)
+	 * octet values.  The first value is the beginning FC address
+	 * (inclusive) and the second value is the ending FC address
+	 * (inclusive). All addresses falling between the two specified
+	 *  addresses are considered to be within the list.
+	 */
+	TS_FC_ADDR_RANGE = 9,
+
 	/**
 	 * A security label.
 	 */
@@ -422,4 +453,22 @@ traffic_selector_t *traffic_selector_create_dynamic(uint8_t protocol,
 int traffic_selector_printf_hook(printf_hook_data_t *data,
 							printf_hook_spec_t *spec, const void *const *args);
 
+/**
+ * Create a new traffic selector using data read from the net.
+ *
+ * There exists a mix of network and host order in the params.
+ * But the parser gives us this data in fcsp format, so we
+ * don't have to convert twice.
+ *
+ * @param start_address	start of address range, network order
+ * @param start_type	starting type of following addresses
+ * @param end_address	end of address range, network order
+ * @param end_rctl		Ending R_CTL
+ * @param start_rctl	Starting R_CTL
+ * @param end_type		ending type of following address
+ * @return				traffic_selector_t object
+ */
+traffic_selector_t *traffic_selector_create_from_fcsp2_format(chunk_t start_address, uint16_t start_port,
+												chunk_t end_address, uint16_t end_port);
+
 #endif /** TRAFFIC_SELECTOR_H_ @}*/
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index 6ddaf6c3e..3f9c27d93 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -17,6 +17,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 <string.h>
 #include <stdio.h>
 #include <errno.h>
@@ -37,7 +59,7 @@ ENUM_NEXT(id_match_names, ID_MATCH_PERFECT, ID_MATCH_PERFECT, ID_MATCH_MAX_WILDC
 	"MATCH_PERFECT");
 ENUM_END(id_match_names, ID_MATCH_PERFECT);
 
-ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID,
+ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_Q_NAME,
 	"ID_ANY",
 	"ID_IPV4_ADDR",
 	"ID_FQDN",
@@ -49,8 +71,9 @@ ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID,
 	"ID_IPV6_ADDR_RANGE",
 	"ID_DER_ASN1_DN",
 	"ID_DER_ASN1_GN",
-	"ID_KEY_ID");
-ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_DER_ASN1_GN_URI, ID_KEY_ID,
+	"ID_KEY_ID",
+	"ID_KEY_Q_NAME");
+ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_DER_ASN1_GN_URI, ID_KEY_Q_NAME,
 	"ID_DER_ASN1_GN_URI");
 ENUM_END(id_type_names, ID_DER_ASN1_GN_URI);
 
@@ -1306,6 +1329,10 @@ int identification_printf_hook(printf_hook_data_t *data,
 		case ID_DER_ASN1_GN:
 			snprintf(buf, BUF_LEN, "(ASN.1 general name)");
 			break;
+		case ID_KEY_Q_NAME:
+			snprintf(buf, sizeof(buf), "%.*s", (int)this->encoded.len,
+					this->encoded.ptr);
+			break;
 		case ID_KEY_ID:
 			if (chunk_printable(this->encoded, NULL, '?') &&
 				this->encoded.len != HASH_SIZE_SHA1)
@@ -1378,6 +1405,7 @@ static private_identification_t *identification_create(id_type_t type)
 			break;
 		case ID_FQDN:
 		case ID_RFC822_ADDR:
+		case ID_KEY_Q_NAME:
 			this->public.hash = _hash_binary;
 			this->public.equals = _equals_strcasecmp;
 			this->public.matches = _matches_string;
@@ -1441,6 +1469,7 @@ static private_identification_t* create_from_string_with_prefix_type(char *str)
 		{ "asn1gn:",		ID_DER_ASN1_GN			},
 		{ "xmppaddr:",		ID_DER_ASN1_GN          },
 		{ "keyid:",			ID_KEY_ID				},
+		{ "0x",				ID_KEY_Q_NAME			},
 	};
 	private_identification_t *this;
 	int i;
diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h
index a85b7c538..ffdc08416 100644
--- a/src/libstrongswan/utils/identification.h
+++ b/src/libstrongswan/utils/identification.h
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 identification identification
  * @{ @ingroup utils
@@ -126,6 +148,12 @@ enum id_type_t {
 	 */
 	ID_KEY_ID = 11,
 
+	/**
+	 * ID data is a qualifier name string.
+	 * The string MUST NOT contain any terminators.
+	 */
+	ID_KEY_Q_NAME = 12,
+
 	/**
 	 * Private ID type which represents a GeneralName of type URI
 	 */
diff --git a/src/libstrongswan/utils/parser_helper.c b/src/libstrongswan/utils/parser_helper.c
index 69800a781..f77a4fb56 100644
--- a/src/libstrongswan/utils/parser_helper.c
+++ b/src/libstrongswan/utils/parser_helper.c
@@ -14,6 +14,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 <limits.h>
 #include <ctype.h>
 #include <stdarg.h>
@@ -24,6 +46,9 @@
 
 #include <collections/array.h>
 
+#include <stdlib.h>
+#include <unistd.h>
+
 typedef struct private_parser_helper_t private_parser_helper_t;
 typedef struct parser_helper_file_t parser_helper_file_t;
 
@@ -92,6 +117,42 @@ static parser_helper_file_t *current_file(private_parser_helper_t *this)
 	return NULL;
 }
 
+#ifdef _WIN32
+static bool get_install_dir(char *install_dir)
+{
+	char path[PATH_MAX], *pos;
+	HMODULE module;
+
+	module = GetModuleHandle(NULL);
+	if (!module)
+	{
+		return FALSE;
+	}
+	if (!GetModuleFileName(module, path, sizeof(path)))
+	{
+		return FALSE;
+	}
+	pos = strrchr(path, '\\');
+	if (!pos)
+	{
+		return FALSE;
+	}
+	*pos = 0;
+
+	pos = strstr(path, "\\usr\\");
+	if (!pos)
+	{
+		return FALSE;
+	}
+	*pos = 0;
+
+	memset(install_dir, 0, sizeof(install_dir));
+	strcpy(install_dir, path);
+
+	return TRUE;
+}
+#endif
+
 METHOD(parser_helper_t, file_next, FILE*,
 	private_parser_helper_t *this)
 {
@@ -111,18 +172,48 @@ METHOD(parser_helper_t, file_next, FILE*,
 	{
 		while (file->matches->enumerate(file->matches, &name, NULL))
 		{
+			char fname[PATH_MAX] = { 0 };
+			memcpy(fname, name, strlen(name));
+
+#ifdef _WIN32
+			int len = 0;
+			if (get_install_dir(fname))
+			{
+				len = strlen(fname);
+				if(strstr(name, "/etc/strongswan.conf") != NULL)
+				{
+					strcpy((&fname[len]), name);
+				}
+				else
+				{
+					memset(fname, 0, PATH_MAX);
+					memcpy(fname, name, strlen(name));
+				}
+			}
+			else
+			{
+				memset(fname, 0, PATH_MAX);
+				memcpy(fname, name, strlen(name));
+			}
+			for (int i = 0; i < strlen(fname); i++)
+			{
+				if(fname[i] == '/')
+				{
+					fname[i] = '\\';
+				}
+			}
+#endif
 			INIT(next,
-				.name = strdup(name),
-				.file = fopen(name, "r"),
+				.name = strdup(fname),
+				.file = fopen(fname, "r"),
 			);
-
 			if (next->file && fstat(fileno(next->file), &st) == 0 &&
 				S_ISREG(st.st_mode))
 			{
 				array_insert(this->files, ARRAY_TAIL, next);
 				return next->file;
 			}
-			PARSER_DBG2(&this->public, "unable to open '%s'", name);
+			PARSER_DBG2(&this->public, "unable to open '%s'", fname);
 			parser_helper_file_destroy(next);
 		}
 		file->matches->destroy(file->matches);
@@ -168,6 +259,21 @@ METHOD(parser_helper_t, file_include, void,
 		free(dir);
 	}
 
+#ifdef _WIN32
+	if(strstr(pat, "/etc/strongswan.conf") != NULL)
+	{
+		char fname[PATH_MAX] = { 0 };
+		int len = 0;
+		memcpy(fname, pat, strlen(pat));
+		if (get_install_dir(fname))
+		{
+			len = strlen(fname);
+			strcpy((&fname[len]), pat);
+			memset(pat, 0, sizeof(pat));
+			memcpy(pat, fname, strlen(fname));
+		}		
+	}
+#endif
 	file->matches = enumerator_create_glob(pat);
 	if (!file->matches)
 	{	/* if glob(3) is not available, try to load pattern directly */
diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h
index c7ccd3afa..1b9d18570 100644
--- a/src/libstrongswan/utils/utils.h
+++ b/src/libstrongswan/utils/utils.h
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 utils_i utils
  * @{ @ingroup utils
@@ -38,6 +60,8 @@
 
 #ifdef WIN32
 # include "compat/windows.h"
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
 #else
 # include <arpa/inet.h>
 # include <sys/socket.h>
@@ -48,6 +72,11 @@
 # include <signal.h>
 #endif
 
+#ifdef WIN32
+#define AF_NETLINK	16
+#define PF_NETLINK	AF_NETLINK
+#endif
+
 #include "utils/types.h"
 #include "enum.h"
 #include "utils/atomics.h"
diff --git a/src/swanctl/swanctl.c b/src/swanctl/swanctl.c
index a3bbc28fd..d43336921 100644
--- a/src/swanctl/swanctl.c
+++ b/src/swanctl/swanctl.c
@@ -15,9 +15,32 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2019-2022 Marvell 
+ *
+ * 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 "swanctl.h"
 #include "command.h"
 
+#include <stdlib.h>
 #include <unistd.h>
 
 #include <library.h>
@@ -28,6 +51,43 @@
  */
 char *swanctl_dir;
 
+#ifdef _WIN32
+static bool get_install_dir(char *install_dir)
+{
+	char path[PATH_MAX], *pos;
+	HMODULE module;
+
+	module = GetModuleHandle(NULL);
+	if (!module)
+	{
+		return FALSE;
+	}
+	if (!GetModuleFileName(module, path, sizeof(path)))
+	{
+		return FALSE;
+	}
+
+	pos = strrchr(path, '\\');
+	if (!pos)
+	{
+		return FALSE;
+	}
+	*pos = 0;
+
+	pos = strstr(path, "\\usr\\");
+	if (!pos)
+	{
+		return FALSE;
+	}
+	*pos = 0;
+
+	memset(install_dir, 0, sizeof(install_dir));
+	strcpy(install_dir, path);
+
+	return TRUE;
+}
+#endif
+
 /*
  * Described in header
  */
@@ -35,6 +95,7 @@ settings_t *load_swanctl_conf(char *file)
 {
 	settings_t *cfg;
 	char buf[PATH_MAX];
+	char fname[PATH_MAX] = { 0 };
 
 	if (!file)
 	{
@@ -48,6 +109,39 @@ settings_t *load_swanctl_conf(char *file)
 				 DIRECTORY_SEPARATOR, SWANCTL_CONF);
 	}
 
+	memcpy(fname, file, strlen(file));
+#ifdef _WIN32
+	int len = 0;
+	if (get_install_dir(fname))
+	{
+		len = strlen(fname);
+		if(strstr(file, "/etc/swanctl\\swanctl.conf") != NULL)
+		{
+			strcpy((&fname[len]), file);
+		}
+		else
+		{
+			memset(fname, 0, PATH_MAX);
+			memcpy(fname, file, strlen(file));
+		}
+	}
+	else
+	{
+		memset(fname, 0, PATH_MAX);
+		memcpy(fname, file, strlen(file));
+	}
+	for (int i = 0; i < strlen(fname); i++)
+	{
+		if(fname[i] == '/')
+		{
+			fname[i] = '\\';
+		}
+	}
+	memset(file, 0, PATH_MAX);
+	memcpy(file, fname, strlen(fname));
+#endif
+	//DBG1(DBG_CFG, "STAGING swanctl - load_swanctl_conf - file=%s", file);
+
 	cfg = settings_create(file);
 	if (!cfg)
 	{
-- 
2.31.1.windows.1

