aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-02-25 12:08:36 +0100
committerMartin Willi <martin@revosec.ch>2013-02-25 12:12:38 +0100
commite2857be823cb916e0d89d02c08544b7c14b309c8 (patch)
tree6bb3cc9fcf6cb35ad0ddbbe5e8519e7db94434a9 /src
parentcdf75a39e3c6eb5e7e59d831d8b2441d8af08516 (diff)
downloadstrongswan-e2857be823cb916e0d89d02c08544b7c14b309c8.tar.bz2
strongswan-e2857be823cb916e0d89d02c08544b7c14b309c8.tar.xz
For IKEv1 Main Mode, use message hash to detect early retransmissions
As the message ID is zero in all Main Mode messages, it can't be used to detect if we are already processing a given message.
Diffstat (limited to 'src')
-rw-r--r--src/libcharon/sa/ike_sa_manager.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index f45c20a97..a4d7445fa 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -108,9 +108,9 @@ struct entry_t {
identification_t *other_id;
/**
- * message ID currently processing, if any
+ * message ID or hash of currently processing message, -1 if none
*/
- u_int32_t message_id;
+ u_int32_t processing;
};
/**
@@ -139,7 +139,7 @@ static entry_t *entry_create()
INIT(this,
.condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
- .message_id = -1,
+ .processing = -1,
);
return this;
@@ -1160,6 +1160,20 @@ METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*,
return ike_sa;
}
+/**
+ * Get the message ID or message hash to detect early retransmissions
+ */
+static u_int32_t get_message_id_or_hash(message_t *message)
+{
+ /* Use the message ID, or the message hash in IKEv1 Main/Aggressive mode */
+ if (message->get_major_version(message) == IKEV1_MAJOR_VERSION &&
+ message->get_message_id(message) == 0)
+ {
+ return chunk_hash(message->get_packet_data(message));
+ }
+ return message->get_message_id(message);
+}
+
METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
private_ike_sa_manager_t* this, message_t *message)
{
@@ -1235,7 +1249,7 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
entry->checked_out = TRUE;
unlock_single_segment(this, segment);
- entry->message_id = message->get_message_id(message);
+ entry->processing = get_message_id_or_hash(message);
entry->init_hash = hash;
DBG2(DBG_MGR, "created IKE_SA %s[%u]",
@@ -1279,12 +1293,11 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
if (get_entry_by_id(this, id, &entry, &segment) == SUCCESS)
{
- /* only check out in IKEv2 if we are not already processing it */
- if (message->get_request(message) &&
- message->get_message_id(message) == entry->message_id)
+ /* only check out if we are not already processing it. */
+ if (entry->processing == get_message_id_or_hash(message))
{
DBG1(DBG_MGR, "ignoring request with ID %u, already processing",
- entry->message_id);
+ entry->processing);
}
else if (wait_for_entry(this, entry, segment))
{
@@ -1294,7 +1307,7 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
entry->checked_out = TRUE;
if (message->get_first_payload_type(message) != FRAGMENT_V1)
{
- entry->message_id = message->get_message_id(message);
+ entry->processing = get_message_id_or_hash(message);
}
if (ike_id->get_responder_spi(ike_id) == 0)
{
@@ -1553,7 +1566,7 @@ METHOD(ike_sa_manager_t, checkin, void,
entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa));
/* signal waiting threads */
entry->checked_out = FALSE;
- entry->message_id = -1;
+ entry->processing = -1;
/* check if this SA is half-open */
if (entry->half_open && ike_sa->get_state(ike_sa) != IKE_CONNECTING)
{