respect different peer_cfg's when initiating a CHILD_SA within an existing IKE_SA
static status_t initiate_execute(interface_job_t *job)
{
ike_sa_t *ike_sa;
- ike_cfg_t *ike_cfg;
interface_bus_listener_t *listener = &job->listener;
peer_cfg_t *peer_cfg = listener->peer_cfg;
- ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
- ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager,
- ike_cfg->get_my_host(ike_cfg), ike_cfg->get_other_host(ike_cfg),
- peer_cfg->get_my_id(peer_cfg), peer_cfg->get_other_id(peer_cfg));
+ ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
+ peer_cfg);
listener->ike_sa = ike_sa;
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
static status_t route_execute(interface_job_t *job)
{
ike_sa_t *ike_sa;
- ike_cfg_t *ike_cfg;
interface_bus_listener_t *listener = &job->listener;
peer_cfg_t *peer_cfg = listener->peer_cfg;
- ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
-
- ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager,
- ike_cfg->get_my_host(ike_cfg), ike_cfg->get_other_host(ike_cfg),
- peer_cfg->get_my_id(peer_cfg), peer_cfg->get_other_id(peer_cfg));
+ ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
+ peer_cfg);
listener->ike_sa = ike_sa;
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
iterator = charon->backends->create_iterator(charon->backends);
while (iterator->iterate(iterator, (void**)&peer_cfg))
{
+ host_t *my_vip_conf, *other_vip_conf;
+ bool my_vip_equals = FALSE, other_vip_equals = FALSE;
+
+ my_vip_conf = peer_cfg->get_my_virtual_ip(peer_cfg);
+ if ((my_vip && my_vip_conf && my_vip->equals(my_vip, my_vip_conf)) ||
+ (!my_vip_conf && !my_vip))
+ {
+ my_vip_equals = TRUE;
+ }
+ DESTROY_IF(my_vip_conf);
+ other_vip_conf = peer_cfg->get_other_virtual_ip(peer_cfg, NULL);
+ if ((other_vip && other_vip_conf && other_vip->equals(other_vip, other_vip_conf)) ||
+ (!other_vip_conf && !other_vip))
+ {
+ other_vip_equals = TRUE;
+ }
+ DESTROY_IF(other_vip_conf);
+
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
if (my_id->equals(my_id, peer_cfg->get_my_id(peer_cfg))
&& other_id->equals(other_id, peer_cfg->get_other_id(peer_cfg))
&& peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1)
&& peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method
&& peer_cfg->get_eap_type(peer_cfg, &vendor) == msg->add_conn.eap_type
- && vendor == msg->add_conn.eap_vendor)
+ && vendor == msg->add_conn.eap_vendor
+ && my_vip_equals && other_vip_equals)
{
DBG1(DBG_CFG, "reusing existing configuration '%s'",
peer_cfg->get_name(peer_cfg));
}
/**
- * Implementation of of ike_sa_manager.checkout_by_peer.
+ * Implementation of of ike_sa_manager.checkout_by_config.
*/
-static ike_sa_t* checkout_by_peer(private_ike_sa_manager_t *this,
- host_t *my_host, host_t *other_host,
- identification_t *my_id,
- identification_t *other_id)
+static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
+ peer_cfg_t *peer_cfg)
{
iterator_t *iterator;
entry_t *entry;
ike_sa_t *ike_sa = NULL;
+ identification_t *my_id, *other_id;
+ host_t *my_host, *other_host;
+ ike_cfg_t *ike_cfg;
+
+ ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
+ my_host = ike_cfg->get_my_host(ike_cfg);
+ other_host = ike_cfg->get_other_host(ike_cfg);
+ my_id = peer_cfg->get_my_id(peer_cfg);
+ other_id = peer_cfg->get_other_id(peer_cfg);
pthread_mutex_lock(&(this->mutex));
(other_host->is_anyaddr(other_host) ||
other_host->ip_equals(other_host, found_other_host)) &&
found_my_id->matches(found_my_id, my_id, &wc) &&
- found_other_id->matches(found_other_id, other_id, &wc))
+ found_other_id->matches(found_other_id, other_id, &wc) &&
+ streq(peer_cfg->get_name(peer_cfg),
+ entry->ike_sa->get_name(entry->ike_sa)))
{
/* looks good, we take this one */
DBG2(DBG_MGR, "found an existing IKE_SA for %H[%D]...%H[%D]",
this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
this->public.checkout_new = (ike_sa_t*(*)(ike_sa_manager_t*,bool))checkout_new;
this->public.checkout_by_message = (ike_sa_t*(*)(ike_sa_manager_t*,message_t*))checkout_by_message;
- this->public.checkout_by_peer = (ike_sa_t*(*)(ike_sa_manager_t*,host_t*,host_t*,identification_t*,identification_t*))checkout_by_peer;
+ this->public.checkout_by_config = (ike_sa_t*(*)(ike_sa_manager_t*,peer_cfg_t*))checkout_by_config;
this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id;
this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name;
this->public.create_iterator = (iterator_t*(*)(ike_sa_manager_t*))create_iterator;
#include <library.h>
#include <sa/ike_sa.h>
#include <encoding/message.h>
+#include <config/peer_cfg.h>
/**
* @brief The IKE_SA-Manager is responsible for managing all initiated and responded IKE_SA's.
ike_sa_t* (*checkout_by_message) (ike_sa_manager_t* this, message_t *message);
/**
- * @brief Checkout an existing IKE_SA by hosts and identifications.
+ * @brief Checkout an IKE_SA for initiation by a peer_config.
*
- * Allows the lookup of an IKE_SA by user IDs and hosts. It returns the
- * first found occurence, if there are multiple candidates. Supplied IDs
- * may contain wildcards, hosts may be %any.
+ * To initiate, a CHILD_SA may be established within an existing IKE_SA.
+ * This call checks for an existing IKE_SA by comparing the configuration.
+ * If the CHILD_SA can be created in an existing IKE_SA, the matching SA
+ * is returned.
* If no IKE_SA is found, a new one is created. This is also the case when
* the found IKE_SA is in the DELETING state.
*
* @param this the manager object
- * @param my_host address of our host
- * @param other_id address of remote host
- * @param my_id ID used by us
- * @param other_id ID used by remote
+ * @param peer_cfg configuration used to find an existing IKE_SA
* @return checked out/created IKE_SA
*/
- ike_sa_t* (*checkout_by_peer) (ike_sa_manager_t* this,
- host_t *my_host, host_t* other_host,
- identification_t *my_id,
- identification_t *other_id);
+ ike_sa_t* (*checkout_by_config) (ike_sa_manager_t* this,
+ peer_cfg_t *peer_cfg);
/**
* @brief Check out an IKE_SA a unique ID.