controller: Add option to force destruction of an IKE_SA
authorTobias Brunner <tobias@strongswan.org>
Fri, 27 Apr 2018 16:01:54 +0000 (18:01 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 22 May 2018 08:06:07 +0000 (10:06 +0200)
It's optionally possible to wait for a timeout to destroy the SA.

src/charon-nm/nm/nm_service.c
src/conftest/actions.c
src/frontends/android/app/src/main/jni/libandroidbridge/backend/android_service.c
src/frontends/osx/charon-xpc/xpc_channels.c
src/libcharon/control/controller.c
src/libcharon/control/controller.h
src/libcharon/plugins/smp/smp.c
src/libcharon/plugins/stroke/stroke_control.c
src/libcharon/plugins/uci/uci_control.c
src/libcharon/plugins/vici/vici_config.c
src/libcharon/plugins/vici/vici_control.c

index 82e126a..0e7035a 100644 (file)
@@ -741,7 +741,7 @@ static gboolean do_disconnect(gpointer plugin)
                {
                        id = ike_sa->get_unique_id(ike_sa);
                        enumerator->destroy(enumerator);
-                       charon->controller->terminate_ike(charon->controller, id,
+                       charon->controller->terminate_ike(charon->controller, id, FALSE,
                                                                                          controller_cb_empty, NULL, 0);
                        return FALSE;
                }
index 36c3c8e..66e41f7 100644 (file)
@@ -209,7 +209,8 @@ static job_requeue_t close_ike(char *config)
        if (id)
        {
                DBG1(DBG_CFG, "closing IKE_SA '%s'", config);
-               charon->controller->terminate_ike(charon->controller, id, NULL, NULL, 0);
+               charon->controller->terminate_ike(charon->controller, id, FALSE, NULL,
+                                                                                 NULL, 0);
        }
        else
        {
index 806375c..b1a095b 100644 (file)
@@ -401,7 +401,7 @@ static void close_tun_device(private_android_service_t *this)
 CALLBACK(terminate, job_requeue_t,
        uint32_t *id)
 {
-       charon->controller->terminate_ike(charon->controller, *id,
+       charon->controller->terminate_ike(charon->controller, *id, FALSE,
                                                                          controller_cb_empty, NULL, 0);
        return JOB_REQUEUE_NONE;
 }
index 6724841..d013e75 100644 (file)
@@ -131,7 +131,7 @@ static void stop_connection(private_xpc_channels_t *this, uint32_t ike_sa,
 {
        status_t status;
 
-       status = charon->controller->terminate_ike(charon->controller, ike_sa,
+       status = charon->controller->terminate_ike(charon->controller, ike_sa, FALSE,
                                                                                           NULL, NULL, 0);
        xpc_dictionary_set_bool(reply, "success", status != NOT_FOUND);
 }
index 6a37fff..3ff1c4b 100644 (file)
@@ -117,10 +117,17 @@ struct interface_listener_t {
         */
        spinlock_t *lock;
 
-       /**
-        * whether to check limits
-        */
-       bool limits;
+       union {
+               /**
+                * whether to check limits during initiation
+                */
+               bool limits;
+
+               /**
+                * whether to force termination
+                */
+               bool force;
+       } options;
 };
 
 
@@ -423,7 +430,7 @@ METHOD(job_t, initiate_execute, job_requeue_t,
        }
        peer_cfg->destroy(peer_cfg);
 
-       if (listener->limits && ike_sa->get_state(ike_sa) == IKE_CREATED)
+       if (listener->options.limits && ike_sa->get_state(ike_sa) == IKE_CREATED)
        {       /* only check if we are not reusing an IKE_SA */
                u_int half_open, limit_half_open, limit_job_load;
 
@@ -508,7 +515,7 @@ METHOD(controller_t, initiate, status_t,
                        .child_cfg = child_cfg,
                        .peer_cfg = peer_cfg,
                        .lock = spinlock_create(),
-                       .limits = limits,
+                       .options.limits = limits,
                },
                .public = {
                        .execute = _initiate_execute,
@@ -557,8 +564,8 @@ METHOD(job_t, terminate_ike_execute, job_requeue_t,
        listener->ike_sa = ike_sa;
        listener->lock->unlock(listener->lock);
 
-       if (ike_sa->delete(ike_sa, FALSE) != DESTROY_ME)
-       {       /* delete failed */
+       if (ike_sa->delete(ike_sa, listener->options.force) != DESTROY_ME)
+       {       /* delete queued */
                listener->status = FAILED;
                charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
        }
@@ -575,7 +582,7 @@ METHOD(job_t, terminate_ike_execute, job_requeue_t,
 }
 
 METHOD(controller_t, terminate_ike, status_t,
-       controller_t *this, uint32_t unique_id,
+       controller_t *this, uint32_t unique_id, bool force,
        controller_cb_t callback, void *param, u_int timeout)
 {
        interface_job_t *job;
@@ -610,13 +617,24 @@ METHOD(controller_t, terminate_ike, status_t,
 
        if (callback == NULL)
        {
+               job->listener.options.force = force;
                terminate_ike_execute(job);
        }
        else
        {
+               if (!timeout)
+               {
+                       job->listener.options.force = force;
+               }
                if (wait_for_listener(job, timeout))
                {
                        job->listener.status = OUT_OF_RES;
+
+                       if (force)
+                       {       /* force termination once timeout is reached */
+                               job->listener.options.force = TRUE;
+                               terminate_ike_execute(job);
+                       }
                }
        }
        status = job->listener.status;
index 9524f53..7ba7218 100644 (file)
@@ -102,6 +102,11 @@ struct controller_t {
         * until the IKE_SA is properly deleted, or the call timed out.
         *
         * @param unique_id             unique id of the IKE_SA to terminate.
+        * @param force                 whether to immediately destroy the IKE_SA without
+        *                                              waiting for a response or retransmitting the delete,
+        *                                              if a callback is provided and timeout is > 0 the
+        *                                              IKE_SA is destroyed once the timeout is reached but
+        *                                              retransmits are sent until then
         * @param cb                    logging callback
         * @param param                 parameter to include in each call of cb
         * @param timeout               timeout in ms to wait for callbacks, 0 to disable
@@ -112,7 +117,7 @@ struct controller_t {
         *                                              - OUT_OF_RES if timed out
         */
        status_t (*terminate_ike)(controller_t *this, uint32_t unique_id,
-                                                         controller_cb_t callback, void *param,
+                                                         bool force, controller_cb_t callback, void *param,
                                                          u_int timeout);
 
        /**
index 56891b2..d4b01f4 100644 (file)
@@ -415,7 +415,7 @@ static void request_control_terminate(xmlTextReaderPtr reader,
                if (ike)
                {
                        status = charon->controller->terminate_ike(
-                                       charon->controller, id,
+                                       charon->controller, id, FALSE,
                                        (controller_cb_t)xml_callback, writer, 0);
                }
                else
index d3c2791..016f0e7 100644 (file)
@@ -316,7 +316,8 @@ static void charon_terminate(private_stroke_control_t *this, uint32_t id,
                else
                {
                        status = charon->controller->terminate_ike(charon->controller, id,
-                                                       (controller_cb_t)stroke_log, &info, this->timeout);
+                                                       FALSE, (controller_cb_t)stroke_log, &info,
+                                                       this->timeout);
                }
                report_terminate_status(this, status, out, id, child);
        }
@@ -327,7 +328,7 @@ static void charon_terminate(private_stroke_control_t *this, uint32_t id,
        }
        else
        {
-               charon->controller->terminate_ike(charon->controller, id,
+               charon->controller->terminate_ike(charon->controller, id, FALSE,
                                                                                  NULL, NULL, 0);
        }
 }
index a7d26e6..22fd3c2 100644 (file)
@@ -180,7 +180,7 @@ static void terminate(private_uci_control_t *this, char *name)
                {
                        id = ike_sa->get_unique_id(ike_sa);
                        enumerator->destroy(enumerator);
-                       charon->controller->terminate_ike(charon->controller, id,
+                       charon->controller->terminate_ike(charon->controller, id, FALSE,
                                                                                          controller_cb_empty, NULL, 0);
                        write_fifo(this, "connection '%s' terminated\n", name);
                        return;
index 2faa66e..c851615 100644 (file)
@@ -2083,7 +2083,7 @@ static void clear_start_action(private_vici_config_t *this, char *peer_name,
                                while (array_remove(ikeids, ARRAY_HEAD, &id))
                                {
                                        DBG1(DBG_CFG, "closing IKE_SA #%u", id);
-                                       charon->controller->terminate_ike(charon->controller,
+                                       charon->controller->terminate_ike(charon->controller, FALSE,
                                                                                                          id, NULL, NULL, 0);
                                }
                                array_destroy(ikeids);
index f9c7d8f..6824079 100644 (file)
@@ -326,7 +326,7 @@ CALLBACK(terminate, vici_message_t*,
                }
                else
                {
-                       if (charon->controller->terminate_ike(charon->controller, *del,
+                       if (charon->controller->terminate_ike(charon->controller, *del, FALSE,
                                                                                        log_cb, &log, timeout) == SUCCESS)
                        {
                                done++;