controller: Use separate callbacks to track termination and initiation of SAs
[strongswan.git] / src / libcharon / control / controller.c
index 3aed414..93ff70b 100644 (file)
@@ -272,6 +272,28 @@ METHOD(listener_t, ike_state_change, bool,
                        }
 #endif /* ME */
                        case IKE_DESTROYING:
+                               return listener_done(this);
+                       default:
+                               break;
+               }
+       }
+       return TRUE;
+}
+
+METHOD(listener_t, ike_state_change_terminate, bool,
+       interface_listener_t *this, ike_sa_t *ike_sa, ike_sa_state_t state)
+{
+       ike_sa_t *target;
+
+       this->lock->lock(this->lock);
+       target = this->ike_sa;
+       this->lock->unlock(this->lock);
+
+       if (target == ike_sa)
+       {
+               switch (state)
+               {
+                       case IKE_DESTROYING:
                                if (ike_sa->get_state(ike_sa) == IKE_DELETING)
                                {       /* proper termination */
                                        this->status = SUCCESS;
@@ -304,10 +326,6 @@ METHOD(listener_t, child_state_change, bool,
                        case CHILD_DESTROYING:
                                switch (child_sa->get_state(child_sa))
                                {
-                                       case CHILD_DELETING:
-                                               /* proper delete */
-                                               this->status = SUCCESS;
-                                               break;
                                        case CHILD_RETRYING:
                                                /* retrying with a different DH group; survive another
                                                 * initiation round */
@@ -331,6 +349,38 @@ METHOD(listener_t, child_state_change, bool,
        return TRUE;
 }
 
+METHOD(listener_t, child_state_change_terminate, bool,
+       interface_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+       child_sa_state_t state)
+{
+       ike_sa_t *target;
+
+       this->lock->lock(this->lock);
+       target = this->ike_sa;
+       this->lock->unlock(this->lock);
+
+       if (target == ike_sa)
+       {
+               switch (state)
+               {
+                       case CHILD_DESTROYING:
+                               switch (child_sa->get_state(child_sa))
+                               {
+                                       case CHILD_DELETING:
+                                               /* proper delete */
+                                               this->status = SUCCESS;
+                                               break;
+                                       default:
+                                               break;
+                               }
+                               return listener_done(this);
+                       default:
+                               break;
+               }
+       }
+       return TRUE;
+}
+
 METHOD(job_t, destroy_job, void,
        interface_job_t *this)
 {
@@ -537,8 +587,8 @@ METHOD(controller_t, terminate_ike, status_t,
        INIT(job,
                .listener = {
                        .public = {
-                               .ike_state_change = _ike_state_change,
-                               .child_state_change = _child_state_change,
+                               .ike_state_change = _ike_state_change_terminate,
+                               .child_state_change = _child_state_change_terminate,
                        },
                        .logger = {
                                .public = {
@@ -639,8 +689,8 @@ METHOD(controller_t, terminate_child, status_t,
        INIT(job,
                .listener = {
                        .public = {
-                               .ike_state_change = _ike_state_change,
-                               .child_state_change = _child_state_change,
+                               .ike_state_change = _ike_state_change_terminate,
+                               .child_state_change = _child_state_change_terminate,
                        },
                        .logger = {
                                .public = {