diff options
author | Martin Willi <martin@revosec.ch> | 2012-01-10 19:13:58 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2012-03-20 17:31:36 +0100 |
commit | 1b82eb23a2416583c464b296161d795a87d1d868 (patch) | |
tree | cde12eabb3cf3ac73e17eaaaad8dbb2807ada41d /src | |
parent | 11aadd772291c3c4d392b6457778a94a8e94c7c5 (diff) | |
download | strongswan-1b82eb23a2416583c464b296161d795a87d1d868.tar.bz2 strongswan-1b82eb23a2416583c464b296161d795a87d1d868.tar.xz |
Handle retransmission of DPD exchange, both as initiator and responder
Diffstat (limited to 'src')
-rwxr-xr-x | src/libcharon/sa/ikev1/task_manager_v1.c | 59 |
1 files changed, 37 insertions, 22 deletions
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c index 562a9eb42..a7c088bac 100755 --- a/src/libcharon/sa/ikev1/task_manager_v1.c +++ b/src/libcharon/sa/ikev1/task_manager_v1.c @@ -332,7 +332,7 @@ METHOD(task_manager_t, initiate, status_t, host_t *me, *other; status_t status; exchange_type_t exchange = EXCHANGE_TYPE_UNDEFINED; - bool new_mid = FALSE, expect_response = FALSE, flushed = FALSE; + bool new_mid = FALSE, expect_response = FALSE, flushed = FALSE, keep = FALSE; if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED) { @@ -412,7 +412,6 @@ METHOD(task_manager_t, initiate, status_t, new_mid = TRUE; break; } - if (activate_task(this, TASK_ISAKMP_DPD)) { exchange = INFORMATIONAL_V1; @@ -485,6 +484,11 @@ METHOD(task_manager_t, initiate, status_t, case SUCCESS: /* task completed, remove it */ this->active_tasks->remove_at(this->active_tasks, enumerator); + if (task->get_type(task) == AGGRESSIVE || + task->get_type(task) == QUICK_MODE) + { /* last message of three message exchange */ + keep = TRUE; + } task->destroy(task); continue; case NEED_MORE: @@ -513,10 +517,22 @@ METHOD(task_manager_t, initiate, status_t, } enumerator->destroy(enumerator); - if (this->active_tasks->get_count(this->active_tasks) == 0) + if (this->active_tasks->get_count(this->active_tasks) == 0 && + (exchange == QUICK_MODE || exchange == AGGRESSIVE)) { /* tasks completed, no exchange active anymore */ this->initiating.type = EXCHANGE_TYPE_UNDEFINED; } + if (exchange == INFORMATIONAL_V1) + { + if (message->get_notify(message, DPD_R_U_THERE)) + { + expect_response = TRUE; + } + if (message->get_notify(message, DPD_R_U_THERE_ACK)) + { + keep = TRUE; + } + } if (flushed) { message->destroy(message); @@ -537,15 +553,13 @@ METHOD(task_manager_t, initiate, status_t, } this->initiating.seqnr++; - if (expect_response) + if (expect_response ) { message->destroy(message); return retransmit(this, this->initiating.seqnr); } - if (message->get_exchange_type(message) == QUICK_MODE || - message->get_exchange_type(message) == AGGRESSIVE) - { /* keep the packet for retransmission in quick/aggressive mode. - * The responder might request a retransmission */ + if (keep) + { /* keep the packet for retransmission, the responder might request it */ charon->sender->send(charon->sender, this->initiating.packet->clone(this->initiating.packet)); } @@ -593,20 +607,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request) /* send response along the path the request came in */ message->set_source(message, me->clone(me)); message->set_destination(message, other->clone(other)); - - /* Create new message id for informational exchanges*/ - if (request->get_exchange_type(request) == INFORMATIONAL_V1) - { - u_int32_t message_id; - - this->rng->get_bytes(this->rng, sizeof(message_id), - (void*)&message_id); - message->set_message_id(message, message_id); - } - else - { - message->set_message_id(message, request->get_message_id(request)); - } + message->set_message_id(message, request->get_message_id(request)); message->set_request(message, FALSE); this->responding.mid = request->get_message_id(request); @@ -858,6 +859,12 @@ static status_t process_request(private_task_manager_t *this, } enumerator->destroy(enumerator); + if (dpd && this->initiating.type == INFORMATIONAL_V1) + { /* got a DPD reply, cancel any retransmission */ + this->initiating.type = EXCHANGE_TYPE_UNDEFINED; + DESTROY_IF(this->initiating.packet); + this->initiating.packet = NULL; + } if (send_response) { if (build_response(this, message) != SUCCESS) @@ -1065,6 +1072,14 @@ METHOD(task_manager_t, process_message, status_t, charon->sender->send(charon->sender, this->responding.packet->clone(this->responding.packet)); } + else if (this->initiating.packet && + this->initiating.type == INFORMATIONAL_V1) + { + DBG1(DBG_IKE, "received retransmit of DPD request, " + "retransmitting response"); + charon->sender->send(charon->sender, + this->initiating.packet->clone(this->initiating.packet)); + } else { DBG1(DBG_IKE, "received retransmit of request with ID %u, " |