diff options
Diffstat (limited to 'crypto/engine/eng_list.c')
-rw-r--r-- | crypto/engine/eng_list.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/crypto/engine/eng_list.c b/crypto/engine/eng_list.c index 1352fb7c96..4f9eb99d15 100644 --- a/crypto/engine/eng_list.c +++ b/crypto/engine/eng_list.c @@ -25,6 +25,12 @@ 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 * cleanup. @@ -126,6 +132,85 @@ static int engine_list_remove(ENGINE *e) 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) { @@ -272,6 +357,8 @@ static void engine_cpy(ENGINE *dest, const ENGINE *src) 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) |