fixed some rekey collision issues
authorMartin Willi <martin@strongswan.org>
Wed, 21 Mar 2007 16:11:14 +0000 (16:11 -0000)
committerMartin Willi <martin@strongswan.org>
Wed, 21 Mar 2007 16:11:14 +0000 (16:11 -0000)
added retry with jitter when rekeying fails

src/charon/config/configuration.c
src/charon/config/configuration.h
src/charon/sa/task_manager.c
src/charon/sa/tasks/child_rekey.c
src/charon/sa/tasks/ike_rekey.c

index f43afda..bed0f63 100755 (executable)
  */
 #define KEEPALIVE_INTERVAL 20
 
+/**
+ * retry interval in seconds.
+ */
+#define RETRY_INTERVAL 15
+
+/**
+ * jitter to user for retrying
+ */
+#define RETRY_JITTER 5
+
 
 typedef struct private_configuration_t private_configuration_t;
 
@@ -119,6 +129,14 @@ static u_int32_t get_keepalive_interval (private_configuration_t *this)
 }
 
 /**
+ * Implementation of configuration_t.get_retry_interval.
+ */
+static u_int32_t get_retry_interval (private_configuration_t *this)
+{
+       return RETRY_INTERVAL - (random() % RETRY_JITTER);
+}
+
+/**
  * Implementation of configuration_t.destroy.
  */
 static void destroy(private_configuration_t *this)
@@ -138,6 +156,7 @@ configuration_t *configuration_create()
        this->public.get_retransmit_timeout = (u_int32_t (*) (configuration_t*,u_int32_t))get_retransmit_timeout;
        this->public.get_half_open_ike_sa_timeout = (u_int32_t (*) (configuration_t*)) get_half_open_ike_sa_timeout;
        this->public.get_keepalive_interval = (u_int32_t (*) (configuration_t*)) get_keepalive_interval;
+       this->public.get_retry_interval = (u_int32_t (*) (configuration_t*)) get_retry_interval;
        
        return (&this->public);
 }
index 77d1fd8..c120717 100755 (executable)
@@ -61,17 +61,28 @@ struct configuration_t {
        u_int32_t (*get_half_open_ike_sa_timeout) (configuration_t *this);
 
        /**
-        * @brief Returns the keepalive interval in ms.
+        * @brief Returns the keepalive interval in s.
         * 
         * The keepalive interval defines the idle time after which a
         * NAT keepalive packet should be sent.
         * 
         * @param this                          calling object
-        * @return                                      interval in seconds
+        * @return                                      interval in s
         */     
        u_int32_t (*get_keepalive_interval) (configuration_t *this);
 
        /**
+        * @brief Returns the interval to retry a failed action again.
+        *
+        * In some situations, the protocol may be in a state where processing
+        * is not possible and an action must be retried (e.g. rekeying).
+        * 
+        * @param this                          calling object
+        * @return                                      interval in s
+        */     
+       u_int32_t (*get_retry_interval) (configuration_t *this);
+
+       /**
         * @brief Destroys a configuration_t object.
         * 
         * @param this                                  calling object
index d63c614..8308c14 100644 (file)
@@ -444,43 +444,43 @@ static void handle_collisions(private_task_manager_t *this, task_t *task)
        
        type = task->get_type(task);
        
-       /* check if we have initiated rekeying ourself */
-       if (this->initiating.type != CREATE_CHILD_SA ||
-               (type != IKE_REKEY && type != CHILD_REKEY && type != CHILD_DELETE))
-       {               
-               task->destroy(task);
-               return;
+       /* do we have to check  */
+       if (type == IKE_REKEY || type == CHILD_REKEY ||
+               type == CHILD_DELETE || type == IKE_DELETE)
+       {
+           /* find an exchange collision, and notify these tasks */
+           iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
+           while (iterator->iterate(iterator, (void**)&active))
+           {
+               switch (active->get_type(active))
+               {
+                       case IKE_REKEY:
+                               if (type == IKE_REKEY || type == IKE_DELETE)
+                               {
+                                       ike_rekey_t *rekey = (ike_rekey_t*)active;
+                                       rekey->collide(rekey, task);
+                                       break;
+                               }
+                               continue;
+                       case CHILD_REKEY:
+                               /* TODO: check if it is the SAME child we are talking about! */
+                               if (type == CHILD_REKEY || type == CHILD_DELETE)
+                               {
+                                       child_rekey_t *rekey = (child_rekey_t*)active;
+                                       rekey->collide(rekey, task);
+                                       break;
+                               }
+                               continue;
+                       default:
+                               continue;
+               }
+                   iterator->destroy(iterator);
+               return;
+               }
+               iterator->destroy(iterator);
        }
-    
-    /* find an exchange collision, and notify these tasks */
-    iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
-    while (iterator->iterate(iterator, (void**)&active))
-    {
-       switch (active->get_type(active))
-       {
-               case IKE_REKEY:
-                       if (type == IKE_REKEY || type == IKE_DELETE)
-                       {
-                               ike_rekey_t *rekey = (ike_rekey_t*)active;
-                               rekey->collide(rekey, task);
-                               break;
-                       }
-                       continue;
-               case CHILD_REKEY:
-                       /* TODO: check if it is the SAME child we are talking about! */
-                       if (type == CHILD_REKEY || type == CHILD_DELETE)
-                       {
-                               child_rekey_t *rekey = (child_rekey_t*)active;
-                               rekey->collide(rekey, task);
-                               break;
-                       }
-                       continue;
-               default:
-                       continue;
-       }
-       break;
-    }
-    iterator->destroy(iterator);
+       /* destroy task if not registered in any active task */
+       task->destroy(task);
 }
 
 /**
@@ -633,7 +633,6 @@ static status_t process_request(private_task_manager_t *this,
                                task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
                        }
                        this->passive_tasks->insert_last(this->passive_tasks, task);
-                       
                        break;
                }
                case INFORMATIONAL:
index 3fb4a54..84d10be 100644 (file)
@@ -26,6 +26,7 @@
 #include <daemon.h>
 #include <encoding/payloads/notify_payload.h>
 #include <sa/tasks/child_create.h>
+#include <queues/jobs/rekey_child_sa_job.h>
 
 
 typedef struct private_child_rekey_t private_child_rekey_t;
@@ -165,12 +166,10 @@ static status_t build_r(private_child_rekey_t *this, message_t *message)
        {
                /* rekeying failed, reuse old child */
                this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
-               /* TODO: reschedule rekeying */
                return SUCCESS;
        }
        
        this->child_sa->set_state(this->child_sa, CHILD_REKEYING);
-       
        return SUCCESS;
 }
 
@@ -191,8 +190,17 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
                if (!(this->collision && 
                          this->collision->get_type(this->collision) == CHILD_DELETE))
                {
+                       job_t *job;
+                       u_int32_t retry = charon->configuration->get_retry_interval(
+                                                               charon->configuration);
+                       job = (job_t*)rekey_child_sa_job_create(
+                                                               this->child_sa->get_reqid(this->child_sa),
+                                                               this->child_sa->get_protocol(this->child_sa),
+                                                               this->child_sa->get_spi(this->child_sa, TRUE));
+                       DBG1(DBG_IKE, "CHILD_SA rekeying failed, "
+                                                               "trying again in %d seconds", retry);
                        this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
-                       /* TODO: rescedule rekeying */
+                       charon->event_queue->add_relative(charon->event_queue, job, retry * 1000);
                }
                return SUCCESS;
        }
index 879a3ee..1ed542e 100644 (file)
@@ -27,6 +27,7 @@
 #include <encoding/payloads/notify_payload.h>
 #include <sa/tasks/ike_init.h>
 #include <queues/jobs/delete_ike_sa_job.h>
+#include <queues/jobs/rekey_ike_sa_job.h>
 
 
 typedef struct private_ike_rekey_t private_ike_rekey_t;
@@ -180,8 +181,15 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message)
                if (!(this->collision &&
                        this->collision->get_type(this->collision) == IKE_DELETE))
                {
+                       job_t *job;
+                       u_int32_t retry = charon->configuration->get_retry_interval(
+                                                                       charon->configuration);
+                       job = (job_t*)rekey_ike_sa_job_create(
+                                                                       this->ike_sa->get_id(this->ike_sa), FALSE);
+                       DBG1(DBG_IKE, "IKE_SA rekeying failed, "
+                                                                       "trying again in %d seconds", retry);
                        this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
-                       /* TODO: reschedule rekeying */
+                       charon->event_queue->add_relative(charon->event_queue, job, retry * 1000);
                }
                return SUCCESS;
        }