diff options
Diffstat (limited to 'src/libstrongswan')
-rw-r--r-- | src/libstrongswan/credentials/sets/mem_cred.c | 76 | ||||
-rw-r--r-- | src/libstrongswan/processing/processor.c | 12 | ||||
-rw-r--r-- | src/libstrongswan/processing/watcher.c | 18 | ||||
-rw-r--r-- | src/libstrongswan/utils/utils.h | 13 |
4 files changed, 113 insertions, 6 deletions
diff --git a/src/libstrongswan/credentials/sets/mem_cred.c b/src/libstrongswan/credentials/sets/mem_cred.c index b8da3f620..d8f568d36 100644 --- a/src/libstrongswan/credentials/sets/mem_cred.c +++ b/src/libstrongswan/credentials/sets/mem_cred.c @@ -307,8 +307,25 @@ METHOD(credential_set_t, create_private_enumerator, enumerator_t*, METHOD(mem_cred_t, add_key, void, private_mem_cred_t *this, private_key_t *key) { + enumerator_t *enumerator; + private_key_t *current; + this->lock->write_lock(this->lock); + + enumerator = this->keys->create_enumerator(this->keys); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current->equals(current, key)) + { + this->keys->remove_at(this->keys, enumerator); + current->destroy(current); + break; + } + } + enumerator->destroy(enumerator); + this->keys->insert_first(this->keys, key); + this->lock->unlock(this->lock); } @@ -334,6 +351,44 @@ static void shared_entry_destroy(shared_entry_t *entry) } /** + * Check if two shared key entries equal + */ +static bool shared_entry_equals(shared_entry_t *a, shared_entry_t *b) +{ + enumerator_t *e1, *e2; + identification_t *id1, *id2; + bool equals = TRUE; + + if (a->shared->get_type(a->shared) != b->shared->get_type(b->shared)) + { + return FALSE; + } + if (!chunk_equals(a->shared->get_key(a->shared), + b->shared->get_key(b->shared))) + { + return FALSE; + } + if (a->owners->get_count(a->owners) != b->owners->get_count(b->owners)) + { + return FALSE; + } + e1 = a->owners->create_enumerator(a->owners); + e2 = b->owners->create_enumerator(b->owners); + while (e1->enumerate(e1, &id1) && e2->enumerate(e2, &id2)) + { + if (!id1->equals(id1, id2)) + { + equals = FALSE; + break; + } + } + e1->destroy(e1); + e2->destroy(e2); + + return equals; +} + +/** * Data for the shared_key enumerator */ typedef struct { @@ -435,15 +490,30 @@ METHOD(credential_set_t, create_shared_enumerator, enumerator_t*, METHOD(mem_cred_t, add_shared_list, void, private_mem_cred_t *this, shared_key_t *shared, linked_list_t* owners) { - shared_entry_t *entry; + shared_entry_t *current, *new; + enumerator_t *enumerator; - INIT(entry, + INIT(new, .shared = shared, .owners = owners, ); this->lock->write_lock(this->lock); - this->shared->insert_first(this->shared, entry); + + enumerator = this->shared->create_enumerator(this->shared); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (shared_entry_equals(current, new)) + { + this->shared->remove_at(this->shared, enumerator); + shared_entry_destroy(current); + break; + } + } + enumerator->destroy(enumerator); + + this->shared->insert_first(this->shared, new); + this->lock->unlock(this->lock); } diff --git a/src/libstrongswan/processing/processor.c b/src/libstrongswan/processing/processor.c index 012b169e3..27e5ab5f6 100644 --- a/src/libstrongswan/processing/processor.c +++ b/src/libstrongswan/processing/processor.c @@ -467,6 +467,8 @@ METHOD(processor_t, cancel, void, { enumerator_t *enumerator; worker_thread_t *worker; + job_t *job; + int i; this->mutex->lock(this->mutex); this->desired_threads = 0; @@ -496,6 +498,14 @@ METHOD(processor_t, cancel, void, worker->thread->join(worker->thread); free(worker); } + for (i = 0; i < JOB_PRIO_MAX; i++) + { + while (this->jobs[i]->remove_first(this->jobs[i], + (void**)&job) == SUCCESS) + { + job->destroy(job); + } + } this->mutex->unlock(this->mutex); } @@ -510,7 +520,7 @@ METHOD(processor_t, destroy, void, this->mutex->destroy(this->mutex); for (i = 0; i < JOB_PRIO_MAX; i++) { - this->jobs[i]->destroy_offset(this->jobs[i], offsetof(job_t, destroy)); + this->jobs[i]->destroy(this->jobs[i]); } this->threads->destroy(this->threads); free(this); diff --git a/src/libstrongswan/processing/watcher.c b/src/libstrongswan/processing/watcher.c index cc3c3a788..09905646c 100644 --- a/src/libstrongswan/processing/watcher.c +++ b/src/libstrongswan/processing/watcher.c @@ -50,6 +50,11 @@ struct private_watcher_t { bool pending; /** + * Is watcher running? + */ + bool running; + + /** * Lock to access FD list */ mutex_t *mutex; @@ -225,6 +230,7 @@ static void activate_all(private_watcher_t *this) entry->in_callback = 0; } enumerator->destroy(enumerator); + this->running = FALSE; this->condvar->broadcast(this->condvar); this->mutex->unlock(this->mutex); } @@ -238,6 +244,7 @@ static job_requeue_t watch(private_watcher_t *this) entry_t *entry; fd_set rd, wr, ex; int maxfd = 0, res; + bool rebuild = FALSE; FD_ZERO(&rd); FD_ZERO(&wr); @@ -282,7 +289,7 @@ static job_requeue_t watch(private_watcher_t *this) enumerator->destroy(enumerator); this->mutex->unlock(this->mutex); - while (TRUE) + while (!rebuild) { char buf[1]; bool old; @@ -308,6 +315,11 @@ static job_requeue_t watch(private_watcher_t *this) enumerator = this->fds->create_enumerator(this->fds); while (enumerator->enumerate(enumerator, &entry)) { + if (entry->in_callback) + { + rebuild = TRUE; + break; + } if (FD_ISSET(entry->fd, &rd) && (entry->events & WATCHER_READ)) { DBG2(DBG_JOB, "watched FD %d ready to read", entry->fd); @@ -347,6 +359,7 @@ static job_requeue_t watch(private_watcher_t *this) return JOB_REQUEUE_DIRECT; } } + return JOB_REQUEUE_DIRECT; } METHOD(watcher_t, add, void, @@ -366,6 +379,7 @@ METHOD(watcher_t, add, void, this->fds->insert_last(this->fds, entry); if (this->fds->get_count(this->fds) == 1) { + this->running = TRUE; lib->processor->queue_job(lib->processor, (job_t*)callback_job_create_with_prio((void*)watch, this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); @@ -393,7 +407,7 @@ METHOD(watcher_t, remove_, void, { if (entry->fd == fd) { - if (entry->in_callback) + if (this->running && entry->in_callback) { is_in_callback = TRUE; break; diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h index 75b31ec1b..53bfceda6 100644 --- a/src/libstrongswan/utils/utils.h +++ b/src/libstrongswan/utils/utils.h @@ -204,6 +204,19 @@ static inline bool memeq(const void *x, const void *y, size_t len) static ret name(this, ##__VA_ARGS__) /** + * Callback declaration/definition macro, allowing casted first parameter. + * + * This is very similar to METHOD, but instead of casting the first parameter + * to a public interface, it uses a void*. This allows type safe definition + * of a callback function, while using the real type for the first parameter. + */ +#define CALLBACK(name, ret, param1, ...) \ + static ret _cb_##name(union {void *_generic; param1;} \ + __attribute__((transparent_union)), ##__VA_ARGS__); \ + static typeof(_cb_##name) *name = (typeof(_cb_##name)*)_cb_##name; \ + static ret _cb_##name(param1, ##__VA_ARGS__) + +/** * Architecture independent bitfield definition helpers (at least with GCC). * * Defines a bitfield with a type t and a fixed size of bitfield members, e.g.: |