diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 20bbd06af..cdc5a4357 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -143,6 +143,11 @@ struct private_ike_sa_t { host_t *other_host; #ifdef ME + /** + * Are we mediation server + */ + bool is_mediation_server; + /** * Server reflexive host */ @@ -931,6 +936,16 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request, } #ifdef ME +/** + * Implementation of ike_sa_t.act_as_mediation_server. + */ +static void act_as_mediation_server(private_ike_sa_t *this) +{ + charon->mediation_manager->update_sa_id(charon->mediation_manager, + this->other_id, this->ike_sa_id); + this->is_mediation_server = TRUE; +} + /** * Implementation of ike_sa_t.get_server_reflexive_host. */ @@ -2127,6 +2142,18 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other) { send_keepalive(this); } + +#ifdef ME + if (other->is_mediation_server) + { + act_as_mediation_server(this); + } + else if (other->server_reflexive_host) + { + this->server_reflexive_host = other->server_reflexive_host->clone( + other->server_reflexive_host); + } +#endif /* ME */ /* adopt all children */ while (other->child_sas->remove_last(other->child_sas, @@ -2332,10 +2359,8 @@ static void destroy(private_ike_sa_t *this) this->additional_addresses->destroy_offset(this->additional_addresses, offsetof(host_t, destroy)); #ifdef ME - if (this->peer_cfg && this->peer_cfg->is_mediation(this->peer_cfg) && - !this->ike_sa_id->is_initiator(this->ike_sa_id)) + if (this->is_mediation_server) { - /* mediation server */ charon->mediation_manager->remove(charon->mediation_manager, this->ike_sa_id); } DESTROY_IF(this->server_reflexive_host); @@ -2427,6 +2452,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip; this->public.add_dns_server = (void (*)(ike_sa_t*,host_t*))add_dns_server; #ifdef ME + this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server; 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; @@ -2474,6 +2500,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->keyingtry = 0; this->ike_initiator = FALSE; #ifdef ME + this->is_mediation_server = FALSE; this->server_reflexive_host = NULL; this->connect_id = chunk_empty; #endif /* ME */ diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index 00dbcd397..58e6e01ba 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -435,6 +435,11 @@ struct ike_sa_t { void (*set_pending_updates)(ike_sa_t *this, u_int32_t updates); #ifdef ME + /** + * Activate mediation server functionality for this IKE_SA. + */ + void (*act_as_mediation_server) (ike_sa_t *this); + /** * Get the server reflexive host. * diff --git a/src/charon/sa/tasks/ike_me.c b/src/charon/sa/tasks/ike_me.c index 44f5c9f21..4d70a9cff 100644 --- a/src/charon/sa/tasks/ike_me.c +++ b/src/charon/sa/tasks/ike_me.c @@ -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 @@ -480,9 +480,7 @@ static status_t process_i(private_ike_me_t *this, message_t *message) if (this->failed) { DBG1(DBG_IKE, "peer '%D' is not online", this->peer_id); - /* FIXME: notify the mediated connection (job?) - * FIXME: probably delete the created checklist, at least as - * responder */ + /* FIXME: notify the mediated connection (job?) */ } else { @@ -501,6 +499,8 @@ static status_t process_i(private_ike_me_t *this, message_t *message) this->ike_sa->get_my_id(this->ike_sa), this->peer_id, this->connect_id, this->connect_key, this->local_endpoints, TRUE); + /* FIXME: also start a timer for the whole transaction (maybe + * within the connect_manager?) */ } } break; @@ -646,10 +646,8 @@ static status_t build_r_ms(private_ike_me_t *this, message_t *message) endpoint->destroy(endpoint); } - /* FIXME: we must delete any existing IKE_SAs */ - charon->mediation_manager->update_sa_id(charon->mediation_manager, - this->ike_sa->get_other_id(this->ike_sa), - this->ike_sa->get_id(this->ike_sa)); + /* FIXME: we actually must delete any existing IKE_SAs with the same remote id */ + this->ike_sa->act_as_mediation_server(this->ike_sa); SIG(CHILD_UP_SUCCESS, "established mediation connection without CHILD_SA successfully"); @@ -700,6 +698,10 @@ static status_t build_r_ms(private_ike_me_t *this, message_t *message) */ static status_t process_i_ms(private_ike_me_t *this, message_t *message) { + /* FIXME: theoretically we should be prepared to receive a ME_CONNECT_FAILED + * here if the responding peer is not able to proceed. in this case we shall + * notify the initiating peer with a ME_CONNECT request containing only a + * ME_CONNECT_FAILED */ return SUCCESS; }