From 5a5b26a7dce4c112f62882cfe16dc37659d766e8 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 17 Jul 2015 11:53:58 +0200 Subject: [PATCH 1/5] ike: Adhere to IKE_SA limit when checking out by config This prevents new SAs from getting created if we hit the global IKE_SA limit (we still allow checkout_new(), which is used for rekeying). --- src/libcharon/sa/ike_sa_manager.c | 71 ++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index ce44207..37d49da 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -1401,48 +1401,51 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*, DBG2(DBG_MGR, "checkout IKE_SA 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); - goto out; - } - - enumerator = create_table_enumerator(this); - while (enumerator->enumerate(enumerator, &entry, &segment)) + if (this->reuse_ikesa || peer_cfg->get_ike_version(peer_cfg) == IKEV1) { - if (!wait_for_entry(this, entry, segment)) + enumerator = create_table_enumerator(this); + while (enumerator->enumerate(enumerator, &entry, &segment)) { - continue; - } - if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING || - entry->ike_sa->get_state(entry->ike_sa) == IKE_REKEYED) - { /* skip IKE_SAs which are not usable, wake other waiting threads */ - entry->condvar->signal(entry->condvar); - continue; - } - - current_peer = entry->ike_sa->get_peer_cfg(entry->ike_sa); - if (current_peer && current_peer->equals(current_peer, peer_cfg)) - { - current_ike = current_peer->get_ike_cfg(current_peer); - if (current_ike->equals(current_ike, peer_cfg->get_ike_cfg(peer_cfg))) + if (!wait_for_entry(this, entry, segment)) { - 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), - current_peer->get_name(current_peer)); - break; + continue; } + if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING || + entry->ike_sa->get_state(entry->ike_sa) == IKE_REKEYED) + { /* skip IKE_SAs which are not usable, wake other waiting threads */ + entry->condvar->signal(entry->condvar); + continue; + } + current_peer = entry->ike_sa->get_peer_cfg(entry->ike_sa); + if (current_peer && current_peer->equals(current_peer, peer_cfg)) + { + 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 = 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), + current_peer->get_name(current_peer)); + break; + } + } + /* other threads might be waiting for this entry */ + entry->condvar->signal(entry->condvar); } - /* other threads might be waiting for this entry */ - entry->condvar->signal(entry->condvar); + enumerator->destroy(enumerator); } - enumerator->destroy(enumerator); if (!ike_sa) - { /* no IKE_SA using such a config, hand out a new */ + { /* no IKE_SA using such a config, or reuse disabled, hand out a new */ + if (this->ikesa_limit && + this->public.get_count(&this->public) >= this->ikesa_limit) + { + DBG1(DBG_MGR, "IKE_SA creation failed, hitting IKE_SA limit (%u)", + this->ikesa_limit); + return NULL; + } ike_sa = checkout_new(this, peer_cfg->get_ike_version(peer_cfg), TRUE); } charon->bus->set_sa(charon->bus, ike_sa); -- 2.5.0