Support installing of quick mode SAs with a specific reqid
[strongswan.git] / src / libcharon / sa / ikev1 / tasks / quick_mode.c
index df7b637..b9acdb0 100644 (file)
@@ -115,9 +115,9 @@ struct private_quick_mode_t {
        u_int64_t lifebytes;
 
        /**
-        * Notify type in case of error
+        * Reqid to use, 0 for auto-allocate
         */
-       notify_type_t notify_type;
+       u_int32_t reqid;
 
        /** states of quick mode */
        enum {
@@ -557,7 +557,7 @@ METHOD(task_t, build_i, status_t,
                        this->child_sa = child_sa_create(
                                                                        this->ike_sa->get_my_host(this->ike_sa),
                                                                        this->ike_sa->get_other_host(this->ike_sa),
-                                                                       this->config, 0, udp);
+                                                                       this->config, this->reqid, udp);
 
                        list = this->config->get_proposals(this->config, FALSE);
 
@@ -704,10 +704,10 @@ METHOD(task_t, process_r, status_t,
                        }
                        tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
                        tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
-                       if (!this->config)
+                       if (!this->config || !this->tsi || !this->tsr)
                        {
-                               DBG1(DBG_IKE, "no child config found");
-                               return send_notify(this, NO_PROPOSAL_CHOSEN);
+                               DBG1(DBG_IKE, "no matching CHILD_SA config found");
+                               return send_notify(this, INVALID_ID_INFORMATION);
                        }
 
                        sa_payload = (sa_payload_t*)message->get_payload(message,
@@ -758,12 +758,13 @@ METHOD(task_t, process_r, status_t,
                        this->child_sa = child_sa_create(
                                                                        this->ike_sa->get_my_host(this->ike_sa),
                                                                        this->ike_sa->get_other_host(this->ike_sa),
-                                                                       this->config, 0, udp);
+                                                                       this->config, this->reqid, udp);
                        return NEED_MORE;
                }
                case QM_NEGOTIATED:
                {
-                       if (has_notify_errors(this, message))
+                       if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
+                               has_notify_errors(this, message))
                        {
                                return SUCCESS;
                        }
@@ -892,10 +893,39 @@ METHOD(task_t, get_type, task_type_t,
        return TASK_QUICK_MODE;
 }
 
+METHOD(quick_mode_t, use_reqid, void,
+       private_quick_mode_t *this, u_int32_t reqid)
+{
+       this->reqid = reqid;
+}
+
 METHOD(task_t, migrate, void,
        private_quick_mode_t *this, ike_sa_t *ike_sa)
 {
+       chunk_free(&this->nonce_i);
+       chunk_free(&this->nonce_r);
+       DESTROY_IF(this->tsi);
+       DESTROY_IF(this->tsr);
+       DESTROY_IF(this->proposal);
+       DESTROY_IF(this->child_sa);
+       DESTROY_IF(this->dh);
+
        this->ike_sa = ike_sa;
+       this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
+       this->state = QM_INIT;
+       this->tsi = NULL;
+       this->tsr = NULL;
+       this->proposal = NULL;
+       this->child_sa = NULL;
+       this->dh = NULL;
+       this->spi_i = 0;
+       this->spi_r = 0;
+
+       if (!this->initiator)
+       {
+               DESTROY_IF(this->config);
+               this->config = NULL;
+       }
 }
 
 METHOD(task_t, destroy, void,
@@ -927,6 +957,7 @@ quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
                                .migrate = _migrate,
                                .destroy = _destroy,
                        },
+                       .use_reqid = _use_reqid,
                },
                .ike_sa = ike_sa,
                .initiator = config != NULL,