]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Catch CHILD_SA state changes during acquire
authorMartin Willi <martin@strongswan.org>
Wed, 7 Oct 2009 08:14:18 +0000 (10:14 +0200)
committerMartin Willi <martin@strongswan.org>
Wed, 7 Oct 2009 11:09:59 +0000 (13:09 +0200)
If an acquire fails due to a TS_UNACCEPTABLE or other CHILD_SA only errors,
we have to reset the pending state in the trap manager.

src/charon/sa/trap_manager.c

index c9090250db513b13164b604b8905f763ddc1567c..ec68e94d05b418de726a6878191777e01878ba9d 100644 (file)
@@ -303,37 +303,64 @@ static void acquire(private_trap_manager_t *this, u_int32_t reqid,
 }
 
 /**
- * Implementation of listener_t.ike_state_change
+ * Complete the acquire, if successful or failed
  */
-static bool ike_state_change(trap_listener_t *listener, ike_sa_t *ike_sa,
-                                                        ike_sa_state_t state)
+static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
+                                        child_sa_t *child_sa)
 {
-       private_trap_manager_t *this;
        enumerator_t *enumerator;
        entry_t *entry;
 
-       switch (state)
-       {
-               case IKE_ESTABLISHED:
-               case IKE_DESTROYING:
-                       break;
-               default:
-                       return TRUE;
-       }
-
-       this = listener->traps;
        this->lock->read_lock(this->lock);
        enumerator = this->traps->create_enumerator(this->traps);
        while (enumerator->enumerate(enumerator, &entry))
        {
-               if (entry->pending == ike_sa)
+               if (entry->pending != ike_sa)
+               {
+                       continue;
+               }
+               if (child_sa && child_sa->get_reqid(child_sa) !=
+                                                                       entry->child_sa->get_reqid(entry->child_sa))
                {
-                       entry->pending = NULL;
+                       continue;
                }
+               entry->pending = NULL;
        }
        enumerator->destroy(enumerator);
        this->lock->unlock(this->lock);
-       return TRUE;
+}
+
+/**
+ * Implementation of listener_t.ike_state_change
+ */
+static bool ike_state_change(trap_listener_t *listener, ike_sa_t *ike_sa,
+                                                        ike_sa_state_t state)
+{
+       switch (state)
+       {
+               case IKE_DESTROYING:
+                       complete(listener->traps, ike_sa, NULL);
+                       return TRUE;
+               default:
+                       return TRUE;
+       }
+}
+
+/**
+ * Implementation of listener_t.child_state_change
+ */
+static bool child_state_change(trap_listener_t *listener, ike_sa_t *ike_sa,
+                                                          child_sa_t *child_sa, child_sa_state_t state)
+{
+       switch (state)
+       {
+               case CHILD_INSTALLED:
+               case CHILD_DESTROYING:
+                       complete(listener->traps, ike_sa, child_sa);
+                       return TRUE;
+               default:
+                       return TRUE;
+       }
 }
 
 /**
@@ -368,6 +395,7 @@ trap_manager_t *trap_manager_create()
        this->listener.traps = this;
        memset(&this->listener.listener, 0, sizeof(listener_t));
        this->listener.listener.ike_state_change = (void*)ike_state_change;
+       this->listener.listener.child_state_change = (void*)child_state_change;
        charon->bus->add_listener(charon->bus, &this->listener.listener);
 
        return &this->public;