ikev2: Properly keep track of pending MOBIKE updates
authorTobias Brunner <tobias@strongswan.org>
Tue, 22 Jul 2014 16:25:37 +0000 (18:25 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 12 Sep 2014 08:29:36 +0000 (10:29 +0200)
Because we only queue one MOBIKE task at a time, but destroy superfluous
ones only after we already increased the counter for pending MOBIKE updates,
we have to reduce the counter when such tasks are destroyed.  Otherwise, the
queued task would assume another task is queued when it is running and
ignore any successful response.

src/libcharon/sa/ikev2/tasks/ike_mobike.c

index 00ca615..a514113 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2012 Tobias Brunner
+ * Copyright (C) 2010-2014 Tobias Brunner
  * Copyright (C) 2007 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -77,6 +77,11 @@ struct private_ike_mobike_t {
         * additional addresses got updated
         */
        bool addresses_updated;
+
+       /**
+        * whether the pending updates counter was increased
+        */
+       bool pending_update;
 };
 
 /**
@@ -481,9 +486,7 @@ METHOD(task_t, process_i, status_t,
        }
        else if (message->get_exchange_type(message) == INFORMATIONAL)
        {
-               u_int32_t updates = this->ike_sa->get_pending_updates(this->ike_sa) - 1;
-               this->ike_sa->set_pending_updates(this->ike_sa, updates);
-               if (updates > 0)
+               if (this->ike_sa->get_pending_updates(this->ike_sa) > 1)
                {
                        /* newer update queued, ignore this one */
                        return SUCCESS;
@@ -560,7 +563,6 @@ METHOD(task_t, process_i, status_t,
                                        this->natd = ike_natd_create(this->ike_sa, this->initiator);
                                }
                                this->check = FALSE;
-                               this->ike_sa->set_pending_updates(this->ike_sa, 1);
                                return NEED_MORE;
                        }
                }
@@ -573,8 +575,12 @@ METHOD(ike_mobike_t, addresses, void,
           private_ike_mobike_t *this)
 {
        this->address = TRUE;
-       this->ike_sa->set_pending_updates(this->ike_sa,
+       if (!this->pending_update)
+       {
+               this->pending_update = TRUE;
+               this->ike_sa->set_pending_updates(this->ike_sa,
                                                this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+       }
 }
 
 METHOD(ike_mobike_t, roam, void,
@@ -582,8 +588,12 @@ METHOD(ike_mobike_t, roam, void,
 {
        this->check = TRUE;
        this->address = address;
-       this->ike_sa->set_pending_updates(this->ike_sa,
+       if (!this->pending_update)
+       {
+               this->pending_update = TRUE;
+               this->ike_sa->set_pending_updates(this->ike_sa,
                                                this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+       }
 }
 
 METHOD(ike_mobike_t, dpd, void,
@@ -593,8 +603,12 @@ METHOD(ike_mobike_t, dpd, void,
        {
                this->natd = ike_natd_create(this->ike_sa, this->initiator);
        }
-       this->ike_sa->set_pending_updates(this->ike_sa,
+       if (!this->pending_update)
+       {
+               this->pending_update = TRUE;
+               this->ike_sa->set_pending_updates(this->ike_sa,
                                                this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+       }
 }
 
 METHOD(ike_mobike_t, is_probing, bool,
@@ -623,6 +637,11 @@ METHOD(task_t, migrate, void,
 METHOD(task_t, destroy, void,
           private_ike_mobike_t *this)
 {
+       if (this->pending_update)
+       {
+               this->ike_sa->set_pending_updates(this->ike_sa,
+                                               this->ike_sa->get_pending_updates(this->ike_sa) - 1);
+       }
        chunk_free(&this->cookie2);
        if (this->natd)
        {