Added possibility to register custom kernel algorithms to kernel interface
authorTobias Brunner <tobias@strongswan.org>
Thu, 13 Sep 2012 12:36:04 +0000 (14:36 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 13 Sep 2012 13:44:47 +0000 (15:44 +0200)
src/libhydra/kernel/kernel_interface.c
src/libhydra/kernel/kernel_interface.h

index 650cb1e..0ee5e1a 100644 (file)
  * for more details.
  */
 
+/*
+ * Copyright (c) 2012 Nanoteq Pty Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include "kernel_interface.h"
 
 #include <debug.h>
 
 typedef struct private_kernel_interface_t private_kernel_interface_t;
 
+typedef struct kernel_algorithm_t kernel_algorithm_t;
+
+/**
+ * Mapping of IKE algorithms to kernel-specific algorithm identifiers
+ */
+struct kernel_algorithm_t {
+
+       /**
+        * Transform type of the algorithm
+        */
+       transform_type_t type;
+
+       /**
+        * Identifier specified in IKE
+        */
+       u_int16_t ike;
+
+       /**
+        * Identifier as defined in pfkeyv2.h
+        */
+       u_int16_t kernel;
+
+       /**
+        * Name of the algorithm in linux crypto API
+        */
+       char *name;
+};
+
 /**
  * Private data of a kernel_interface_t object.
  */
@@ -62,6 +112,16 @@ struct private_kernel_interface_t {
         * list of registered listeners
         */
        linked_list_t *listeners;
+
+       /**
+        * mutex for algorithm mappings
+        */
+       mutex_t *mutex_algs;
+
+       /**
+        * List of algorithm mappings (kernel_algorithm_t*)
+        */
+       linked_list_t *algorithms;
 };
 
 METHOD(kernel_interface_t, get_spi, status_t,
@@ -510,13 +570,72 @@ METHOD(kernel_interface_t, roam, void,
        this->mutex->unlock(this->mutex);
 }
 
+METHOD(kernel_interface_t, register_algorithm, void,
+       private_kernel_interface_t *this, u_int16_t alg_id, transform_type_t type,
+       u_int16_t kernel_id, char *kernel_name)
+{
+       kernel_algorithm_t *algorithm;
+
+       INIT(algorithm,
+               .type = type,
+               .ike = alg_id,
+               .kernel = kernel_id,
+               .name = strdup(kernel_name),
+       );
+
+       this->mutex_algs->lock(this->mutex_algs);
+       this->algorithms->insert_first(this->algorithms, algorithm);
+       this->mutex_algs->unlock(this->mutex_algs);
+}
+
+METHOD(kernel_interface_t, lookup_algorithm, bool,
+       private_kernel_interface_t *this, u_int16_t alg_id, transform_type_t type,
+       u_int16_t *kernel_id, char **kernel_name)
+{
+       kernel_algorithm_t *algorithm;
+       enumerator_t *enumerator;
+       bool found = FALSE;
+
+       this->mutex_algs->lock(this->mutex_algs);
+       enumerator = this->algorithms->create_enumerator(this->algorithms);
+       while (enumerator->enumerate(enumerator, &algorithm))
+       {
+               if (algorithm->type == type && algorithm->ike == alg_id)
+               {
+                       if (kernel_id)
+                       {
+                               *kernel_id = algorithm->kernel;
+                       }
+                       if (kernel_name)
+                       {
+                               *kernel_name = algorithm->name;
+                       }
+                       found = TRUE;
+                       break;
+               }
+       }
+       enumerator->destroy(enumerator);
+       this->mutex_algs->unlock(this->mutex_algs);
+       return found;
+}
+
 METHOD(kernel_interface_t, destroy, void,
        private_kernel_interface_t *this)
 {
+       kernel_algorithm_t *algorithm;
+
+       while (this->algorithms->remove_first(this->algorithms,
+                                                                                (void**)&algorithm) == SUCCESS)
+       {
+               free(algorithm->name);
+               free(algorithm);
+       }
+       this->algorithms->destroy(this->algorithms);
+       this->mutex_algs->destroy(this->mutex_algs);
        DESTROY_IF(this->ipsec);
        DESTROY_IF(this->net);
-       this->mutex->destroy(this->mutex);
        this->listeners->destroy(this->listeners);
+       this->mutex->destroy(this->mutex);
        free(this);
 }
 
@@ -559,6 +678,8 @@ kernel_interface_t *kernel_interface_create()
 
                        .add_listener = _add_listener,
                        .remove_listener = _remove_listener,
+                       .register_algorithm = _register_algorithm,
+                       .lookup_algorithm = _lookup_algorithm,
                        .acquire = _acquire,
                        .expire = _expire,
                        .mapping = _mapping,
@@ -568,6 +689,8 @@ kernel_interface_t *kernel_interface_create()
                },
                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
                .listeners = linked_list_create(),
+               .mutex_algs = mutex_create(MUTEX_TYPE_DEFAULT),
+               .algorithms = linked_list_create(),
        );
 
        return &this->public;
index 37b72f8..a17e8c6 100644 (file)
  * for more details.
  */
 
+/*
+ * Copyright (c) 2012 Nanoteq Pty Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 /**
  * @defgroup kernel_interface kernel_interface
  * @{ @ingroup hkernel
@@ -493,6 +515,32 @@ struct kernel_interface_t {
        void (*roam)(kernel_interface_t *this, bool address);
 
        /**
+        * Register a new algorithm with the kernel interface.
+        *
+        * @param alg_id                        the IKE id of the algorithm
+        * @param type                          the transform type of the algorithm
+        * @param kernel_id                     the kernel id of the algorithm
+        * @param kernel_name           the kernel name of the algorithm
+        */
+       void (*register_algorithm)(kernel_interface_t *this, u_int16_t alg_id,
+                                                          transform_type_t type, u_int16_t kernel_id,
+                                                          char *kernel_name);
+
+       /**
+        * Return the kernel-specific id and/or name for an algorithms depending on
+        * the arguments specified.
+        *
+        * @param alg_id                        the IKE id of the algorithm
+        * @param type                          the transform type of the algorithm
+        * @param kernel_id                     the kernel id of the algorithm (optional)
+        * @param kernel_name           the kernel name of the algorithm (optional)
+        * @return                                      TRUE if algorithm was found
+        */
+       bool (*lookup_algorithm)(kernel_interface_t *this, u_int16_t alg_id,
+                                                        transform_type_t type, u_int16_t *kernel_id,
+                                                        char **kernel_name);
+
+       /**
         * Destroys a kernel_interface_manager_t object.
         */
        void (*destroy) (kernel_interface_t *this);