ikev1: Defer Mode Config push after CHILD adoption and reauth detection
authorMartin Willi <martin@revosec.ch>
Mon, 7 Jul 2014 08:42:11 +0000 (10:42 +0200)
committerMartin Willi <martin@revosec.ch>
Mon, 25 Aug 2014 07:55:44 +0000 (09:55 +0200)
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.

src/libcharon/sa/ikev1/tasks/aggressive_mode.c
src/libcharon/sa/ikev1/tasks/main_mode.c

index 7009ae9..3101ab6 100644 (file)
@@ -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:
index 8a5d9ae..c264dd4 100644 (file)
@@ -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: