while (iterator->iterate(iterator, (void**)&waiting_sa))
{
ike_sa_t *sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, waiting_sa->ike_sa_id);
- if (sa->initiate_mediated(sa, pair->local, pair->remote, waiting_sa->childs) != SUCCESS)
+ if (sa->initiate_mediated(sa, pair->local, pair->remote, waiting_sa->childs,
+ checklist->connect_id) != SUCCESS)
{
SIG(IKE_UP_FAILED, "establishing the mediated connection failed");
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa);
}
/**
+ * Implementation of connect_manager_t.stop_checks.
+ */
+static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id)
+{
+ check_list_t *checklist;
+
+ pthread_mutex_lock(&(this->mutex));
+
+ if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "checklist with id '%B' not found",
+ &connect_id);
+ pthread_mutex_unlock(&(this->mutex));
+ return NOT_FOUND;
+ }
+
+ DBG1(DBG_IKE, "removing checklist with id '%B'", &connect_id);
+
+ remove_checklist(this, checklist);
+ check_list_destroy(checklist);
+
+ pthread_mutex_unlock(&(this->mutex));
+
+ return SUCCESS;
+}
+
+/**
* Implementation of connect_manager_t.destroy.
*/
static void destroy(private_connect_manager_t *this)
this->public.set_initiator_data = (status_t(*)(connect_manager_t*,identification_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))set_initiator_data;
this->public.set_responder_data = (status_t(*)(connect_manager_t*,chunk_t,chunk_t,linked_list_t*))set_responder_data;
this->public.process_check = (void(*)(connect_manager_t*,message_t*))process_check;
+ this->public.stop_checks = (status_t(*)(connect_manager_t*,chunk_t))stop_checks;
this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (this->hasher == NULL)
/*
- * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2007-2008 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
status_t (*set_responder_data) (connect_manager_t *this,
chunk_t connect_id, chunk_t key, linked_list_t *endpoints);
+ /**
+ * Stops checks for a checklist. Used after the responder received an IKE_SA_INIT
+ * request which contains a ME_CONNECTID payload.
+ *
+ * @param connect_id the connect ID
+ * @returns
+ * - NOT_FOUND, if the checklist has not been found
+ * - SUCCESS, otherwise
+ */
+ status_t (*stop_checks) (connect_manager_t *this, chunk_t connect_id);
/**
* Processes a connectivity check
/*
- * Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Server reflexive host
*/
host_t *server_reflexive_host;
+
+ /**
+ * Connect ID
+ */
+ chunk_t connect_id;
#endif /* ME */
/**
}
/**
+ * Implementation of ike_sa_t.get_connect_id.
+ */
+static chunk_t get_connect_id(private_ike_sa_t *this)
+{
+ return this->connect_id;
+}
+
+/**
* Implementation of ike_sa_t.respond
*/
static status_t respond(private_ike_sa_t *this, identification_t *peer_id,
* Implementation of ike_sa_t.initiate_mediated
*/
static status_t initiate_mediated(private_ike_sa_t *this, host_t *me, host_t *other,
- linked_list_t *childs)
+ linked_list_t *childs, chunk_t connect_id)
{
this->my_host = me->clone(me);
this->other_host = other->clone(other);
+ this->connect_id = chunk_clone(connect_id);
task_t *task;
child_cfg_t *child_cfg;
charon->mediation_manager->remove(charon->mediation_manager, this->ike_sa_id);
}
DESTROY_IF(this->server_reflexive_host);
+ chunk_free(&this->connect_id);
#endif /* ME */
DESTROY_IF(this->my_host);
#ifdef ME
this->public.get_server_reflexive_host = (host_t* (*)(ike_sa_t*)) get_server_reflexive_host;
this->public.set_server_reflexive_host = (void (*)(ike_sa_t*,host_t*)) set_server_reflexive_host;
+ this->public.get_connect_id = (chunk_t (*)(ike_sa_t*)) get_connect_id;
this->public.initiate_mediation = (status_t (*)(ike_sa_t*,peer_cfg_t*)) initiate_mediation;
- this->public.initiate_mediated = (status_t (*)(ike_sa_t*,host_t*,host_t*,linked_list_t*)) initiate_mediated;
+ this->public.initiate_mediated = (status_t (*)(ike_sa_t*,host_t*,host_t*,linked_list_t*,chunk_t)) initiate_mediated;
this->public.relay = (status_t (*)(ike_sa_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool)) relay;
this->public.callback = (status_t (*)(ike_sa_t*,identification_t*)) callback;
this->public.respond = (status_t (*)(ike_sa_t*,identification_t*,chunk_t)) respond;
this->ike_initiator = FALSE;
#ifdef ME
this->server_reflexive_host = NULL;
+ this->connect_id = chunk_empty;
#endif /* ME */
return &this->public;
/*
- * Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
void (*set_server_reflexive_host) (ike_sa_t *this, host_t *host);
/**
+ * Get the connect ID.
+ *
+ * @return connect ID
+ */
+ chunk_t (*get_connect_id) (ike_sa_t *this);
+
+ /**
* Initiate the mediation of a mediated connection (i.e. initiate a
* ME_CONNECT exchange).
*
* @param me local endpoint (gets cloned)
* @param other remote endpoint (gets cloned)
* @param childs linked list of child_cfg_t of CHILD_SAs (gets cloned)
+ * @param connect_id connect ID (gets cloned)
* @return
* - SUCCESS if initialization started
* - DESTROY_ME if initialization failed
*/
status_t (*initiate_mediated) (ike_sa_t *this, host_t *me, host_t *other,
- linked_list_t *childs);
+ linked_list_t *childs, chunk_t connect_id);
/**
* Relay data from one peer to another (i.e. initiate a
/*
+ * Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
}
build_payloads(this, message);
-
+
+#ifdef ME
+ {
+ chunk_t connect_id = this->ike_sa->get_connect_id(this->ike_sa);
+ if (connect_id.ptr)
+ {
+ message->add_notify(message, FALSE, ME_CONNECTID, connect_id);
+ }
+ }
+#endif /* ME */
return NEED_MORE;
}
}
randomizer->destroy(randomizer);
+#ifdef ME
+ {
+ chunk_t connect_id = chunk_empty;
+ iterator_t *iterator;
+ payload_t *payload;
+
+ /* check for a ME_CONNECTID notify */
+ iterator = message->get_payload_iterator(message);
+ while (iterator->iterate(iterator, (void**)&payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+ notify_type_t type = notify->get_notify_type(notify);
+
+ switch (type)
+ {
+ case ME_CONNECTID:
+ {
+ chunk_free(&connect_id);
+ connect_id = chunk_clone(notify->get_notification_data(notify));
+ DBG2(DBG_IKE, "received ME_CONNECTID %#B", &connect_id);
+ break;
+ }
+ default:
+ {
+ if (type < 16383)
+ {
+ DBG1(DBG_IKE, "received %N notify error",
+ notify_type_names, type);
+ break;
+ }
+ DBG1(DBG_IKE, "received %N notify",
+ notify_type_names, type);
+ break;
+ }
+ }
+ }
+ }
+ iterator->destroy(iterator);
+
+ if (connect_id.ptr)
+ {
+ charon->connect_manager->stop_checks(charon->connect_manager,
+ connect_id);
+ chunk_free(&connect_id);
+ }
+ }
+#endif /* ME */
+
process_payloads(this, message);
return NEED_MORE;