From: Martin Willi Date: Mon, 7 Jul 2014 08:42:11 +0000 (+0200) Subject: ikev1: Defer Mode Config push after CHILD adoption and reauth detection X-Git-Tag: 5.2.1dr1~97^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=891bbbd4bb8d3ef19e48ecbdb79d8b8a20007749;p=thirdparty%2Fstrongswan.git ikev1: Defer Mode Config push after CHILD adoption and reauth detection When an initiator starts reauthentication on a connection that uses push mode to assign a virtual IP, we can't execute the Mode Config before releasing the virtual IP. Otherwise we would request a new and different lease, which the client probably can't handle. Defer Mode Config execution, so the same IP gets first released then reassigned during reauthentication. --- diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c index 7009ae95d7..3101ab6eeb 100644 --- a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c +++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c @@ -475,6 +475,8 @@ METHOD(task_t, process_r, status_t, } case AM_AUTH: { + adopt_children_job_t *job = NULL; + while (TRUE) { if (this->ph1->verify_auth(this->ph1, this->method, message, @@ -524,9 +526,8 @@ METHOD(task_t, process_r, status_t, { return send_delete(this); } - lib->processor->queue_job(lib->processor, (job_t*) - adopt_children_job_create( - this->ike_sa->get_id(this->ike_sa))); + job = adopt_children_job_create( + this->ike_sa->get_id(this->ike_sa)); break; } /* check for and prepare mode config push/pull */ @@ -542,10 +543,22 @@ METHOD(task_t, process_r, status_t, { if (!this->peer_cfg->use_pull_mode(this->peer_cfg)) { - this->ike_sa->queue_task(this->ike_sa, - (task_t*)mode_config_create(this->ike_sa, TRUE, FALSE)); + if (job) + { + job->queue_task(job, (task_t*) + mode_config_create(this->ike_sa, TRUE, FALSE)); + } + else + { + this->ike_sa->queue_task(this->ike_sa, (task_t*) + mode_config_create(this->ike_sa, TRUE, FALSE)); + } } } + if (job) + { + lib->processor->queue_job(lib->processor, (job_t*)job); + } return SUCCESS; } default: diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c index 8a5d9ae161..c264dd44d0 100644 --- a/src/libcharon/sa/ikev1/tasks/main_mode.c +++ b/src/libcharon/sa/ikev1/tasks/main_mode.c @@ -479,6 +479,7 @@ METHOD(task_t, build_r, status_t, { id_payload_t *id_payload; identification_t *id; + adopt_children_job_t *job = NULL; id = this->ph1->get_id(this->ph1, this->peer_cfg, TRUE); if (!id) @@ -522,9 +523,8 @@ METHOD(task_t, build_r, status_t, { return send_notify(this, AUTHENTICATION_FAILED); } - lib->processor->queue_job(lib->processor, (job_t*) - adopt_children_job_create( - this->ike_sa->get_id(this->ike_sa))); + job = adopt_children_job_create( + this->ike_sa->get_id(this->ike_sa)); break; } if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg)) @@ -539,10 +539,22 @@ METHOD(task_t, build_r, status_t, { if (!this->peer_cfg->use_pull_mode(this->peer_cfg)) { - this->ike_sa->queue_task(this->ike_sa, - (task_t*)mode_config_create(this->ike_sa, TRUE, FALSE)); + if (job) + { + job->queue_task(job, (task_t*) + mode_config_create(this->ike_sa, TRUE, FALSE)); + } + else + { + this->ike_sa->queue_task(this->ike_sa, (task_t*) + mode_config_create(this->ike_sa, TRUE, FALSE)); + } } } + if (job) + { + lib->processor->queue_job(lib->processor, (job_t*)job); + } return SUCCESS; } default: