diff options
Diffstat (limited to 'src/libcharon/sa/ikev2/tasks/child_rekey.c')
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_rekey.c | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c index 761c860e7..b67e9b80f 100644 --- a/src/libcharon/sa/ikev2/tasks/child_rekey.c +++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2016 Tobias Brunner + * Copyright (C) 2009-2017 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * HSR Hochschule fuer Technik Rapperswil @@ -283,7 +283,8 @@ METHOD(task_t, build_r, status_t, /** * Handle a rekey collision */ -static child_sa_t *handle_collision(private_child_rekey_t *this) +static child_sa_t *handle_collision(private_child_rekey_t *this, + child_sa_t **to_install) { child_sa_t *to_delete; @@ -302,8 +303,11 @@ static child_sa_t *handle_collision(private_child_rekey_t *this) { child_sa_t *child_sa; - DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting old child"); + *to_install = this->child_create->get_child(this->child_create); to_delete = this->child_sa; + DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting old child " + "%s{%d}", to_delete->get_name(to_delete), + to_delete->get_unique_id(to_delete)); /* don't touch child other created, it has already been deleted */ if (!this->other_child_destroyed) { @@ -321,9 +325,10 @@ static child_sa_t *handle_collision(private_child_rekey_t *this) } else { - DBG1(DBG_IKE, "CHILD_SA rekey collision lost, " - "deleting rekeyed child"); to_delete = this->child_create->get_child(this->child_create); + DBG1(DBG_IKE, "CHILD_SA rekey collision lost, deleting redundant " + "child %s{%d}", to_delete->get_name(to_delete), + to_delete->get_unique_id(to_delete)); } } else @@ -334,15 +339,17 @@ static child_sa_t *handle_collision(private_child_rekey_t *this) * the CHILD_SA the other is not deleting. */ if (del->get_child(del) != this->child_sa) { - DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, " - "deleting rekeyed child"); to_delete = this->child_sa; + DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, deleting old child " + "%s{%d}", to_delete->get_name(to_delete), + to_delete->get_unique_id(to_delete)); } else { - DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, " - "deleting redundant child"); to_delete = this->child_create->get_child(this->child_create); + DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, deleting redundant " + "child %s{%d}", to_delete->get_name(to_delete), + to_delete->get_unique_id(to_delete)); } } return to_delete; @@ -353,7 +360,7 @@ METHOD(task_t, process_i, status_t, { protocol_id_t protocol; uint32_t spi; - child_sa_t *to_delete; + child_sa_t *to_delete, *to_install = NULL; if (message->get_notify(message, NO_ADDITIONAL_SAS)) { @@ -415,19 +422,48 @@ METHOD(task_t, process_i, status_t, /* check for rekey collisions */ if (this->collision) { - to_delete = handle_collision(this); + to_delete = handle_collision(this, &to_install); } else { + to_install = this->child_create->get_child(this->child_create); to_delete = this->child_sa; } - + if (to_install) + { + if (to_install->install_outbound(to_install) != SUCCESS) + { + DBG1(DBG_IKE, "unable to install outbound IPsec SA (SAD) in kernel"); + charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED, + to_install); + /* FIXME: delete the child_sa? fail the task? */ + } + else + { + linked_list_t *my_ts, *other_ts; + + my_ts = linked_list_create_from_enumerator( + to_install->create_ts_enumerator(to_install, TRUE)); + other_ts = linked_list_create_from_enumerator( + to_install->create_ts_enumerator(to_install, FALSE)); + + DBG0(DBG_IKE, "outbound CHILD_SA %s{%d} established " + "with SPIs %.8x_i %.8x_o and TS %#R === %#R", + to_install->get_name(to_install), + to_install->get_unique_id(to_install), + ntohl(to_install->get_spi(to_install, TRUE)), + ntohl(to_install->get_spi(to_install, FALSE)), + my_ts, other_ts); + + my_ts->destroy(my_ts); + other_ts->destroy(other_ts); + } + } if (to_delete != this->child_create->get_child(this->child_create)) { /* invoke rekey hook if rekeying successful */ charon->bus->child_rekey(charon->bus, this->child_sa, this->child_create->get_child(this->child_create)); } - if (to_delete == NULL) { return SUCCESS; |