diff options
-rw-r--r-- | src/charon/sa/connect_manager.c | 31 | ||||
-rw-r--r-- | src/charon/sa/connect_manager.h | 12 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.c | 23 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.h | 12 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_init.c | 62 |
5 files changed, 132 insertions, 8 deletions
diff --git a/src/charon/sa/connect_manager.c b/src/charon/sa/connect_manager.c index c231baaf2..56a7823f4 100644 --- a/src/charon/sa/connect_manager.c +++ b/src/charon/sa/connect_manager.c @@ -1147,7 +1147,8 @@ static job_requeue_t initiate_mediated(initiate_data_t *data) 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); @@ -1493,6 +1494,33 @@ static status_t set_responder_data(private_connect_manager_t *this, } /** + * 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) @@ -1521,6 +1549,7 @@ connect_manager_t *connect_manager_create() 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) diff --git a/src/charon/sa/connect_manager.h b/src/charon/sa/connect_manager.h index 2f121c123..ad6ac946c 100644 --- a/src/charon/sa/connect_manager.h +++ b/src/charon/sa/connect_manager.h @@ -1,5 +1,5 @@ /* - * 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 @@ -92,6 +92,16 @@ struct connect_manager_t { 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 diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index da5f0e0aa..213aa0e14 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -1,5 +1,5 @@ /* - * 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 @@ -147,6 +147,11 @@ struct private_ike_sa_t { * Server reflexive host */ host_t *server_reflexive_host; + + /** + * Connect ID + */ + chunk_t connect_id; #endif /* ME */ /** @@ -943,6 +948,14 @@ static void set_server_reflexive_host(private_ike_sa_t *this, host_t *host) } /** + * 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, @@ -992,10 +1005,11 @@ static status_t initiate_mediation(private_ike_sa_t *this, peer_cfg_t *mediated_ * 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; @@ -2314,6 +2328,7 @@ static void destroy(private_ike_sa_t *this) 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); @@ -2403,8 +2418,9 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) #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; @@ -2448,6 +2464,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->ike_initiator = FALSE; #ifdef ME this->server_reflexive_host = NULL; + this->connect_id = chunk_empty; #endif /* ME */ return &this->public; diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index 33b990703..00dbcd397 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -1,5 +1,5 @@ /* - * 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 @@ -450,6 +450,13 @@ struct ike_sa_t { 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). * @@ -466,12 +473,13 @@ struct ike_sa_t { * @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 diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c index f65969711..384bcedc8 100644 --- a/src/charon/sa/tasks/ike_init.c +++ b/src/charon/sa/tasks/ike_init.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -265,7 +266,16 @@ static status_t build_i(private_ike_init_t *this, message_t *message) } 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; } @@ -290,6 +300,56 @@ static status_t process_r(private_ike_init_t *this, message_t *message) } 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; |