summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/ikev1/tasks/quick_mode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ikev1/tasks/quick_mode.c')
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index e6273682d..1133aab65 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -1030,7 +1030,8 @@ METHOD(task_t, process_r, status_t,
}
tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
- if (!this->config || !this->tsi || !this->tsr)
+ if (!this->config || !this->tsi || !this->tsr ||
+ this->mode != this->config->get_mode(this->config))
{
DBG1(DBG_IKE, "no matching CHILD_SA config found");
return send_notify(this, INVALID_ID_INFORMATION);
@@ -1117,11 +1118,22 @@ METHOD(task_t, process_r, status_t,
}
case QM_NEGOTIATED:
{
- if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
- has_notify_errors(this, message))
+ if (has_notify_errors(this, message))
{
return SUCCESS;
}
+ if (message->get_exchange_type(message) == INFORMATIONAL_V1)
+ {
+ if (message->get_payload(message, PLV1_DELETE))
+ {
+ /* If the DELETE for a Quick Mode follows immediately
+ * after rekeying, we might receive it before the
+ * third completing Quick Mode message. Ignore it, as
+ * it gets handled by a separately queued delete task. */
+ return NEED_MORE;
+ }
+ return SUCCESS;
+ }
if (!install(this))
{
ike_sa_t *ike_sa = this->ike_sa;
@@ -1198,6 +1210,14 @@ METHOD(task_t, build_r, status_t,
this->state = QM_NEGOTIATED;
return NEED_MORE;
}
+ case QM_NEGOTIATED:
+ if (message->get_exchange_type(message) == INFORMATIONAL_V1)
+ {
+ /* skip INFORMATIONAL response if we received a INFORMATIONAL
+ * delete, see process_r() */
+ return ALREADY_DONE;
+ }
+ /* fall */
default:
return FAILED;
}