diff -Naur libreswan-3.15-orig/programs/pluto/connections.c libreswan-3.15/programs/pluto/connections.c
--- libreswan-3.15-orig/programs/pluto/connections.c 2016-03-24 12:23:58.563262638 -0400
+++ libreswan-3.15/programs/pluto/connections.c 2016-03-24 12:24:31.462320143 -0400
@@ -2498,6 +2498,8 @@
struct connection *c,
lset_t req_policy, lset_t policy_exact_mask)
{
+ struct connection *candidate = NULL;
+
DBG(DBG_CONTROLMORE,
DBG_log("find_next_host_connection policy=%s",
bitnamesof(sa_policy_bit_names, req_policy)));
@@ -2547,10 +2549,22 @@
* Success if all specified policy bits are in candidate's policy.
* It works even when the exact-match bits are included.
*/
- if ((req_policy & ~c->policy) == LEMPTY)
- break;
+ if ((req_policy & ~c->policy) == LEMPTY) {
+ if (c->newest_isakmp_sa != SOS_NOBODY) {
+ break;
+ } else {
+ /*
+ * We prefer connections with an IKE SA.
+ * so remember this, but keep looking
+ */
+ candidate = c;
+ }
+ }
}
+ if (c == NULL && candidate != NULL)
+ c = candidate;
+
DBG(DBG_CONTROLMORE,
DBG_log("find_next_host_connection returns %s",
c ? c->name : "empty"));
diff -Naur libreswan-3.15-orig/programs/pluto/state.c libreswan-3.15/programs/pluto/state.c
--- libreswan-3.15-orig/programs/pluto/state.c 2016-03-24 12:23:58.560262542 -0400
+++ libreswan-3.15/programs/pluto/state.c 2016-03-24 12:24:33.929399445 -0400
@@ -939,6 +939,28 @@
return FALSE;
}
+bool shared_phase1_connection(const struct connection *c)
+{
+ int i;
+
+ so_serial_t serial_us = c->newest_isakmp_sa;
+
+ if (serial_us == SOS_NOBODY)
+ return FALSE;
+
+ for (i = 0; i < STATE_TABLE_SIZE; i++) {
+ struct state *st;
+
+ FOR_EACH_ENTRY(st, i, {
+ if (st->st_connection == c)
+ continue;
+ if (st->st_clonedfrom == serial_us)
+ return TRUE;
+ });
+ }
+ return FALSE;
+}
+
/*
* delete all states that were created for a given connection,
* additionally delete any states for which func(st, c)
@@ -1108,8 +1130,9 @@
{
if (IS_ISAKMP_SA_ESTABLISHED(this->st_state))
return FALSE;
- else
+ if (c->kind == CK_INSTANCE)
return same_phase1_sa_relations(this, c);
+ return FALSE;
}
void delete_p2states_by_connection(struct connection *c)
diff -Naur libreswan-3.15-orig/programs/pluto/state.h libreswan-3.15/programs/pluto/state.h
--- libreswan-3.15-orig/programs/pluto/state.h 2015-08-24 22:28:32.000000000 -0400
+++ libreswan-3.15/programs/pluto/state.h 2016-03-24 12:24:33.929399445 -0400
@@ -587,6 +587,7 @@
extern bool require_ddos_cookies(void);
extern void show_globalstate_status(void);
extern void log_newest_sa_change(char *f, struct state *const st);
+bool shared_phase1_connection(const struct connection *c);
#ifdef XAUTH_HAVE_PAM
void ikev2_free_auth_pam(so_serial_t st_serialno);
diff -Naur libreswan-3.15-orig/programs/pluto/terminate.c libreswan-3.15/programs/pluto/terminate.c
--- libreswan-3.15-orig/programs/pluto/terminate.c 2015-08-24 22:28:32.000000000 -0400
+++ libreswan-3.15/programs/pluto/terminate.c 2016-03-24 12:24:33.930399477 -0400
@@ -75,7 +75,14 @@
libreswan_log("terminating SAs using this connection");
c->policy &= ~POLICY_UP;
flush_pending_by_connection(c);
- delete_states_by_connection(c, FALSE);
+ if (shared_phase1_connection(c)) {
+ libreswan_log("IKE SA is shared - only terminating IPsec SA");
+ delete_state(state_with_serialno(c->newest_ipsec_sa));
+ } else {
+ DBG(DBG_CONTROL, DBG_log("connection not shared pkilling phase1 and phase2"));
+ delete_states_by_connection(c, FALSE);
+ }
+
reset_cur_connection();
return 1;