static ENGINE *engine_list_head = NULL;
static ENGINE *engine_list_tail = NULL;
+/*
+ * The linked list of currently loaded dynamic engines.
+ */
+static ENGINE *engine_dyn_list_head = NULL;
+static ENGINE *engine_dyn_list_tail = NULL;
+
/*
* This cleanup function is only needed internally. If it should be called,
* we register it with the "engine_cleanup_int()" stack to be called during
return 1;
}
+/* Add engine to dynamic engine list. */
+int engine_add_dynamic_id(ENGINE *e, ENGINE_DYNAMIC_ID dynamic_id,
+ int not_locked)
+{
+ int result = 0;
+ ENGINE *iterator = NULL;
+
+ if (e == NULL)
+ return 0;
+
+ if (e->dynamic_id == NULL && dynamic_id == NULL)
+ return 0;
+
+ if (not_locked && !CRYPTO_THREAD_write_lock(global_engine_lock))
+ return 0;
+
+ if (dynamic_id != NULL) {
+ iterator = engine_dyn_list_head;
+ while (iterator != NULL) {
+ if (iterator->dynamic_id == dynamic_id)
+ goto err;
+ iterator = iterator->next;
+ }
+ if (e->dynamic_id != NULL)
+ goto err;
+ e->dynamic_id = dynamic_id;
+ }
+
+ if (engine_dyn_list_head == NULL) {
+ /* We are adding to an empty list. */
+ if (engine_dyn_list_tail != NULL)
+ goto err;
+ engine_dyn_list_head = e;
+ e->prev_dyn = NULL;
+ } else {
+ /* We are adding to the tail of an existing list. */
+ if (engine_dyn_list_tail == NULL
+ || engine_dyn_list_tail->next_dyn != NULL)
+ goto err;
+ engine_dyn_list_tail->next_dyn = e;
+ e->prev_dyn = engine_dyn_list_tail;
+ }
+
+ engine_dyn_list_tail = e;
+ e->next_dyn = NULL;
+ result = 1;
+
+ err:
+ if (not_locked)
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ return result;
+}
+
+/* Remove engine from dynamic engine list. */
+void engine_remove_dynamic_id(ENGINE *e, int not_locked)
+{
+ if (e == NULL || e->dynamic_id == NULL)
+ return;
+
+ if (not_locked && !CRYPTO_THREAD_write_lock(global_engine_lock))
+ return;
+
+ e->dynamic_id = NULL;
+
+ /* un-link e from the chain. */
+ if (e->next_dyn != NULL)
+ e->next_dyn->prev_dyn = e->prev_dyn;
+ if (e->prev_dyn != NULL)
+ e->prev_dyn->next_dyn = e->next_dyn;
+ /* Correct our head/tail if necessary. */
+ if (engine_dyn_list_head == e)
+ engine_dyn_list_head = e->next_dyn;
+ if (engine_dyn_list_tail == e)
+ engine_dyn_list_tail = e->prev_dyn;
+
+ if (not_locked)
+ CRYPTO_THREAD_unlock(global_engine_lock);
+}
+
/* Get the first/last "ENGINE" type available. */
ENGINE *ENGINE_get_first(void)
{
dest->load_pubkey = src->load_pubkey;
dest->cmd_defns = src->cmd_defns;
dest->flags = src->flags;
+ dest->dynamic_id = src->dynamic_id;
+ engine_add_dynamic_id(dest, NULL, 0);
}
ENGINE *ENGINE_by_id(const char *id)
extern CRYPTO_ONCE engine_lock_init;
DECLARE_RUN_ONCE(do_engine_lock_init)
+typedef void (*ENGINE_DYNAMIC_ID)(void);
+int engine_add_dynamic_id(ENGINE *e, ENGINE_DYNAMIC_ID dynamic_id,
+ int not_locked);
+void engine_remove_dynamic_id(ENGINE *e, int not_locked);
+
/*
* This is a structure for storing implementations of various crypto
* algorithms and functions.
/* Used to maintain the linked-list of engines. */
struct engine_st *prev;
struct engine_st *next;
+ /* Used to maintain the linked-list of dynamic engines. */
+ struct engine_st *prev_dyn;
+ struct engine_st *next_dyn;
+ ENGINE_DYNAMIC_ID dynamic_id;
};
typedef struct st_engine_pile ENGINE_PILE;