diff options
Diffstat (limited to 'src/libcharon/sa/ike_sa_manager.c')
-rw-r--r-- | src/libcharon/sa/ike_sa_manager.c | 97 |
1 files changed, 65 insertions, 32 deletions
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index 4625df5b8..307ea3b4a 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2005-2011 Martin Willi * Copyright (C) 2011 revosec AG - * Copyright (C) 2008-2015 Tobias Brunner + * Copyright (C) 2008-2016 Tobias Brunner * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -17,12 +17,14 @@ */ #include <string.h> +#include <inttypes.h> #include "ike_sa_manager.h" #include <daemon.h> #include <sa/ike_sa_id.h> #include <bus/bus.h> +#include <threading/thread.h> #include <threading/condvar.h> #include <threading/mutex.h> #include <threading/rwlock.h> @@ -57,9 +59,9 @@ struct entry_t { condvar_t *condvar; /** - * Is this ike_sa currently checked out? + * Thread by which this IKE_SA is currently checked out, if any */ - bool checked_out; + thread_t *checked_out; /** * Does this SA drives out new threads? @@ -1142,13 +1144,16 @@ METHOD(ike_sa_manager_t, checkout, ike_sa_t*, entry_t *entry; u_int segment; - DBG2(DBG_MGR, "checkout IKE_SA"); + DBG2(DBG_MGR, "checkout %N SA with SPIs %.16"PRIx64"_i %.16"PRIx64"_r", + ike_version_names, ike_sa_id->get_ike_version(ike_sa_id), + be64toh(ike_sa_id->get_initiator_spi(ike_sa_id)), + be64toh(ike_sa_id->get_responder_spi(ike_sa_id))); if (get_entry_by_id(this, ike_sa_id, &entry, &segment) == SUCCESS) { if (wait_for_entry(this, entry, segment)) { - entry->checked_out = TRUE; + entry->checked_out = thread_current(); ike_sa = entry->ike_sa; DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out", ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); @@ -1156,6 +1161,11 @@ METHOD(ike_sa_manager_t, checkout, ike_sa_t*, unlock_single_segment(this, segment); } charon->bus->set_sa(charon->bus, ike_sa); + + if (!ike_sa) + { + DBG2(DBG_MGR, "IKE_SA checkout not successful"); + } return ike_sa; } @@ -1228,7 +1238,10 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, id = id->clone(id); id->switch_initiator(id); - DBG2(DBG_MGR, "checkout IKE_SA by message"); + DBG2(DBG_MGR, "checkout %N SA by message with SPIs %.16"PRIx64"_i " + "%.16"PRIx64"_r", ike_version_names, id->get_ike_version(id), + be64toh(id->get_initiator_spi(id)), + be64toh(id->get_responder_spi(id))); if (id->get_responder_spi(id) == 0 && message->get_message_id(message) == 0) @@ -1269,7 +1282,7 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, DBG1(DBG_MGR, "ignoring message, failed to hash message"); DESTROY_IF(hasher); id->destroy(id); - return NULL; + goto out; } hasher->destroy(hasher); @@ -1288,20 +1301,17 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, entry = entry_create(); entry->ike_sa = ike_sa; entry->ike_sa_id = id; + entry->processing = get_message_id_or_hash(message); + entry->init_hash = hash; segment = put_entry(this, entry); - entry->checked_out = TRUE; + entry->checked_out = thread_current(); unlock_single_segment(this, segment); - entry->processing = get_message_id_or_hash(message); - entry->init_hash = hash; - DBG2(DBG_MGR, "created IKE_SA %s[%u]", ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); - - charon->bus->set_sa(charon->bus, ike_sa); - return ike_sa; + goto out; } else { @@ -1317,14 +1327,14 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, remove_init_hash(this, hash); chunk_free(&hash); id->destroy(id); - return NULL; + goto out; } case FAILED: { /* we failed to allocate an SPI */ chunk_free(&hash); id->destroy(id); DBG1(DBG_MGR, "ignoring message, failed to allocate SPI"); - return NULL; + goto out; } case ALREADY_DONE: default: @@ -1348,7 +1358,7 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, ike_sa_id_t *ike_id; ike_id = entry->ike_sa->get_id(entry->ike_sa); - entry->checked_out = TRUE; + entry->checked_out = thread_current(); if (message->get_first_payload_type(message) != PLV1_FRAGMENT && message->get_first_payload_type(message) != PLV2_FRAGMENT) { /* TODO-FRAG: this fails if there are unencrypted payloads */ @@ -1369,7 +1379,13 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, charon->bus->alert(charon->bus, ALERT_INVALID_IKE_SPI, message); } id->destroy(id); + +out: charon->bus->set_sa(charon->bus, ike_sa); + if (!ike_sa) + { + DBG2(DBG_MGR, "IKE_SA checkout not successful"); + } return ike_sa; } @@ -1385,11 +1401,11 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*, DBG2(DBG_MGR, "checkout IKE_SA by config"); - if (!this->reuse_ikesa) - { /* IKE_SA reuse disable by config */ + if (!this->reuse_ikesa && peer_cfg->get_ike_version(peer_cfg) != IKEV1) + { /* IKE_SA reuse disabled by config (not possible for IKEv1) */ ike_sa = checkout_new(this, peer_cfg->get_ike_version(peer_cfg), TRUE); charon->bus->set_sa(charon->bus, ike_sa); - return ike_sa; + goto out; } enumerator = create_table_enumerator(this); @@ -1411,7 +1427,7 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*, current_ike = current_peer->get_ike_cfg(current_peer); if (current_ike->equals(current_ike, peer_cfg->get_ike_cfg(peer_cfg))) { - entry->checked_out = TRUE; + entry->checked_out = thread_current(); ike_sa = entry->ike_sa; DBG2(DBG_MGR, "found existing IKE_SA %u with a '%s' config", ike_sa->get_unique_id(ike_sa), @@ -1429,6 +1445,12 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*, ike_sa = checkout_new(this, peer_cfg->get_ike_version(peer_cfg), TRUE); } charon->bus->set_sa(charon->bus, ike_sa); + +out: + if (!ike_sa) + { + DBG2(DBG_MGR, "IKE_SA checkout not successful"); + } return ike_sa; } @@ -1440,7 +1462,7 @@ METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*, ike_sa_t *ike_sa = NULL; u_int segment; - DBG2(DBG_MGR, "checkout IKE_SA by ID %u", id); + DBG2(DBG_MGR, "checkout IKE_SA by unique ID %u", id); enumerator = create_table_enumerator(this); while (enumerator->enumerate(enumerator, &entry, &segment)) @@ -1450,7 +1472,7 @@ METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*, if (entry->ike_sa->get_unique_id(entry->ike_sa) == id) { ike_sa = entry->ike_sa; - entry->checked_out = TRUE; + entry->checked_out = thread_current(); break; } /* other threads might be waiting for this entry */ @@ -1464,6 +1486,10 @@ METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*, DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out", ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); } + else + { + DBG2(DBG_MGR, "IKE_SA checkout not successful"); + } charon->bus->set_sa(charon->bus, ike_sa); return ike_sa; } @@ -1477,6 +1503,8 @@ METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*, child_sa_t *child_sa; u_int segment; + DBG2(DBG_MGR, "checkout IKE_SA by%s name '%s'", child ? " child" : "", name); + enumerator = create_table_enumerator(this); while (enumerator->enumerate(enumerator, &entry, &segment)) { @@ -1506,7 +1534,7 @@ METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*, /* got one, return */ if (ike_sa) { - entry->checked_out = TRUE; + entry->checked_out = thread_current(); DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out", ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); break; @@ -1518,6 +1546,11 @@ METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*, enumerator->destroy(enumerator); charon->bus->set_sa(charon->bus, ike_sa); + + if (!ike_sa) + { + DBG2(DBG_MGR, "IKE_SA checkout not successful"); + } return ike_sa; } @@ -1598,7 +1631,7 @@ METHOD(ike_sa_manager_t, checkin, void, /* ike_sa_id must be updated */ entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa)); /* signal waiting threads */ - entry->checked_out = FALSE; + entry->checked_out = NULL; entry->processing = -1; /* check if this SA is half-open */ if (entry->half_open && ike_sa->get_state(ike_sa) != IKE_CONNECTING) @@ -1623,7 +1656,6 @@ METHOD(ike_sa_manager_t, checkin, void, entry->other = other->clone(other); put_half_open(this, entry); } - DBG2(DBG_MGR, "check-in of IKE_SA successful."); entry->condvar->signal(entry->condvar); } else @@ -1639,6 +1671,7 @@ METHOD(ike_sa_manager_t, checkin, void, } segment = put_entry(this, entry); } + DBG2(DBG_MGR, "checkin of IKE_SA successful"); /* apply identities for duplicate test */ if ((ike_sa->get_state(ike_sa) == IKE_ESTABLISHED || @@ -1657,7 +1690,7 @@ METHOD(ike_sa_manager_t, checkin, void, * thread can acquire it. Since it is not yet in the list of * connected peers that will not cause a deadlock as no other * caller of check_unqiueness() will try to check out this SA */ - entry->checked_out = TRUE; + entry->checked_out = thread_current(); unlock_single_segment(this, segment); this->public.check_uniqueness(&this->public, ike_sa, TRUE); @@ -1668,7 +1701,7 @@ METHOD(ike_sa_manager_t, checkin, void, * thread is waiting, but it should still exist, so there is no * need for a lookup via get_entry_by... */ lock_single_segment(this, segment); - entry->checked_out = FALSE; + entry->checked_out = NULL; /* We already signaled waiting threads above, we have to do that * again after checking the SA out and back in again. */ entry->condvar->signal(entry->condvar); @@ -1711,8 +1744,8 @@ METHOD(ike_sa_manager_t, checkin_and_destroy, void, if (entry->driveout_waiting_threads && entry->driveout_new_threads) { /* it looks like flush() has been called and the SA is being deleted * anyway, just check it in */ - DBG2(DBG_MGR, "ignored check-in and destroy of IKE_SA during shutdown"); - entry->checked_out = FALSE; + DBG2(DBG_MGR, "ignored checkin and destroy of IKE_SA during shutdown"); + entry->checked_out = NULL; entry->condvar->broadcast(entry->condvar); unlock_single_segment(this, segment); return; @@ -1748,11 +1781,11 @@ METHOD(ike_sa_manager_t, checkin_and_destroy, void, entry_destroy(entry); - DBG2(DBG_MGR, "check-in and destroy of IKE_SA successful"); + DBG2(DBG_MGR, "checkin and destroy of IKE_SA successful"); } else { - DBG1(DBG_MGR, "tried to check-in and delete nonexisting IKE_SA"); + DBG1(DBG_MGR, "tried to checkin and delete nonexisting IKE_SA"); ike_sa->destroy(ike_sa); } charon->bus->set_sa(charon->bus, NULL); |