File strongswan-marvell-auth-els.patch of Package strongswan.22506
From 31541a25dfc199439450fb03381fbb4b687386b7 Mon Sep 17 00:00:00 2001
From: Bhushan Narkhede <bnarkhede@marvell.com>
Date: Fri, 20 Aug 2021 02:53:56 -0700
Subject: [PATCH] strongswan marvell auth els
---
conf/Makefile.am | 1 +
conf/options/charon.opt | 3 +
conf/plugins/auth-els.opt | 26 +
configure.ac | 8 +
src/charon-cmd/cmd/cmd_connection.c | 3 +-
src/charon-nm/nm/nm_service.c | 3 +-
src/charon/Makefile.am | 4 +
src/libcharon/Makefile.am | 8 +
src/libcharon/config/ike_cfg.c | 2 +-
src/libcharon/encoding/parser.c | 10 +
.../payloads/traffic_selector_substructure.c | 139 +++-
src/libcharon/kernel/kernel_fc_sp.c | 40 ++
src/libcharon/kernel/kernel_fc_sp.h | 341 ++++++++++
src/libcharon/kernel/kernel_interface.c | 169 ++++-
src/libcharon/kernel/kernel_interface.h | 30 +-
src/libcharon/kernel/kernel_ipsec.h | 2 +
src/libcharon/network/sender.c | 35 +-
src/libcharon/network/socket.h | 6 +
src/libcharon/network/socket_manager.c | 135 ++--
src/libcharon/network/socket_manager.h | 3 +-
src/libcharon/plugins/auth_els/Makefile.am | 25 +
.../plugins/auth_els/auth_els_configs.c | 595 ++++++++++++++++++
.../plugins/auth_els/auth_els_configs.h | 44 ++
src/libcharon/plugins/auth_els/auth_els_ike.c | 265 ++++++++
src/libcharon/plugins/auth_els/auth_els_ike.h | 42 ++
.../plugins/auth_els/auth_els_kernel_fc_sp.c | 252 ++++++++
.../plugins/auth_els/auth_els_kernel_fc_sp.h | 35 ++
.../plugins/auth_els/auth_els_plugin.c | 208 ++++++
.../plugins/auth_els/auth_els_plugin.h | 43 ++
.../plugins/auth_els/auth_els_socket.c | 115 ++++
.../plugins/auth_els/auth_els_socket.h | 29 +
.../plugins/auth_els/auth_els_utils.h | 40 ++
src/libcharon/plugins/ha/ha_tunnel.c | 2 +-
.../plugins/load_tester/load_tester_config.c | 3 +-
src/libcharon/plugins/medcli/medcli_config.c | 5 +-
src/libcharon/plugins/medsrv/medsrv_config.c | 3 +-
src/libcharon/plugins/sql/sql_config.c | 3 +-
.../plugins/stroke/stroke_attribute.c | 2 +
src/libcharon/plugins/stroke/stroke_config.c | 3 +-
src/libcharon/plugins/stroke/stroke_list.c | 10 +
src/libcharon/plugins/uci/uci_config.c | 5 +-
src/libcharon/plugins/vici/vici_attribute.c | 4 +-
src/libcharon/plugins/vici/vici_config.c | 5 +-
src/libcharon/plugins/vici/vici_control.c | 3 +-
src/libcharon/processing/jobs/migrate_job.c | 2 +-
src/libcharon/sa/child_sa.c | 20 +-
src/libcharon/sa/child_sa.h | 11 +
src/libcharon/sa/ike_sa.c | 33 +-
src/libcharon/sa/ike_sa.h | 4 +
src/libcharon/sa/ike_sa_manager.c | 27 +-
src/libcharon/sa/ike_sa_manager.h | 15 +-
src/libcharon/sa/ikev1/tasks/informational.c | 3 +-
src/libcharon/sa/ikev1/tasks/isakmp_natd.c | 3 +-
src/libcharon/sa/ikev2/task_manager_v2.c | 3 +-
src/libcharon/sa/ikev2/tasks/child_create.c | 8 +-
src/libcharon/sa/ikev2/tasks/ike_mobike.c | 6 +-
src/libcharon/sa/ikev2/tasks/ike_natd.c | 19 +-
src/libstrongswan/networking/host.c | 19 +-
src/libstrongswan/plugins/plugin_loader.c | 2 +-
.../selectors/traffic_selector.c | 215 ++++++-
.../selectors/traffic_selector.h | 80 ++-
src/libstrongswan/utils/identification.c | 14 +-
src/libstrongswan/utils/identification.h | 7 +
63 files changed, 3069 insertions(+), 131 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 1c2b41236..ce3129df0 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/bypass-lan.opt \
plugins/certexpire.opt \
diff --git a/conf/options/charon.opt b/conf/options/charon.opt
index cc58afda8..3f4ff1395 100644
--- a/conf/options/charon.opt
+++ b/conf/options/charon.opt
@@ -380,6 +380,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..8e1d796f6
--- /dev/null
+++ b/conf/plugins/auth-els.opt
@@ -0,0 +1,26 @@
+charon.plugins.auth-els.rekey_config.rekey_1.rekey_time = 7200
+ Time between each request for a new key, only applies to initiator.
+
+charon.plugins.auth-els.rekey_config.rekey_1.reauth_time = 606000
+ Reauth time to replace old key with new one.
+
+charon.plugins.auth-els.rekey_config.rekey_1.reauth_rekey_jitter = 60
+ Minimum separation between reauth and rekey.
+
+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 : . -.
+
+charon.plugins.auth-els.shared_secret_config.shared_secret_1.shared_secret = strongswan
+ Shared secret between initiator and target
+
+charon.plugins.auth-els.algorithm_config.ike_proposal = aes256gcm16-prfsha256-curve25519
+ Encryption algorithm for IKE - SA negotiation
+
+charon.plugins.auth-els.algorithm_config.esp_proposal = aes128gcm16
+ Encryption algorithm for ESP - data on the wire
+
+charon.plugins.auth-els.rekey_config.rekey_1.ike_auth_direct_child = false
+ If it is desired to get the child SA during the IKE_AUTH phase, set this to true
diff --git a/configure.ac b/configure.ac
index d7e7a1134..d1513760f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,6 +3,7 @@
# Copyright (C) 2006-2019 Andreas Steffen
# Copyright (C) 2006-2014 Martin Willi
# HSR Hochschule fuer Technik Rapperswil
+# Copyright (C) 2019-2020 Marvell
#
# 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
@@ -204,6 +205,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.])
@@ -596,6 +598,8 @@ AC_CHECK_FUNCS(pthread_rwlock_init)
AC_CHECK_FUNCS(pthread_spin_init)
# check if we have POSIX semaphore functions, including timed-wait
AC_CHECK_FUNCS(sem_timedwait)
+# lookup major()/minor()/makedev()
+AC_HEADER_MAJOR
LIBS=$saved_LIBS
AC_CHECK_FUNC(
@@ -1462,6 +1466,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([resolve], [c charon cmd])
ADD_PLUGIN([save-keys], [c])
@@ -1644,6 +1649,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)
@@ -1988,6 +1995,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 b91c89830..1a7bc637f 100644
--- a/src/charon-cmd/cmd/cmd_connection.c
+++ b/src/charon-cmd/cmd/cmd_connection.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2013 Martin Willi
* Copyright (C) 2013 revosec AG
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -181,7 +182,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 1b07230fd..30ffed66c 100644
--- a/src/charon-nm/nm/nm_service.c
+++ b/src/charon-nm/nm/nm_service.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2013-2019 Tobias Brunner
* Copyright (C) 2008-2009 Martin Willi
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -397,7 +398,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 15ac7a6d1..baec785bb 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 79a344e45..a3a74a14c 100644
--- a/src/libcharon/config/ike_cfg.c
+++ b/src/libcharon/config/ike_cfg.c
@@ -450,7 +450,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;
}
diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c
index 9169ba202..66fb72307 100644
--- a/src/libcharon/encoding/parser.c
+++ b/src/libcharon/encoding/parser.c
@@ -2,6 +2,7 @@
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -596,11 +597,20 @@ METHOD(parser_t, parse_payload, status_t,
return PARSE_ERROR;
}
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 ADDRESS:
{
int address_length = (ts_type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
+ address_length = ((ts_type == TS_FC_ADDR_RANGE) ? 3 : address_length);
if (!parse_chunk(this, rule_number, output + rule->offset,
address_length))
diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.c b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
index febf0c410..68e770fe5 100644
--- a/src/libcharon/encoding/payloads/traffic_selector_substructure.c
+++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
@@ -3,6 +3,7 @@
* Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -66,6 +67,22 @@ struct private_traffic_selector_substructure_t {
* Ending address.
*/
chunk_t ending_address;
+
+ /**
+ * starting R_CTL.
+ */
+ uint8_t starting_r_ctl;
+
+ /**
+ * ending R_CTL.
+ */
+ uint8_t ending_r_ctl;
+
+ /**
+ * FC port is identified using port index
+ * as host_t structure is still not FC compliant.
+ */
+ uint16_t id;
};
/**
@@ -109,9 +126,68 @@ static encoding_rule_t encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
+/**
+ * Encoding rules to parse or generate a TS payload as per FC-SP-2
+ *
+ * The defined offsets are the positions in a object of type
+ * private_traffic_selector_substructure_t.
+ */
+static encoding_rule_t fc_encodings[] = {
+ /* 1 Byte next ts type*/
+ { TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
+ /* 1 Byte reserved*/
+ { U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) },
+ /* 2 Byte Length of the whole payload*/
+ { PAYLOAD_LENGTH,offsetof(private_traffic_selector_substructure_t, payload_length) },
+ /* 1 Byte starting R_CTL*/
+ { U_INT_8, offsetof(private_traffic_selector_substructure_t, starting_r_ctl) },
+ /* 3 Bytes starting address */
+ { ADDRESS, offsetof(private_traffic_selector_substructure_t, starting_address) },
+ /* 1 Byte ending R_CTL*/
+ { U_INT_8, offsetof(private_traffic_selector_substructure_t, ending_r_ctl) },
+ /* 3 Bytes ending address */
+ { ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) },
+ /* 2 Byte start type*/
+ { U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) },
+ /* 2 Byte start type*/
+ { U_INT_16, offsetof(private_traffic_selector_substructure_t, end_port) }
+};
+/*
+ 0 1 2 3 4
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! TS Type ! Reserved* | Selector Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Starting R_CTL| Starting Address* |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Ending R_CTL | Ending Address* |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Start Type* | End Type* |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
METHOD(payload_t, verify, status_t,
private_traffic_selector_substructure_t *this)
{
+ if (this->ts_type == TS_FC_ADDR_RANGE)
+ {
+ if (this->start_port > this->end_port)
+ {
+ return FAILED;
+ }
+ if (this->starting_r_ctl > this->ending_r_ctl)
+ {
+ return FAILED;
+ }
+ if ((this->starting_address.len != 3) ||
+ (this->ending_address.len != 3))
+ {
+ /* ipv4 address must be 4 bytes long */
+ return FAILED;
+ }
+ return SUCCESS;
+ }
+
if (this->start_port > this->end_port)
{
/* OPAQUE ports are the only exception */
@@ -142,6 +218,15 @@ METHOD(payload_t, verify, status_t,
}
break;
}
+ case TS_FC_ADDR_RANGE:
+ {
+ if ((this->starting_address.len != 3) ||
+ (this->ending_address.len != 3))
+ {
+ return FAILED;
+ }
+ break;
+ }
default:
{
/* not supported ts type */
@@ -155,8 +240,16 @@ METHOD(payload_t, verify, status_t,
METHOD(payload_t, get_encoding_rules, int,
private_traffic_selector_substructure_t *this, encoding_rule_t **rules)
{
- *rules = encodings;
- return countof(encodings);
+ if (this->ts_type == TS_FC_ADDR_RANGE)
+ {
+ *rules = fc_encodings;
+ return countof(fc_encodings);
+ }
+ else
+ {
+ *rules = encodings;
+ return countof(encodings);
+ }
}
METHOD(payload_t, get_header_length, int,
@@ -188,13 +281,42 @@ 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) +
+ 8; //starting address(3), ending address(3), start R_CTL(1), end R_CTL(1)
+ }
+}
+
+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)
{
- return traffic_selector_create_from_bytes(
+ traffic_selector_t* ts = NULL;
+ if (this->ts_type == TS_FC_ADDR_RANGE)
+ {
+ ts = traffic_selector_create_from_fcsp2_format(this->starting_address, this->start_port,
+ this->ending_address, this->end_port,
+ this->starting_r_ctl, this->ending_r_ctl);
+ }
+ else
+ {
+ ts = traffic_selector_create_from_bytes(
this->ip_protocol_id, this->ts_type,
this->starting_address, this->start_port,
this->ending_address, this->end_port);
+ }
+ return ts;
}
METHOD2(payload_t, traffic_selector_substructure_t, destroy, void,
@@ -224,6 +346,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,
.destroy = _destroy,
},
@@ -251,6 +375,15 @@ traffic_selector_substructure_t *traffic_selector_substructure_create_from_traff
this->ending_address = chunk_clone(ts->get_to_address(ts));
this->payload_length = get_header_length(this) +
this->ending_address.len + this->starting_address.len;
+ if (this->ts_type == TS_FC_ADDR_RANGE)
+ {
+ this->payload_length = get_header_length(this) +
+ this->ending_address.len + this->starting_address.len +
+ 2; //start/end R_CTL
+ this->starting_r_ctl = ts->get_start_rctl(ts);
+ this->ending_r_ctl = ts->get_end_rctl(ts);
+ this->id = ts->get_id(ts);
+ }
return &this->public;
}
diff --git a/src/libcharon/kernel/kernel_fc_sp.c b/src/libcharon/kernel/kernel_fc_sp.c
new file mode 100644
index 000000000..9532cae4f
--- /dev/null
+++ b/src/libcharon/kernel/kernel_fc_sp.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
+ *
+ *
+ * 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.
+ */
+
+#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..2d2b12e59
--- /dev/null
+++ b/src/libcharon/kernel/kernel_fc_sp.h
@@ -0,0 +1,341 @@
+/*
+ * 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: 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 <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;
+ /** 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 e216c972c..9304723e1 100644
--- a/src/libcharon/kernel/kernel_interface.c
+++ b/src/libcharon/kernel/kernel_interface.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -90,6 +91,11 @@ struct private_kernel_interface_t {
* Registered IPsec constructor
*/
kernel_ipsec_constructor_t ipsec_constructor;
+
+ /**
+ * Registered FC-SP constructor
+ */
+ kernel_fc_sp_constructor_t fc_sp_constructor;
/**
* Registered net constructor
@@ -100,6 +106,11 @@ struct private_kernel_interface_t {
* ipsec interface
*/
kernel_ipsec_t *ipsec;
+
+ /**
+ * fc-sp interface
+ */
+ kernel_fc_sp_t *fc_sp;
/**
* network interface
@@ -150,17 +161,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;
}
@@ -169,6 +190,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;
@@ -180,6 +214,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;
@@ -436,6 +481,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;
@@ -459,6 +516,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;
@@ -470,6 +539,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;
@@ -491,6 +572,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;
@@ -502,6 +594,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;
@@ -513,6 +613,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;
@@ -629,6 +740,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;
@@ -639,6 +759,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;
@@ -773,6 +902,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)
{
@@ -992,6 +1146,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);
@@ -1042,6 +1197,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 b7e3686d1..3fddfa91c 100644
--- a/src/libcharon/kernel/kernel_interface.h
+++ b/src/libcharon/kernel/kernel_interface.h
@@ -3,6 +3,7 @@
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -55,6 +56,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 +88,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 +111,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.
@@ -459,6 +466,7 @@ struct kernel_interface_t {
*/
bool (*add_ipsec_interface)(kernel_interface_t *this,
kernel_ipsec_constructor_t create);
+
/**
* Unregister an ipsec kernel interface constructor.
@@ -469,6 +477,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 70ff2eb12..917c5fde5 100644
--- a/src/libcharon/kernel/kernel_ipsec.h
+++ b/src/libcharon/kernel/kernel_ipsec.h
@@ -5,6 +5,7 @@
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -184,6 +185,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 04cd4dc01..89c99dda6 100644
--- a/src/libcharon/network/sender.c
+++ b/src/libcharon/network/sender.c
@@ -48,6 +48,10 @@ struct private_sender_t {
* mutex to synchronize access to list
*/
mutex_t *mutex;
+
+ mutex_t *wakeup_mutex;
+
+ int sender_thread_count;
/**
* condvar to signal for packets added to list
@@ -97,8 +101,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)
{
@@ -150,12 +154,24 @@ 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);
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);
+ this->mutex->unlock(this->mutex);
+ continue;
+ }
}
this->list->remove_first(this->list, (void**)&packet);
this->sent->signal(this->sent);
+ this->wakeup_mutex->unlock (this->wakeup_mutex);
this->mutex->unlock(this->mutex);
charon->socket->send(charon->socket, packet);
@@ -191,6 +207,7 @@ METHOD(sender_t, destroy, void,
sender_t * sender_create()
{
private_sender_t *this;
+ int i;
INIT(this,
.public = {
@@ -201,6 +218,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,
@@ -213,10 +233,13 @@ sender_t * sender_create()
"%s.send_delay_response", TRUE, lib->ns),
);
- 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));
-
+ 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 e8ee5e347..b037dfcfa 100644
--- a/src/libcharon/network/socket.h
+++ b/src/libcharon/network/socket.h
@@ -4,6 +4,7 @@
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -60,6 +61,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 0a7ac9d11..6df56a0bb 100644
--- a/src/libcharon/network/socket_manager.c
+++ b/src/libcharon/network/socket_manager.c
@@ -3,6 +3,7 @@
* HSR Hochschule fuer Technik Rapperswil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -21,6 +22,7 @@
#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;
@@ -33,16 +35,21 @@ struct private_socket_manager_t {
* Public socket_manager_t interface.
*/
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;
+ socket_t *ip_socket;
+
+ /**
+ * Instantiated socket implementation for FC
+ */
+ socket_t *fc_socket;
/**
* The constructor used to create the current socket
@@ -60,7 +67,7 @@ METHOD(socket_manager_t, receiver, status_t,
{
status_t status;
this->lock->read_lock(this->lock);
- if (!this->socket)
+ if (!this->ip_socket)
{
DBG1(DBG_NET, "no socket implementation registered, receiving failed");
this->lock->unlock(this->lock);
@@ -68,7 +75,7 @@ METHOD(socket_manager_t, receiver, status_t,
}
/* receive is blocking and the thread can be cancelled */
thread_cleanup_push((thread_cleanup_t)this->lock->unlock, this->lock);
- status = this->socket->receive(this->socket, packet);
+ status = this->ip_socket->receive(this->ip_socket, packet);
thread_cleanup_pop(TRUE);
return status;
}
@@ -77,26 +84,51 @@ METHOD(socket_manager_t, sender, status_t,
private_socket_manager_t *this, packet_t *packet)
{
status_t status;
+ socket_t *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)
+ {
+ socket = this->fc_socket;
+ }
+ else
+ {
+ socket = this->ip_socket;
+ }
+
+ if (!socket)
{
- DBG1(DBG_NET, "no socket implementation registered, sending failed");
+ 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 = socket->send(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 *socket;
+
this->lock->read_lock(this->lock);
- if (this->socket)
+ if (family == SOCKET_FAMILY_FC)
+ {
+ socket = this->fc_socket;
+ }
+ else
{
- port = this->socket->get_port(this->socket, nat_t);
+ socket = this->ip_socket;
+ }
+
+ if (socket)
+ {
+ port = socket->get_port(socket, nat_t);
}
this->lock->unlock(this->lock);
return port;
@@ -106,40 +138,41 @@ 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)
- {
- families = this->socket->supported_families(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->ip_socket != NULL)
+ {
+ this->lock->read_lock(this->lock);
+ families = this->ip_socket->supported_families (this->ip_socket);
+ this->lock->unlock(this->lock);
}
- this->lock->unlock(this->lock);
return families;
}
-static void create_socket(private_socket_manager_t *this)
-{
- 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)
- {
- this->socket = create();
- if (this->socket)
- {
- this->create = create;
- break;
- }
- }
-}
-
METHOD(socket_manager_t, add_socket, void,
private_socket_manager_t *this, socket_constructor_t create)
{
+ socket_t *new_socket;
+ socket_family_t family;
+
this->lock->write_lock(this->lock);
- this->sockets->insert_last(this->sockets, create);
- if (!this->socket)
+ new_socket = create();
+ family = new_socket->supported_families (new_socket);
+
+ if (new_socket)
+ {
+ this->socket_constructors->put (this->socket_constructors, (void*) create, (void*) family);
+ }
+
+ if (family == SOCKET_FAMILY_FC)
{
- create_socket(this);
+ this->fc_socket = new_socket;
+ }
+ else
+ {
+ this->ip_socket = new_socket;
}
this->lock->unlock(this->lock);
}
@@ -148,22 +181,28 @@ 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 = NULL;
- this->create = NULL;
- create_socket(this);
+ this->ip_socket->destroy (this->ip_socket);
+ this->ip_socket = NULL;
}
+ this->socket_constructors->remove (this->socket_constructors, (void*) create);
this->lock->unlock(this->lock);
}
METHOD(socket_manager_t, destroy, void,
private_socket_manager_t *this)
{
- DESTROY_IF(this->socket);
- this->sockets->destroy(this->sockets);
+ DESTROY_IF(this->ip_socket);
+ DESTROY_IF(this->fc_socket);
this->lock->destroy(this->lock);
free(this);
}
@@ -185,8 +224,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),
+ .ip_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 38baaea91..01781691e 100644
--- a/src/libcharon/network/socket_manager.h
+++ b/src/libcharon/network/socket_manager.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010-2013 Tobias Brunner
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -58,7 +59,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..1332a109b
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_configs.c
@@ -0,0 +1,595 @@
+/* Copyright (C) 2019-2020 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 <config/child_cfg.h>
+
+#include "auth_els_utils.h"
+#include "auth_els_configs.h"
+
+typedef struct auth_els_backend_t auth_els_backend_t;
+struct auth_els_backend_t {
+
+ backend_t public;
+ linked_list_t* configs;
+};
+
+typedef struct auth_els_psk_creds_t auth_els_psk_creds_t;
+struct auth_els_psk_creds_t {
+
+ credential_set_t credential_set;
+ linked_list_t* auth_els_psks;
+};
+
+typedef struct {
+ enumerator_t public;
+ enumerator_t *inner;
+ shared_key_t *current;
+ identification_t *me;
+ identification_t *other;
+} shared_enumerator_t;
+
+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;
+
+ auth_els_backend_t backend;
+ auth_els_psk_creds_t* creds;
+
+ chunk_t shared_secret;
+ enum shared_secret_type_t secret_type;
+
+ proposal_t *esp_proposal;
+ proposal_t *ike_proposal;
+};
+typedef struct private_auth_els_configs_t private_auth_els_configs_t;
+
+
+METHOD(enumerator_t, shared_enumerator_enumerate, bool,
+ shared_enumerator_t *this, va_list args)
+{
+ DBG4(DBG_CFG, "auth_els - entering shared_enumerator_enumerate");
+
+ shared_key_t **key;
+ shared_enumerator_t *rport_shared_key;
+ enumerator_t *e1;
+ id_match_t local_match = ID_MATCH_NONE, remote_match = ID_MATCH_NONE;
+ id_match_t *me_match;
+ id_match_t *other_match;
+
+ VA_ARGS_VGET(args, key, me_match, other_match);
+
+ if ((this != NULL) && (this->inner != NULL))
+ {
+ e1 = this->inner;//->create_enumerator(this->inner);
+ while (e1->enumerate(e1, &rport_shared_key))
+ {
+ if( (rport_shared_key == NULL) ||
+ (rport_shared_key->me == NULL) ||
+ (rport_shared_key->other == NULL) )
+ {
+ DBG4(DBG_CFG, "auth_els - shared_enumerator_enumerate shared key is NULL");
+ continue;
+ }
+
+ if ( (this == NULL) || (this->me == NULL) || (this->other == NULL) ) {
+ DBG4(DBG_CFG, "auth_els - shared_enumerator_enumerate local or remote identification is NULL");
+ continue;
+ }
+
+ local_match = this->me->matches(this->me, rport_shared_key->me);
+ remote_match = this->other->matches(this->other, rport_shared_key->other);
+ if (me_match)
+ *me_match = local_match;
+ if (other_match)
+ *other_match = remote_match;
+ DBG_STD ("me_match=%N other_match=%N",
+ id_match_names, local_match, id_match_names, remote_match);
+ if ( (local_match >= ID_MATCH_PERFECT) && (remote_match >= ID_MATCH_PERFECT) )
+ {
+ chunk_t key_s = rport_shared_key->current->get_key(rport_shared_key->current);
+ this->current = shared_key_create( SHARED_IKE, chunk_clone(key_s));
+ *key = this->current;
+ DBG_STD ("matching shared key for %Y - %Y is %#B",
+ rport_shared_key->me, rport_shared_key->other,
+ &key_s);
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+METHOD(enumerator_t, shared_enumerator_destroy, void,
+ shared_enumerator_t *this)
+{
+ DESTROY_IF(this->inner);
+ DESTROY_IF(this->me);
+ DESTROY_IF(this->other);
+ DESTROY_IF(this->current);
+ free(this);
+}
+
+METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
+ auth_els_psk_creds_t *this, shared_key_type_t type,
+ identification_t *me, identification_t *other)
+{
+ DBG4(DBG_CFG, "auth_els - entering create_shared_enumerator");
+ DBG_ENTER;
+
+ shared_enumerator_t *data;
+
+ if (type != SHARED_IKE)
+ {
+ return NULL;
+ }
+
+ if ((me == NULL) || (other == NULL))
+ {
+ DBG_STD ("local or remote identification is NULL");
+ return NULL;
+ }
+
+ if (this->auth_els_psks == NULL)
+ {
+ this->auth_els_psks = linked_list_create ();
+ }
+
+ INIT(data,
+ .public = {
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _shared_enumerator_enumerate,
+ .destroy = _shared_enumerator_destroy,
+ },
+ .inner = this->auth_els_psks->create_enumerator(this->auth_els_psks),
+ .current = NULL,
+ .me = identification_create_from_encoding(me->get_type(me), me->get_encoding(me)),
+ .other = identification_create_from_encoding(other->get_type(other), other->get_encoding(other)),
+ );
+
+ return &data->public;
+}
+
+CALLBACK(ike_filter, bool,
+ void *data, enumerator_t *orig, va_list args)
+{
+ //DBG4(DBG_CFG, "auth_els - entering ike_filter me => %#H", me);
+
+ peer_cfg_t *cfg;
+ ike_cfg_t **out;
+ ike_cfg_t *ikecfg;
+
+ host_t *me = (host_t *)data;
+
+ VA_ARGS_VGET(args, out);
+
+ while (orig->enumerate(orig, &cfg))
+ {
+ ikecfg = cfg->get_ike_cfg(cfg);
+ if (ikecfg && me)
+ {
+ if (ikecfg->get_my_port(ikecfg) == me->get_port(me))
+ {
+ //DBG4(DBG_CFG, "auth_els - ike_filter ike_cfg found for me => %#H", me);
+ *out = ikecfg;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
+ auth_els_backend_t *this, host_t *me, host_t *other)
+{
+ if (this->configs == NULL)
+ {
+ this->configs = linked_list_create ();
+ }
+ return enumerator_create_filter(
+ this->configs->create_enumerator(this->configs),
+ (void*)ike_filter, me, (void*)nop);
+}
+
+typedef struct {
+ identification_t *me;
+ identification_t *other;
+} peer_data_t;
+
+CALLBACK(peer_filter, bool,
+ void *data, enumerator_t *orig, va_list args)
+{
+ peer_cfg_t *cfg;
+ peer_cfg_t **out;
+ id_match_t match_me = ID_MATCH_NONE;
+ id_match_t match_other = ID_MATCH_NONE;
+
+ peer_data_t *peer_data = (peer_data_t*)data;
+ identification_t *me = (identification_t *)peer_data->me;
+ identification_t *other = (identification_t *)peer_data->other;
+
+ //DBG4(DBG_CFG, "auth_els - auth_els_configs - peer_filter looking for peer configs matching [%Y]...[%Y]",
+ // me, other);
+
+ VA_ARGS_VGET(args, out);
+
+ if ((me == NULL) || (me->get_encoding(me).ptr == NULL))
+ return FALSE;
+
+ if ((other == NULL) || (other->get_encoding(other).ptr == NULL))
+ return FALSE;
+
+ //DBG4(DBG_CFG, "auth_els - entering peer_filter me => name %s", me->get_encoding(me).ptr);
+
+ while (orig->enumerate(orig, &cfg))
+ {
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
+ identification_t *candidate;
+ enumerator = cfg->create_auth_cfg_enumerator(cfg, TRUE);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ candidate = auth->get(auth, AUTH_RULE_IDENTITY);
+ if (candidate)
+ {
+ if (me)
+ {
+ //DBG1(DBG_CFG, "auth_els - auth_els_configs - peer_filter enumerator me[%Y]...my[%Y]",
+ // me, candidate);
+ match_me = me->matches(me, candidate);
+ }
+
+ if (match_me == ID_MATCH_PERFECT)
+ {
+ break;
+ }
+
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = cfg->create_auth_cfg_enumerator(cfg, FALSE);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ candidate = auth->get(auth, AUTH_RULE_IDENTITY);
+ if (candidate)
+ {
+ if (other)
+ {
+ //DBG4(DBG_CFG, "auth_els - auth_els_configs - peer_filter enumerator other[%Y]...remote[%Y]",
+ // other, candidate);
+ match_other = other->matches(other, candidate);
+ }
+
+ if (match_other == ID_MATCH_PERFECT)
+ {
+ //DBG4(DBG_CFG, "auth_els - peer_filter id_match=%N", id_match_names, match);
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if ((match_me == ID_MATCH_PERFECT) && (match_other == ID_MATCH_PERFECT))
+ {
+ //DBG4(DBG_CFG, "auth_els - peer_filter id_match=%N", id_match_names, match);
+ *out = cfg;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void destroy_peer_cfg_enum (void *data)
+{
+ free (data);
+}
+
+METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
+ auth_els_backend_t *this, identification_t *me, identification_t *other)
+{
+ if (this->configs == NULL)
+ {
+ this->configs = linked_list_create ();
+ }
+
+ peer_data_t *data;
+ INIT(data,
+ .me = me,
+ .other = other,
+ );
+
+ return enumerator_create_filter(
+ this->configs->create_enumerator(this->configs),
+ (void*)peer_filter, data, destroy_peer_cfg_enum);
+}
+
+METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
+ auth_els_backend_t *this, char *name)
+{
+ DBG2(DBG_CFG, "auth_els - entering get_peer_cfg_by_name name=%s", name);
+ enumerator_t *e1;
+ peer_cfg_t *current, *found = NULL;
+
+ if (this->configs == NULL)
+ {
+ this->configs = linked_list_create ();
+ }
+
+ e1 = this->configs->create_enumerator(this->configs);
+ while (e1->enumerate(e1, ¤t))
+ {
+ if (strncaseeq(current->get_name(current), name, 32))
+ {
+ found = current;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ return found;
+}
+
+static auth_els_psk_creds_t *auth_els_psk_creds_create()
+{
+ auth_els_psk_creds_t *this;
+
+ INIT(this,
+ .credential_set = {
+ .create_shared_enumerator = _create_shared_enumerator,
+ .create_private_enumerator = (void*)return_null,
+ .create_cert_enumerator = (void*)return_null,
+ .create_cdp_enumerator = (void*)return_null,
+ .cache_cert = (void*)nop,
+ },
+ .auth_els_psks = NULL,
+ );
+
+ return this;
+}
+
+METHOD(auth_els_configs_t, reload_config, bool,
+ private_auth_els_configs_t *this)
+{
+
+ char *shared_secret_section, *shared_secret_string = NULL;
+ enumerator_t* enumerator;
+
+ enumerator = lib->settings->create_section_enumerator(lib->settings,
+ "%s.plugins.auth-els.shared_secret_config", lib->ns);
+
+ while (enumerator->enumerate(enumerator, &shared_secret_section))
+ {
+ shared_secret_string = lib->settings->get_str(lib->settings,
+ "%s.plugins.auth-els.shared_secret_config.%s.shared_secret", NULL,
+ lib->ns, shared_secret_section);
+ DBG1(DBG_CFG, "auth_els - add_rport_cfg - config file secret: %s", shared_secret_string);
+ }
+ enumerator->destroy(enumerator);
+
+ if (shared_secret_string == NULL)
+ {
+ this->secret_type = SHARED_SECRET_TYPE_WWPN;
+ }
+ else
+ {
+ this->shared_secret = chunk_clone (chunk_create (shared_secret_string, strlen (shared_secret_string)));
+ this->secret_type = SHARED_SECRET_TYPE_CONFIG_FILE;
+ }
+
+ char *proposal = lib->settings->get_str(lib->settings,
+ "%s.plugins.auth-els.algorithm_config.esp_proposal", NULL,
+ lib->ns);
+
+ if (proposal)
+ {
+ // If the user gives us a proposal, then validate below.
+ DBG_STD ("User encryption algorithms proposal: %s", proposal);
+ }
+ else
+ {
+ proposal = ESP_ENCR_PROPOSAL_DEFAULT_128_BIT;
+ DBG_STD ("Default encryption algorithms proposal: %s", proposal);
+ }
+
+ this->esp_proposal = proposal_create_from_string(PROTO_ESP, proposal);
+ if (this->esp_proposal == NULL)
+ {
+ DBG_FATAL ("Invalid ESP proposal");
+ return FALSE;
+ }
+
+ proposal = lib->settings->get_str(lib->settings,
+ "%s.plugins.auth-els.algorithm_config.ike_proposal", NULL,
+ lib->ns);
+
+ if (proposal)
+ {
+ // If the user gives us a proposal, then validate below.
+ DBG_STD ("User ike algorithms proposal: %s", proposal);
+ }
+ else
+ {
+ proposal = IKE_PROPOSAL_DEFAULT_128_BIT;
+
+ DBG_STD ("Default ike algorithms proposal: %s", proposal);
+ }
+
+ this->ike_proposal = proposal_create_from_string(PROTO_IKE, proposal);
+ if (this->ike_proposal == NULL)
+ {
+ DBG_FATAL ("Invalid IKE proposal");
+ return FALSE;
+ }
+
+ uint16_t esp_enc_alg, ike_enc_alg, prf, dh_group;
+ uint16_t key_size_temp, esp_key_size;
+ this->esp_proposal->get_algorithm (this->esp_proposal, ENCRYPTION_ALGORITHM, (uint16_t*) &esp_enc_alg, &key_size_temp);
+
+ if ((esp_enc_alg != ENCR_AES_GCM_ICV16) && (esp_enc_alg != ENCR_NULL_AUTH_AES_GMAC))
+ {
+ DBG_STD ("Invalid encryption algorithm specified: %N, set to default", encryption_algorithm_names, esp_enc_alg);
+ this->esp_proposal->destroy (this->esp_proposal);
+ this->esp_proposal = proposal_create_from_string(PROTO_ESP, ESP_ENCR_PROPOSAL_DEFAULT_128_BIT);
+ }
+
+ this->esp_proposal->get_algorithm (this->esp_proposal, ENCRYPTION_ALGORITHM, &esp_enc_alg, &esp_key_size);
+ this->ike_proposal->get_algorithm (this->ike_proposal, ENCRYPTION_ALGORITHM, &ike_enc_alg, &key_size_temp);
+ this->ike_proposal->get_algorithm (this->ike_proposal, DIFFIE_HELLMAN_GROUP, &dh_group, &key_size_temp);
+ this->ike_proposal->get_algorithm (this->ike_proposal, PSEUDO_RANDOM_FUNCTION, &prf, &key_size_temp);
+
+ // We don't have a separate integrity algorithm because GCM and GMAC are AEAD which has integrity algorithm built in.
+ DBG_STD ("chosen algorithms: esp encryption: %N, %d, ike encryption: %N, %d, PRF: %N, %d, DH Group: %N, %d",
+ encryption_algorithm_names, esp_enc_alg, esp_enc_alg,
+ encryption_algorithm_names, ike_enc_alg, ike_enc_alg,
+ pseudo_random_function_names, prf, prf,
+ diffie_hellman_group_names, dh_group, dh_group);
+
+ enumerator = this->esp_proposal->create_enumerator (this->esp_proposal, ENCRYPTION_ALGORITHM);
+ while (enumerator->enumerate (enumerator, &esp_enc_alg, &esp_key_size))
+ {
+ DBG_STD ("Possible key size for ESP GCM: %d", esp_key_size);
+ }
+ enumerator->destroy (enumerator);
+
+ return TRUE;
+}
+
+METHOD(auth_els_configs_t, get_esp_proposal, proposal_t*, private_auth_els_configs_t *this)
+{
+ // We have to return a clone because the proposal is destroyed whenever the ike_sa is destroyed.
+ proposal_t *clone_prop = this->esp_proposal->clone (this->esp_proposal, 0);
+ return clone_prop;
+}
+
+METHOD(auth_els_configs_t, get_ike_proposal, proposal_t*, private_auth_els_configs_t *this)
+{
+ // We have to return a clone because the proposal is destroyed whenever the ike_sa is destroyed.
+ proposal_t *clone_prop = this->ike_proposal->clone (this->ike_proposal, 0);
+ return clone_prop;
+}
+
+METHOD(auth_els_configs_t, get_shared_secret, chunk_t, private_auth_els_configs_t *this,
+ bool initiator, char *host_name, char *rport_name)
+{
+ if (this->secret_type == SHARED_SECRET_TYPE_WWPN)
+ {
+ uint8_t default_shared_secret[(2 * HOST_NAME_SIZE) + 1] = { 0 };
+ chunk_t shared_secret;
+
+ if (initiator)
+ {
+ strncpy(default_shared_secret, host_name, HOST_NAME_SIZE);
+ strncpy(default_shared_secret+HOST_NAME_SIZE, rport_name, HOST_NAME_SIZE);
+ }
+ else
+ {
+ strncpy(default_shared_secret, rport_name, HOST_NAME_SIZE);
+ strncpy(default_shared_secret+HOST_NAME_SIZE, host_name, HOST_NAME_SIZE);
+ }
+ default_shared_secret[(2 * HOST_NAME_SIZE)] = '\0'; // Make sure default secret is only 32 bytes.
+
+ shared_secret = chunk_clone (chunk_create (default_shared_secret, (2 * HOST_NAME_SIZE) + 1));
+
+ return shared_secret;
+ }
+ else
+ {
+ return chunk_clone (this->shared_secret);
+ }
+}
+
+METHOD(auth_els_configs_t, get_backend, backend_t*,
+ private_auth_els_configs_t *this)
+{
+ return &this->backend.public;
+}
+
+METHOD(auth_els_configs_t, get_creds, credential_set_t*,
+ private_auth_els_configs_t *this)
+{
+ return &this->creds->credential_set;
+}
+
+METHOD(auth_els_configs_t, destroy, void,
+ private_auth_els_configs_t *this)
+{
+ peer_cfg_t *current;
+ enumerator_t *config_enum = this->backend.configs->create_enumerator(this->backend.configs);
+
+ DBG_ENTER;
+
+ while (config_enum->enumerate(config_enum, ¤t))
+ {
+ this->backend.configs->remove (this->backend.configs, current, NULL);
+ current->destroy(current);
+ }
+ if (this->creds->auth_els_psks)
+ {
+ this->creds->auth_els_psks->destroy_function (this->creds->auth_els_psks, (void*)_shared_enumerator_destroy);
+ }
+ free (this->creds);
+
+ if (this->secret_type != SHARED_SECRET_TYPE_WWPN)
+ {
+ chunk_free (&this->shared_secret);
+ }
+ DESTROY_IF (this->esp_proposal);
+ DESTROY_IF (this->ike_proposal);
+ free(this);
+}
+
+auth_els_configs_t *auth_els_configs_create()
+{
+ private_auth_els_configs_t *this;
+
+ INIT(this,
+ .public = {
+ .destroy = _destroy,
+ .get_backend = _get_backend,
+ .get_creds = _get_creds,
+ .reload_config = _reload_config,
+ .get_shared_secret = _get_shared_secret,
+ .get_esp_proposal = _get_esp_proposal,
+ .get_ike_proposal = _get_ike_proposal,
+ },
+ .backend = {
+ .configs = NULL,
+ .public = {
+ .create_peer_cfg_enumerator = (void*)_create_peer_cfg_enumerator,
+ .create_ike_cfg_enumerator = (void*)_create_ike_cfg_enumerator,
+ .get_peer_cfg_by_name = (void*)_get_peer_cfg_by_name,
+ },
+ },
+ .creds = auth_els_psk_creds_create(),
+ .ike_proposal = NULL,
+ .esp_proposal = NULL,
+ );
+
+ 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..76be6df88
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_configs.h
@@ -0,0 +1,44 @@
+/* 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 {
+
+ backend_t* (*get_backend)(auth_els_configs_t *this);
+ credential_set_t* (*get_creds)(auth_els_configs_t *this);
+ bool (*reload_config)(auth_els_configs_t *this);
+ chunk_t (*get_shared_secret) (auth_els_configs_t *this,
+ bool initiator, char *host_name, char *rport_name);
+ proposal_t* (*get_esp_proposal) (auth_els_configs_t *this);
+ proposal_t* (*get_ike_proposal) (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..8914f5d3c
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_ike.c
@@ -0,0 +1,265 @@
+/* Copyright (C) 2019-2020 Marvell */
+
+#include "auth_els_plugin.h"
+#include "auth_els_ike.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_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;
+ auth_els_plugin_t *plugin;
+
+ unsigned int rekey_time;
+ unsigned int reauth_time;
+ unsigned int reauth_rekey_jitter;
+};
+
+
+
+METHOD(listener_t, ike_keys, bool,
+ private_auth_els_ike_t *this, ike_sa_t *ike_sa, diffie_hellman_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, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
+{
+ DBG_STD ("ike_sa: %p, child_sa: %p", ike_sa, child_sa);
+
+ chunk_t secret;
+
+ if (dh && dh->get_shared_secret(dh, &secret))
+ {
+ DBG_STD ("DH secret:");
+ chunk_clear(&secret);
+ }
+
+ 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(auth_els_plugin_t *plugin_ref)
+{
+ 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,
+ },
+ .plugin = plugin_ref,
+ );
+
+ 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..5404454f4
--- /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(auth_els_plugin_t *plugin_ref);
+
+#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..cba29def4
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_kernel_fc_sp.c
@@ -0,0 +1,252 @@
+/* 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 ipsec instance.
+ */
+struct private_auth_els_kernel_fc_sp_t {
+
+ /**
+ * Public auth_els_kernel_ipsec 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_ipsec_t, get_features, kernel_feature_t,
+ private_auth_els_kernel_fc_sp_t *this)
+{
+ DBG2 (DBG_CFG, "auth_els - auth_els_kernel_ipsec - get_features callback, ignoring");
+ return KERNEL_POLICY_SPI;
+}
+
+METHOD(kernel_ipsec_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_ipsec_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_ipsec_t, add_sa, status_t,
+ private_auth_els_kernel_fc_sp_t *this, kernel_ipsec_sa_id_t *id,
+ kernel_ipsec_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_ipsec_t, query_sa, status_t,
+ private_auth_els_kernel_fc_sp_t *this, kernel_ipsec_sa_id_t *id,
+ kernel_ipsec_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_ipsec_t, del_sa, status_t,
+ private_auth_els_kernel_fc_sp_t *this,
+ kernel_ipsec_sa_id_t *id,
+ kernel_ipsec_del_sa_t *data)
+{
+ status_t final_status = FAILED;
+
+ DBG_STD ("start: spi: %x", id->spi);
+
+ return final_status;
+}
+
+METHOD(kernel_ipsec_t, update_sa, status_t,
+ private_auth_els_kernel_fc_sp_t *this, kernel_ipsec_sa_id_t *id,
+ kernel_ipsec_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_ipsec_t, flush_sas, status_t,
+ private_auth_els_kernel_fc_sp_t *this)
+{
+ DBG_ENTER;
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, add_policy, status_t,
+ private_auth_els_kernel_fc_sp_t *this, kernel_ipsec_policy_id_t *id,
+ kernel_ipsec_manage_policy_t *data)
+{
+ DBG_ENTER;
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, query_policy, status_t,
+ private_auth_els_kernel_fc_sp_t *this, kernel_ipsec_policy_id_t *id,
+ kernel_ipsec_query_policy_t *data, time_t *use_time)
+{
+ DBG_ENTER;
+ return NOT_SUPPORTED;
+}
+
+METHOD(kernel_ipsec_t, del_policy, status_t,
+ private_auth_els_kernel_fc_sp_t *this, kernel_ipsec_policy_id_t *id,
+ kernel_ipsec_manage_policy_t *data)
+{
+ DBG_ENTER;
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, flush_policies, status_t,
+ private_auth_els_kernel_fc_sp_t *this)
+{
+ DBG_ENTER;
+ return SUCCESS;
+}
+
+
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+ private_auth_els_kernel_fc_sp_t *this, int fd, int family)
+{
+ DBG_ENTER;
+ return TRUE;
+}
+
+METHOD(kernel_ipsec_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_ipsec_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,
+ .flush_sas = _flush_sas,
+ .add_policy = _add_policy,
+ .query_policy = _query_policy,
+ .del_policy = _del_policy,
+ .flush_policies = _flush_policies,
+ .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..56d7418ac
--- /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_ipsec.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_ipsec_t interface
+ */
+ kernel_ipsec_t interface;
+
+};
+
+/**
+ * Create a auth_els kernel ipsec interface instance.
+ *
+ * @return auth_els_kernel_ipsec_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..35b683aaa
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_plugin.c
@@ -0,0 +1,208 @@
+/* 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_ike_t *ike;
+ backend_t* backend;
+ credential_set_t *creds;
+
+ int apidev_fd;
+ auth_els_configs_t *configs;
+};
+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 %x", 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);
+
+}
+
+/**
+ * Initialize plugin
+ */
+static bool initialize_plugin(private_auth_els_plugin_t *this)
+{
+ if (this->configs->reload_config(this->configs) == FALSE)
+ {
+ return FALSE;
+ }
+
+ this->ike = auth_els_ike_create(&this->public);
+
+ setup_signal_handlers (this);
+
+ 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)
+ {
+ DBG_STD ("before socket_register");
+
+ lib->credmgr->add_set(lib->credmgr, this->creds);
+ }
+
+ if (reg)
+ {
+ if (!initialize_plugin(this))
+ {
+ return FALSE;
+ }
+ charon->bus->add_listener(charon->bus, &this->ike->listener);
+ charon->backends->add_backend(charon->backends, this->backend);
+ }
+ else
+ {
+ lib->credmgr->remove_set(lib->credmgr, this->creds);
+ }
+ 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-ipsec"),
+ PLUGIN_CALLBACK(socket_register, auth_els_socket_create),
+ PLUGIN_PROVIDE(CUSTOM, "socket"),
+ PLUGIN_DEPENDS(CUSTOM, "kernel-ipsec"),
+ 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)
+{
+ return TRUE;
+}
+
+METHOD(plugin_t, destroy, void,
+ private_auth_els_plugin_t *this)
+{
+ DESTROY_IF(this->ike);
+
+ 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 = NULL,
+ );
+
+ this->configs = auth_els_configs_create ();
+
+ this->backend = this->configs->get_backend(this->configs);
+ this->creds = this->configs->get_creds(this->configs);
+
+ 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..8d74c1f52
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_plugin.h
@@ -0,0 +1,43 @@
+/* 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 3
+#define AUTH_STRING_SUFFIX_VERSION "-stub"
+#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
+
+/** Test **/
+
+/**
+ * Plugin to synchronize state in a high availability cluster.
+ */
+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..00faba208
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_socket.c
@@ -0,0 +1,115 @@
+/* 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_plugin.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..6c864582d
--- /dev/null
+++ b/src/libcharon/plugins/auth_els/auth_els_utils.h
@@ -0,0 +1,40 @@
+/* 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
+ */
+
+#include <pthread.h>
+
+#ifndef AUTH_ELS_UTILS_H
+#define AUTH_ELS_UTILS_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__); \
+}
+
+#endif /* AUTH_ELS_UTILS_H */
+
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index f94291505..27a0b4aca 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -193,7 +193,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/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index 77c9630ca..3bbd08f69 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -746,7 +747,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint 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 be42d7d7d..b31542afd 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -90,7 +91,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,
};
@@ -404,7 +405,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 b9dce8c0d..500be51b1 100644
--- a/src/libcharon/plugins/medsrv/medsrv_config.c
+++ b/src/libcharon/plugins/medsrv/medsrv_config.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -133,7 +134,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 fb8ea8c5e..30560d9b0 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2006-2008 Martin Willi
* Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -275,7 +276,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 fff6a438f..1d2a69cca 100644
--- a/src/libcharon/plugins/stroke/stroke_attribute.c
+++ b/src/libcharon/plugins/stroke/stroke_attribute.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2010 Tobias Brunner
* Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -192,6 +193,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 fe5c1a542..cfd58a402 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2012-2014 Tobias Brunner
* Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -291,7 +292,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);
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index 92b18a8a6..abf8d1bde 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -5,6 +5,8 @@
* Copyright (C) 2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
+ * Copyright (C) 2019-2020 Marvell
+ *
* 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
@@ -653,10 +655,13 @@ 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)))
{
@@ -665,8 +670,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)
@@ -676,9 +683,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 a66bb58cb..807da0344 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -2,6 +2,7 @@
* Copyright (C) 2008 Thomas Kallenberg
* Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -129,7 +130,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,
@@ -254,7 +255,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 f7c7ce13a..de6c302e6 100644
--- a/src/libcharon/plugins/vici/vici_attribute.c
+++ b/src/libcharon/plugins/vici/vici_attribute.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -467,6 +468,7 @@ CALLBACK(pool_li, bool,
switch (host->get_family(host))
{
case AF_INET:
+ case AF_NETLINK:
type = keys[index].v4;
break;
case AF_INET6:
@@ -481,7 +483,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 eb679290d..c3e8e7517 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2015-2019 Tobias Brunner
* Copyright (C) 2015-2018 Andreas Steffen
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -750,7 +751,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,
@@ -2473,7 +2474,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 4c09b578d..2b2694e9a 100644
--- a/src/libcharon/plugins/vici/vici_control.c
+++ b/src/libcharon/plugins/vici/vici_control.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -480,7 +481,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 574d715a7..c8cc72703 100644
--- a/src/libcharon/processing/jobs/migrate_job.c
+++ b/src/libcharon/processing/jobs/migrate_job.c
@@ -103,7 +103,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 b11236b8f..e0d467ddc 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -5,6 +5,7 @@
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -633,7 +634,8 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
.mark = this->mark_in,
.if_id = this->if_id_in,
};
- 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,
&in) == SUCCESS)
@@ -660,7 +662,8 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
.if_id = this->if_id_out,
.interface = this->config->get_interface(this->config),
};
- 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)
@@ -736,6 +739,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)
{
@@ -947,7 +956,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);
}
@@ -1310,10 +1319,12 @@ METHOD(child_sa_t, register_outbound, status_t,
uint16_t cpi, bool tfcv3)
{
status_t status;
+
+ int family = this->my_addr->get_family (this->my_addr);
/* if the kernel supports installing SPIs with policies we install the
* SA immediately as it will only be used once we update the policies */
- if (charon->kernel->get_features(charon->kernel) & KERNEL_POLICY_SPI)
+ if (charon->kernel->get_features(charon->kernel, family) & KERNEL_POLICY_SPI)
{
status = install_internal(this, encr, integ, spi, cpi, FALSE, FALSE,
tfcv3);
@@ -1811,6 +1822,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 c9b3f63e2..90cec0146 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -3,6 +3,7 @@
* Copyright (C) 2006-2008 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -334,6 +335,16 @@ struct child_sa_t {
* @return absolute time
*/
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 d6cc4e5a7..0d63bc763 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -4,6 +4,7 @@
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -1076,10 +1077,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));
}
}
@@ -1384,6 +1385,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:
@@ -1435,7 +1437,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
{
@@ -2572,6 +2574,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:
@@ -3015,11 +3018,9 @@ METHOD(ike_sa_t, destroy, void,
free(this);
}
-/*
- * 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;
@@ -3131,8 +3132,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),
@@ -3163,8 +3164,9 @@ 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)
{
@@ -3174,3 +3176,12 @@ 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);
+}
\ No newline at end of file
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index d51108140..466f541fb 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -3,6 +3,7 @@
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -1221,4 +1222,7 @@ 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);
+
#endif /** IKE_SA_H_ @}*/
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 1de410d6c..c0f608758 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2005-2011 Martin Willi
* Copyright (C) 2011 revosec AG
+ * Copyright (C) 2019-2020 Marvell
*
* Copyright (C) 2008-2018 Tobias Brunner
* Copyright (C) 2005 Jan Hutter
@@ -1202,8 +1203,8 @@ METHOD(ike_sa_manager_t, checkout, ike_sa_t*,
return ike_sa;
}
-METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*,
- private_ike_sa_manager_t* this, ike_version_t version, bool initiator)
+METHOD(ike_sa_manager_t, checkout_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;
@@ -1227,7 +1228,7 @@ METHOD(ike_sa_manager_t, checkout_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)
@@ -1238,6 +1239,12 @@ METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*,
return ike_sa;
}
+METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*,
+ private_ike_sa_manager_t* this, ike_version_t version, bool initiator)
+{
+ return checkout_new_with_family (this, version, initiator, AF_INET);
+}
+
/**
* Get the message ID or message hash to detect early retransmissions
*/
@@ -1256,8 +1263,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;
@@ -1328,7 +1335,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();
@@ -1422,6 +1429,12 @@ out:
return ike_sa;
}
+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)
{
@@ -2361,7 +2374,9 @@ ike_sa_manager_t *ike_sa_manager_create()
.public = {
.checkout = _checkout,
.checkout_new = _checkout_new,
+ .checkout_new_with_family = _checkout_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 efad2e4d6..012059af0 100644
--- a/src/libcharon/sa/ike_sa_manager.h
+++ b/src/libcharon/sa/ike_sa_manager.h
@@ -2,6 +2,7 @@
* Copyright (C) 2008-2017 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -58,9 +59,20 @@ struct ike_sa_manager_t {
* - NULL, if specified IKE_SA is not found.
*/
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* (*checkout_new_with_family) (ike_sa_manager_t* this, ike_version_t version,
+ bool initiator, int family);
/**
- * Create and check out a new IKE_SA.
+ * Create and check out a new IKE_SA with default address family of AF_INET.
*
* @param version IKE version of this SA
* @param initiator TRUE for initiator, FALSE otherwise
@@ -90,6 +102,7 @@ struct ike_sa_manager_t {
* - checked out/created IKE_SA
* - NULL to not process message further
*/
+ ike_sa_t* (*checkout_by_message_with_family) (ike_sa_manager_t* this, message_t *message, int family);
ike_sa_t* (*checkout_by_message) (ike_sa_manager_t* this, message_t *message);
/**
diff --git a/src/libcharon/sa/ikev1/tasks/informational.c b/src/libcharon/sa/ikev1/tasks/informational.c
index 2798978b2..bf11991dd 100644
--- a/src/libcharon/sa/ikev1/tasks/informational.c
+++ b/src/libcharon/sa/ikev1/tasks/informational.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2011 Martin Willi
* Copyright (C) 2011 revosec AG
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -117,7 +118,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 81e63740e..482c6803a 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
@@ -2,6 +2,7 @@
* Copyright (C) 2006-2011 Tobias Brunner,
* Copyright (C) 2006-2007 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2019-2020 Marvell
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -103,7 +104,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 6bafd42e0..757f1fb7c 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -2,6 +2,7 @@
* Copyright (C) 2007-2018 Tobias Brunner
* Copyright (C) 2007-2010 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -2083,7 +2084,7 @@ METHOD(task_manager_t, queue_child, void,
{
child_create_t *task;
- task = child_create_create(this->ike_sa, cfg, FALSE, tsi, tsr);
+ task = child_create_create(this->ike_sa, cfg->get_ref(cfg), FALSE, tsi, tsr);
if (reqid)
{
task->use_reqid(task, reqid);
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index e98c1dbcc..95e338005 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -3,6 +3,7 @@
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -901,8 +902,11 @@ static bool build_payloads(private_child_create_t *this, message_t *message)
default:
break;
}
+
+ 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);
+ features = charon->kernel->get_features(charon->kernel, family);
if (!(features & KERNEL_ESP_V3_TFC))
{
message->add_notify(message, FALSE, ESP_TFC_PADDING_NOT_SUPPORTED,
@@ -1323,7 +1327,7 @@ static linked_list_t* get_ts_if_nat_transport(private_child_create_t *this,
static child_cfg_t* select_child_cfg(private_child_create_t *this)
{
peer_cfg_t *peer_cfg;
- child_cfg_t *child_cfg = NULL;;
+ child_cfg_t *child_cfg = NULL;
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
if (peer_cfg && this->tsi && this->tsr)
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
index b2ad0a02a..5fc74721a 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
@@ -2,6 +2,7 @@
* Copyright (C) 2010-2018 Tobias Brunner
* Copyright (C) 2007 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -327,9 +328,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)
{
@@ -375,6 +376,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 8ea903ec8..e04714e75 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_natd.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_natd.c
@@ -2,6 +2,7 @@
* Copyright (C) 2006-2007 Martin Willi
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -85,7 +86,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;
@@ -101,6 +102,18 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this,
chunk_t natd_hash;
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);
@@ -109,11 +122,10 @@ 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);
-
+
/* natd_hash = SHA1( spi_i | spi_r | address | port ) */
natd_chunk = chunk_cat("cccc", spi_i_chunk, spi_r_chunk, addr_chunk, port_chunk);
if (!this->hasher->allocate_hash(this->hasher, natd_chunk, &natd_hash))
@@ -184,6 +196,7 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
ike_sa_id = message->get_ike_sa_id(message);
me = message->get_destination(message);
other = message->get_source(message);
+
dst_hash = generate_natd_hash(this, ike_sa_id, me);
src_hash = generate_natd_hash(this, ike_sa_id, other);
diff --git a/src/libstrongswan/networking/host.c b/src/libstrongswan/networking/host.c
index 110ece894..8d9fbb40e 100644
--- a/src/libstrongswan/networking/host.c
+++ b/src/libstrongswan/networking/host.c
@@ -84,6 +84,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);
}
@@ -121,19 +122,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),
@@ -166,6 +171,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;
@@ -197,6 +203,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);
}
@@ -217,6 +224,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;
@@ -258,6 +266,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));
@@ -286,6 +295,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);
}
@@ -394,6 +404,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;
@@ -405,7 +416,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;
@@ -430,6 +441,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));
@@ -481,6 +493,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;
@@ -515,6 +528,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);
@@ -664,6 +678,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/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c
index b694e97cd..121248bbe 100644
--- a/src/libstrongswan/plugins/plugin_loader.c
+++ b/src/libstrongswan/plugins/plugin_loader.c
@@ -658,7 +658,7 @@ static bool loadable_feature_matches(registered_feature_t *a,
}
/**
- * Returns a compatible plugin feature for the given dependency
+ * Returns a compatible plugin feature for the given depencency
*/
static bool find_compatible_feature(private_plugin_loader_t *this,
plugin_feature_t *dependency)
diff --git a/src/libstrongswan/selectors/traffic_selector.c b/src/libstrongswan/selectors/traffic_selector.c
index cfd2b029d..9377ca980 100644
--- a/src/libstrongswan/selectors/traffic_selector.c
+++ b/src/libstrongswan/selectors/traffic_selector.c
@@ -3,6 +3,7 @@
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -27,13 +28,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(ts_type_name, TS_IPV4_ADDR_RANGE, TS_IPV6_ADDR_RANGE,
+ENUM(ts_type_name, TS_IPV4_ADDR_RANGE, TS_FC_ADDR_RANGE,
"TS_IPV4_ADDR_RANGE",
"TS_IPV6_ADDR_RANGE",
+ "TS_FC_ADDR_RANGE",
);
typedef struct private_traffic_selector_t private_traffic_selector_t;
@@ -88,6 +91,23 @@ struct private_traffic_selector_t {
* end of port range
*/
uint16_t to_port;
+
+ /**
+ * starting R_CTL.
+ */
+ uint8_t starting_r_ctl;
+
+ /**
+ * ending R_CTL.
+ */
+ uint8_t ending_r_ctl;
+
+ /**
+ * FC port is identified using port index
+ * as host_t structure is still not FC compliant.
+ */
+ uint16_t id;
+
};
/**
@@ -234,7 +254,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");
@@ -245,6 +265,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));
@@ -312,6 +337,14 @@ 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);
+ written += print_in_hook(data, "%d-%d",
+ this->starting_r_ctl, this->ending_r_ctl);
+
+ }
else
{
serv = getservbyport(htons(this->from_port), serv_proto);
@@ -340,6 +373,12 @@ int traffic_selector_printf_hook(printf_hook_data_t *data,
{
written += print_in_hook(data, "%d-%d",
this->from_port, this->to_port);
+ if (this->type == TS_FC_ADDR_RANGE)
+ {
+ written += print_in_hook(data, "%d-%d",
+ this->starting_r_ctl, this->ending_r_ctl);
+
+ }
}
}
@@ -421,6 +460,14 @@ METHOD(traffic_selector_t, get_subset, traffic_selector_t*,
/* we have a match in protocol, port, and address: return it... */
subset = traffic_selector_create(protocol, this->type, from_port, to_port);
+ if(this->type == TS_FC_ADDR_RANGE)
+ {
+ subset->starting_r_ctl = this->starting_r_ctl;
+ subset->ending_r_ctl = this->ending_r_ctl;
+ subset->id = this->id;
+ from = this->from;
+ to = this->to;
+ }
memcpy(subset->from, from, size);
memcpy(subset->to, to, size);
calc_netbits(subset);
@@ -470,6 +517,56 @@ METHOD(traffic_selector_t, get_protocol, uint8_t,
return this->protocol;
}
+METHOD(traffic_selector_t, get_start_rctl, uint8_t,
+ private_traffic_selector_t *this)
+{
+ return this->starting_r_ctl;
+}
+
+METHOD(traffic_selector_t, set_start_rctl, void,
+ private_traffic_selector_t *this, uint8_t starting_r_ctl)
+{
+ this->starting_r_ctl = starting_r_ctl;
+}
+
+METHOD(traffic_selector_t, get_end_rctl, uint8_t,
+ private_traffic_selector_t *this)
+{
+ return this->ending_r_ctl;
+}
+
+METHOD(traffic_selector_t, set_end_rctl, void,
+ private_traffic_selector_t *this, uint8_t ending_r_ctl)
+{
+ this->ending_r_ctl = ending_r_ctl;
+}
+
+METHOD(traffic_selector_t, set_id, void,
+ private_traffic_selector_t *this, uint16_t port_index)
+{
+ this->id = port_index;
+}
+
+METHOD(traffic_selector_t, get_id, uint16_t,
+ private_traffic_selector_t *this)
+{
+ return this->id;
+}
+
+METHOD(traffic_selector_t, set_port_id, void,
+ private_traffic_selector_t *this, chunk_t from, chunk_t to)
+{
+ if (this->type == TS_FC_ADDR_RANGE)
+ {
+ if ((from.len != 3) || (to.len != 3))
+ {
+ return;
+ }
+ memcpy(this->from, from.ptr, from.len);
+ memcpy(this->to, to.ptr, to.len);
+ }
+}
+
METHOD(traffic_selector_t, is_host, bool,
private_traffic_selector_t *this, host_t *host)
{
@@ -488,6 +585,14 @@ METHOD(traffic_selector_t, is_host, bool,
return TRUE;
}
}
+ else if (this->type == TS_FC_ADDR_RANGE)
+ {
+ uint16_t port_index = host->get_port(host);
+ if (this->id == port_index)
+ {
+ return TRUE;
+ }
+ }
}
else
{
@@ -515,21 +620,38 @@ 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
- : TS_IPV6_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))
{
memset(this->from, 0x00, sizeof(this->from));
memset(this->to, 0xFF, sizeof(this->to));
this->netbits = 0;
+
+ if (this->type == TS_FC_ADDR_RANGE)
+ {
+ uint16_t port_index = host->get_port(host);
+ this->id = port_index;
+ }
}
else
{
- chunk_t from = host->get_address(host);
- memcpy(this->from, from.ptr, from.len);
- memcpy(this->to, from.ptr, from.len);
- this->netbits = from.len * 8;
+ if (this->type == TS_FC_ADDR_RANGE)
+ {
+ uint16_t port_index = host->get_port(host);
+ this->id = port_index;
+ }
+ else
+ {
+ chunk_t from = host->get_address(host);
+ memcpy(this->from, from.ptr, from.len);
+ memcpy(this->to, from.ptr, from.len);
+ this->netbits = from.len * 8;
+ }
}
this->dynamic = FALSE;
}
@@ -540,6 +662,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)
@@ -558,6 +689,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))
@@ -568,6 +700,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;
}
@@ -633,12 +772,24 @@ METHOD(traffic_selector_t, clone_, traffic_selector_t*,
memcpy(clone->from, this->from, len);
memcpy(clone->to, this->to, len);
+ if (clone->type == TS_FC_ADDR_RANGE)
+ {
+ clone->starting_r_ctl = this->starting_r_ctl;
+ clone->ending_r_ctl = this->ending_r_ctl;
+ clone->id = this->id;
+ }
return &clone->public;
}
METHOD(traffic_selector_t, hash, u_int,
private_traffic_selector_t *this, u_int hash)
{
+ if (this->type == TS_FC_ADDR_RANGE)
+ {
+ hash = chunk_hash_inc(chunk_from_thing(this->starting_r_ctl),
+ chunk_hash_inc(chunk_from_thing(this->ending_r_ctl),
+ hash));
+ }
return chunk_hash_inc(get_from_address(this),
chunk_hash_inc(get_to_address(this),
chunk_hash_inc(chunk_from_thing(this->from_port),
@@ -706,7 +857,23 @@ int traffic_selector_cmp(traffic_selector_t *a_pub, traffic_selector_t *b_pub,
return res;
}
/* larger port ranges first */
- return compare_int(b->to_port, a->to_port);
+ res = compare_int(b->to_port, a->to_port);
+ if (res)
+ {
+ return res;
+ }
+
+ if (a->type == TS_FC_ADDR_RANGE)
+ {
+ res = compare_int(b->starting_r_ctl, a->starting_r_ctl);
+ if (res)
+ {
+ return res;
+ }
+ res = compare_int(b->ending_r_ctl, a->ending_r_ctl);
+ }
+ return res;
+
}
/*
@@ -882,7 +1049,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;
}
@@ -906,6 +1073,13 @@ static private_traffic_selector_t *traffic_selector_create(uint8_t protocol,
.clone = _clone_,
.hash = _hash,
.destroy = _destroy,
+ .get_start_rctl = _get_start_rctl,
+ .get_end_rctl = _get_end_rctl,
+ .set_start_rctl = _set_start_rctl,
+ .set_end_rctl = _set_end_rctl,
+ .set_port_id = _set_port_id,
+ .set_id = _set_id,
+ .get_id = _get_id,
},
.from_port = from_port,
.to_port = to_port,
@@ -919,3 +1093,22 @@ 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_type,
+ chunk_t end_address, uint16_t end_type,
+ uint8_t start_rctl, uint8_t end_rctl)
+{
+ ts_type_t type = TS_FC_ADDR_RANGE;
+ private_traffic_selector_t *this = traffic_selector_create(IPPROTO_RAW, type,
+ start_type, end_type);
+
+ memset(this->from, 0x0, start_address.len);
+ memcpy(this->from, start_address.ptr, start_address.len);
+ this->starting_r_ctl = start_rctl;
+
+ memset(this->to, 0x0, end_address.len);
+ memcpy(this->to, end_address.ptr, end_address.len);
+ this->ending_r_ctl = end_rctl;
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/selectors/traffic_selector.h b/src/libstrongswan/selectors/traffic_selector.h
index 03f7a6d8c..9c7251705 100644
--- a/src/libstrongswan/selectors/traffic_selector.h
+++ b/src/libstrongswan/selectors/traffic_selector.h
@@ -3,6 +3,7 @@
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -50,7 +51,16 @@ enum ts_type_t {
* (inclusive). All addresses falling between the two specified
* addresses are considered to be within the list.
*/
- TS_IPV6_ADDR_RANGE = 8
+ 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
};
/**
@@ -152,6 +162,55 @@ struct traffic_selector_t {
*/
uint8_t (*get_protocol)(traffic_selector_t *this);
+ /**
+ * Get the starting R_CTL type allowed for FC frame
+ *
+ * @return starting R_CTL
+ */
+ uint8_t (*get_start_rctl) (traffic_selector_t *this);
+
+ /**
+ * Get the ending R_CTL type allowed for FC frame
+ *
+ * @return ending R_CTL
+ */
+ uint8_t (*get_end_rctl) (traffic_selector_t *this);
+
+ /**
+ * set the starting R_CTL type allowed for FC frame
+ *
+ * @return ending R_CTL
+ */
+ void (*set_start_rctl) (traffic_selector_t *this, uint8_t starting_r_ctl);
+
+ /**
+ * set the ending R_CTL type allowed for FC frame
+ *
+ * @return ending R_CTL
+ */
+ void (*set_end_rctl) (traffic_selector_t *this, uint8_t ending_r_ctl);
+
+ /**
+ * set the 3 bytes port identifiers allowed for FC port
+ *
+ * @return ending R_CTL
+ */
+ void (*set_port_id) (traffic_selector_t *this, chunk_t from, chunk_t to);
+
+ /**
+ * set id in ts for FC port as host_t is still not FC compilant
+ *
+ * @return ending R_CTL
+ */
+ void (*set_id) (traffic_selector_t *this, uint16_t port_index);
+
+ /**
+ * get id from ts for FC port to check corresponding host match to identity payload
+ *
+ * @return ending R_CTL
+ */
+ uint16_t (*get_id) (traffic_selector_t *this);
+
/**
* Check if the traffic selector is for a single host.
*
@@ -416,4 +475,23 @@ 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_type,
+ chunk_t end_address, uint16_t end_type,
+ uint8_t start_rctl, uint8_t end_rctl);
+
#endif /** TRAFFIC_SELECTOR_H_ @}*/
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index 3d803c04b..f60e2df40 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -4,6 +4,7 @@
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -36,7 +37,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",
@@ -48,8 +49,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);
@@ -1281,6 +1283,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)
@@ -1353,6 +1359,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;
@@ -1416,6 +1423,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 704df7842..b2d57ccd7 100644
--- a/src/libstrongswan/utils/identification.h
+++ b/src/libstrongswan/utils/identification.h
@@ -3,6 +3,7 @@
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2019-2020 Marvell
*
* 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
@@ -125,6 +126,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
*/
--
2.29.2