summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/ikev1/task_manager_v1.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ikev1/task_manager_v1.c')
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c100
1 files changed, 61 insertions, 39 deletions
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index 3c601a4fa..b0c4f5f84 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2007-2015 Tobias Brunner
+ * Copyright (C) 2007-2016 Tobias Brunner
* Copyright (C) 2007-2011 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -67,7 +67,7 @@ struct exchange_t {
/**
* Message ID used for this transaction
*/
- u_int32_t mid;
+ uint32_t mid;
/**
* generated packet for retransmission
@@ -104,12 +104,12 @@ struct private_task_manager_t {
/**
* Message ID of the last response
*/
- u_int32_t mid;
+ uint32_t mid;
/**
* Hash of a previously received message
*/
- u_int32_t hash;
+ uint32_t hash;
/**
* packet(s) for retransmission
@@ -119,7 +119,7 @@ struct private_task_manager_t {
/**
* Sequence number of the last sent message
*/
- u_int32_t seqnr;
+ uint32_t seqnr;
/**
* how many times we have retransmitted so far
@@ -135,12 +135,12 @@ struct private_task_manager_t {
/**
* Message ID of the exchange
*/
- u_int32_t mid;
+ uint32_t mid;
/**
* Hashes of old responses we can ignore
*/
- u_int32_t old_hashes[MAX_OLD_HASHES];
+ uint32_t old_hashes[MAX_OLD_HASHES];
/**
* Position in old hash array
@@ -150,7 +150,7 @@ struct private_task_manager_t {
/**
* Sequence number of the last sent message
*/
- u_int32_t seqnr;
+ uint32_t seqnr;
/**
* how many times we have retransmitted so far
@@ -212,12 +212,12 @@ struct private_task_manager_t {
/**
* Sequence number for sending DPD requests
*/
- u_int32_t dpd_send;
+ uint32_t dpd_send;
/**
* Sequence number for received DPD requests
*/
- u_int32_t dpd_recv;
+ uint32_t dpd_recv;
};
/**
@@ -341,11 +341,11 @@ static bool generate_message(private_task_manager_t *this, message_t *message,
/**
* Retransmit a packet (or its fragments)
*/
-static status_t retransmit_packet(private_task_manager_t *this, u_int32_t seqnr,
+static status_t retransmit_packet(private_task_manager_t *this, uint32_t seqnr,
u_int mid, u_int retransmitted, array_t *packets)
{
packet_t *packet;
- u_int32_t t;
+ uint32_t t;
array_get(packets, 0, &packet);
if (retransmitted > this->retransmit_tries)
@@ -354,14 +354,15 @@ static status_t retransmit_packet(private_task_manager_t *this, u_int32_t seqnr,
charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_TIMEOUT, packet);
return DESTROY_ME;
}
- t = (u_int32_t)(this->retransmit_timeout * 1000.0 *
+ t = (uint32_t)(this->retransmit_timeout * 1000.0 *
pow(this->retransmit_base, retransmitted));
if (retransmitted)
{
DBG1(DBG_IKE, "sending retransmit %u of %s message ID %u, seq %u",
retransmitted, seqnr < RESPONDING_SEQ ? "request" : "response",
mid, seqnr < RESPONDING_SEQ ? seqnr : seqnr - RESPONDING_SEQ);
- charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet);
+ charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet,
+ retransmitted);
}
send_packets(this, packets);
lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
@@ -370,7 +371,7 @@ static status_t retransmit_packet(private_task_manager_t *this, u_int32_t seqnr,
}
METHOD(task_manager_t, retransmit, status_t,
- private_task_manager_t *this, u_int32_t seqnr)
+ private_task_manager_t *this, uint32_t seqnr)
{
status_t status = SUCCESS;
@@ -514,26 +515,26 @@ METHOD(task_manager_t, initiate, status_t,
new_mid = TRUE;
break;
}
- if (!mode_config_expected(this) &&
- activate_task(this, TASK_QUICK_MODE))
+ if (activate_task(this, TASK_ISAKMP_DELETE))
{
- exchange = QUICK_MODE;
+ exchange = INFORMATIONAL_V1;
new_mid = TRUE;
break;
}
- if (activate_task(this, TASK_INFORMATIONAL))
+ if (activate_task(this, TASK_QUICK_DELETE))
{
exchange = INFORMATIONAL_V1;
new_mid = TRUE;
break;
}
- if (activate_task(this, TASK_QUICK_DELETE))
+ if (!mode_config_expected(this) &&
+ activate_task(this, TASK_QUICK_MODE))
{
- exchange = INFORMATIONAL_V1;
+ exchange = QUICK_MODE;
new_mid = TRUE;
break;
}
- if (activate_task(this, TASK_ISAKMP_DELETE))
+ if (activate_task(this, TASK_INFORMATIONAL))
{
exchange = INFORMATIONAL_V1;
new_mid = TRUE;
@@ -807,7 +808,7 @@ static void send_notify(private_task_manager_t *this, message_t *request,
message_t *response;
array_t *packets = NULL;
host_t *me, *other;
- u_int32_t mid;
+ uint32_t mid;
if (request->get_exchange_type(request) == INFORMATIONAL_V1)
{ /* don't respond to INFORMATIONAL requests to avoid a notify war */
@@ -857,7 +858,7 @@ static bool process_dpd(private_task_manager_t *this, message_t *message)
{
notify_payload_t *notify;
notify_type_t type;
- u_int32_t seq;
+ uint32_t seq;
chunk_t data;
type = DPD_R_U_THERE;
@@ -910,7 +911,7 @@ static bool process_dpd(private_task_manager_t *this, message_t *message)
* Check if we already have a quick mode task queued for the exchange with the
* given message ID
*/
-static bool have_quick_mode_task(private_task_manager_t *this, u_int32_t mid)
+static bool have_quick_mode_task(private_task_manager_t *this, uint32_t mid)
{
enumerator_t *enumerator;
quick_mode_t *qm;
@@ -935,9 +936,9 @@ static bool have_quick_mode_task(private_task_manager_t *this, u_int32_t mid)
}
/**
- * Check if we still have an aggressive mode task queued
+ * Check if we still have a specific task queued
*/
-static bool have_aggressive_mode_task(private_task_manager_t *this)
+static bool have_task_queued(private_task_manager_t *this, task_type_t type)
{
enumerator_t *enumerator;
task_t *task;
@@ -946,7 +947,7 @@ static bool have_aggressive_mode_task(private_task_manager_t *this)
enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
while (enumerator->enumerate(enumerator, &task))
{
- if (task->get_type(task) == TASK_AGGRESSIVE_MODE)
+ if (task->get_type(task) == type)
{
found = TRUE;
break;
@@ -1180,6 +1181,12 @@ static status_t process_response(private_task_manager_t *this,
}
enumerator->destroy(enumerator);
+ if (this->initiating.retransmitted)
+ {
+ packet_t *packet = NULL;
+ array_get(this->initiating.packets, 0, &packet);
+ charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_CLEARED, packet);
+ }
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
clear_packets(this->initiating.packets);
@@ -1305,7 +1312,7 @@ static status_t queue_message(private_task_manager_t *this, message_t *msg)
METHOD(task_manager_t, process_message, status_t,
private_task_manager_t *this, message_t *msg)
{
- u_int32_t hash, mid, i;
+ uint32_t hash, mid, i;
host_t *me, *other;
status_t status;
@@ -1405,7 +1412,7 @@ METHOD(task_manager_t, process_message, status_t,
/* drop XAuth/Mode Config/Quick Mode messages until we received the last
* Aggressive Mode message. since Informational messages are not
* retransmitted we queue them. */
- if (have_aggressive_mode_task(this))
+ if (have_task_queued(this, TASK_AGGRESSIVE_MODE))
{
if (msg->get_exchange_type(msg) == INFORMATIONAL_V1)
{
@@ -1427,6 +1434,13 @@ METHOD(task_manager_t, process_message, status_t,
return queue_message(this, msg);
}
+ /* some peers send INITIAL_CONTACT notifies during XAuth, cache it */
+ if (have_task_queued(this, TASK_XAUTH) &&
+ msg->get_exchange_type(msg) == INFORMATIONAL_V1)
+ {
+ return queue_message(this, msg);
+ }
+
msg->set_request(msg, TRUE);
charon->bus->message(charon->bus, msg, TRUE, FALSE);
status = parse_message(this, msg);
@@ -1499,8 +1513,8 @@ static bool has_queued(private_task_manager_t *this, task_type_t type)
return found;
}
-METHOD(task_manager_t, queue_task, void,
- private_task_manager_t *this, task_t *task)
+METHOD(task_manager_t, queue_task_delayed, void,
+ private_task_manager_t *this, task_t *task, uint32_t delay)
{
task_type_t type = task->get_type(task);
@@ -1521,6 +1535,12 @@ METHOD(task_manager_t, queue_task, void,
this->queued_tasks->insert_last(this->queued_tasks, task);
}
+METHOD(task_manager_t, queue_task, void,
+ private_task_manager_t *this, task_t *task)
+{
+ queue_task_delayed(this, task, 0);
+}
+
METHOD(task_manager_t, queue_ike, void,
private_task_manager_t *this)
{
@@ -1660,7 +1680,7 @@ METHOD(task_manager_t, queue_mobike, void,
}
METHOD(task_manager_t, queue_child, void,
- private_task_manager_t *this, child_cfg_t *cfg, u_int32_t reqid,
+ private_task_manager_t *this, child_cfg_t *cfg, uint32_t reqid,
traffic_selector_t *tsi, traffic_selector_t *tsr)
{
quick_mode_t *task;
@@ -1739,7 +1759,7 @@ static traffic_selector_t* get_first_ts(child_sa_t *child_sa, bool local)
}
METHOD(task_manager_t, queue_child_rekey, void,
- private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi)
+ private_task_manager_t *this, protocol_id_t protocol, uint32_t spi)
{
child_sa_t *child_sa;
child_cfg_t *cfg;
@@ -1754,6 +1774,7 @@ METHOD(task_manager_t, queue_child_rekey, void,
{
if (is_redundant(this, child_sa))
{
+ child_sa->set_state(child_sa, CHILD_REKEYED);
queue_task(this, (task_t*)quick_delete_create(this->ike_sa,
protocol, spi, FALSE, FALSE));
}
@@ -1774,7 +1795,7 @@ METHOD(task_manager_t, queue_child_rekey, void,
}
METHOD(task_manager_t, queue_child_delete, void,
- private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi,
+ private_task_manager_t *this, protocol_id_t protocol, uint32_t spi,
bool expired)
{
queue_task(this, (task_t*)quick_delete_create(this->ike_sa, protocol,
@@ -1785,7 +1806,7 @@ METHOD(task_manager_t, queue_dpd, void,
private_task_manager_t *this)
{
peer_cfg_t *peer_cfg;
- u_int32_t t, retransmit;
+ uint32_t t, retransmit;
queue_task(this, (task_t*)isakmp_dpd_create(this->ike_sa, DPD_R_U_THERE,
this->dpd_send++));
@@ -1798,7 +1819,7 @@ METHOD(task_manager_t, queue_dpd, void,
/* use the same timeout as a retransmitting IKE message would have */
for (retransmit = 0; retransmit <= this->retransmit_tries; retransmit++)
{
- t += (u_int32_t)(this->retransmit_timeout * 1000.0 *
+ t += (uint32_t)(this->retransmit_timeout * 1000.0 *
pow(this->retransmit_base, retransmit));
}
}
@@ -1871,7 +1892,7 @@ METHOD(task_manager_t, incr_mid, void,
}
METHOD(task_manager_t, reset, void,
- private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
+ private_task_manager_t *this, uint32_t initiate, uint32_t respond)
{
enumerator_t *enumerator;
task_t *task;
@@ -1960,6 +1981,7 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
.task_manager = {
.process_message = _process_message,
.queue_task = _queue_task,
+ .queue_task_delayed = _queue_task_delayed,
.queue_ike = _queue_ike,
.queue_ike_rekey = _queue_ike_rekey,
.queue_ike_reauth = _queue_ike_reauth,