aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan')
-rw-r--r--src/libstrongswan/credentials/sets/mem_cred.c76
-rw-r--r--src/libstrongswan/processing/processor.c12
-rw-r--r--src/libstrongswan/processing/watcher.c18
-rw-r--r--src/libstrongswan/utils/utils.h13
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, &current))
+ {
+ 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, &current))
+ {
+ 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.: