Defer CHILD_SA rekeying if allocating an SPI fails
authorMartin Willi <martin@revosec.ch>
Wed, 3 Apr 2013 10:16:27 +0000 (12:16 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 3 Apr 2013 10:25:27 +0000 (12:25 +0200)
src/libcharon/sa/ikev2/task_manager_v2.c
src/libcharon/sa/ikev2/tasks/child_rekey.c

index a53c06b..5298abf 100644 (file)
@@ -475,6 +475,7 @@ METHOD(task_manager_t, initiate, status_t,
                                break;
                        case FAILED:
                        default:
+                               this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
                                if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
                                {
                                        charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
index f8c2ed1..262cb10 100644 (file)
@@ -87,6 +87,24 @@ struct private_child_rekey_t {
 };
 
 /**
+ * Schedule a retry if rekeying temporary failed
+ */
+static void schedule_delayed_rekey(private_child_rekey_t *this)
+{
+       u_int32_t retry;
+       job_t *job;
+
+       retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
+       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);
+       lib->scheduler->schedule_job(lib->scheduler, job, retry);
+}
+
+/**
  * Implementation of task_t.build for initiator, after rekeying
  */
 static status_t build_i_delete(private_child_rekey_t *this, message_t *message)
@@ -166,8 +184,13 @@ METHOD(task_t, build_i, status_t,
        }
        reqid = this->child_sa->get_reqid(this->child_sa);
        this->child_create->use_reqid(this->child_create, reqid);
-       this->child_create->task.build(&this->child_create->task, message);
 
+       if (this->child_create->task.build(&this->child_create->task,
+                                                                          message) != NEED_MORE)
+       {
+               schedule_delayed_rekey(this);
+               return FAILED;
+       }
        this->child_sa->set_state(this->child_sa, CHILD_REKEYING);
 
        return NEED_MORE;
@@ -316,17 +339,7 @@ METHOD(task_t, process_i, status_t,
                if (!(this->collision &&
                          this->collision->get_type(this->collision) == TASK_CHILD_DELETE))
                {
-                       job_t *job;
-                       u_int32_t retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
-
-                       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);
-                       lib->scheduler->schedule_job(lib->scheduler, job, retry);
+                       schedule_delayed_rekey(this);
                }
                return SUCCESS;
        }