summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c')
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c98
1 files changed, 91 insertions, 7 deletions
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c
index 0a960635b..f789c31d2 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c
@@ -17,6 +17,15 @@
#include <collections/linked_list.h>
#include <utils/debug.h>
+#include <threading/rwlock.h>
+#include <processing/jobs/callback_job.h>
+
+#include <daemon.h>
+
+/**
+ * Default PDP connection timeout, in s
+ */
+#define DEFAULT_TIMEOUT 30
typedef struct private_tnc_pdp_connections_t private_tnc_pdp_connections_t;
typedef struct entry_t entry_t;
@@ -32,9 +41,19 @@ struct private_tnc_pdp_connections_t {
tnc_pdp_connections_t public;
/**
- * List of TNC PEP RADIUS Connections
+ * TNC PEP RADIUS Connections
*/
linked_list_t *list;
+
+ /**
+ * Lock to access PEP connection list
+ */
+ rwlock_t *lock;
+
+ /**
+ * Connection timeout before we kill non-completed connections, in s
+ */
+ int timeout;
};
/**
@@ -61,6 +80,11 @@ struct entry_t {
* IKE SA used for bus communication
*/
ike_sa_t *ike_sa;
+
+ /**
+ * Timestamp this entry has been created
+ */
+ time_t created;
};
/**
@@ -105,6 +129,35 @@ static void dbg_nas_user(chunk_t nas_id, chunk_t user_name, bool not, char *op)
}
}
+/**
+ * Check if any connection has timed out
+ */
+static job_requeue_t check_timeouts(private_tnc_pdp_connections_t *this)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ time_t now;
+
+ now = time_monotonic(NULL);
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->list->create_enumerator(this->list);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->created + this->timeout <= now)
+ {
+ DBG1(DBG_CFG, "RADIUS connection timed out after %d seconds",
+ this->timeout);
+ this->list->remove_at(this->list, enumerator);
+ free_entry(entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return JOB_REQUEUE_NONE;
+}
+
METHOD(tnc_pdp_connections_t, add, void,
private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
identification_t *peer, eap_method_t *method)
@@ -120,6 +173,7 @@ METHOD(tnc_pdp_connections_t, add, void,
ike_sa_id->destroy(ike_sa_id);
ike_sa->set_other_id(ike_sa, peer);
+ this->lock->read_lock(this->lock);
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -131,20 +185,33 @@ METHOD(tnc_pdp_connections_t, add, void,
DBG1(DBG_CFG, "removed stale RADIUS connection");
entry->method = method;
entry->ike_sa = ike_sa;
+ entry->created = time_monotonic(NULL);
break;
}
}
enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
if (!found)
{
- entry = malloc_thing(entry_t);
- entry->nas_id = chunk_clone(nas_id);
- entry->user_name = chunk_clone(user_name);
- entry->method = method;
- entry->ike_sa = ike_sa;
+ INIT(entry,
+ .nas_id = chunk_clone(nas_id),
+ .user_name = chunk_clone(user_name),
+ .method = method,
+ .ike_sa = ike_sa,
+ .created = time_monotonic(NULL),
+ );
+ this->lock->write_lock(this->lock);
this->list->insert_last(this->list, entry);
+ this->lock->unlock(this->lock);
}
+
+ /* schedule timeout checking */
+ lib->scheduler->schedule_job_ms(lib->scheduler,
+ (job_t*)callback_job_create((callback_job_cb_t)check_timeouts,
+ this, NULL, (callback_job_cancel_t)return_false),
+ this->timeout * 1000);
+
dbg_nas_user(nas_id, user_name, FALSE, "created");
}
@@ -154,6 +221,7 @@ METHOD(tnc_pdp_connections_t, remove_, void,
enumerator_t *enumerator;
entry_t *entry;
+ this->lock->write_lock(this->lock);
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -166,6 +234,7 @@ METHOD(tnc_pdp_connections_t, remove_, void,
}
}
enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
}
METHOD(tnc_pdp_connections_t, get_state, eap_method_t*,
@@ -176,6 +245,7 @@ METHOD(tnc_pdp_connections_t, get_state, eap_method_t*,
entry_t *entry;
eap_method_t *found = NULL;
+ this->lock->read_lock(this->lock);
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -187,14 +257,25 @@ METHOD(tnc_pdp_connections_t, get_state, eap_method_t*,
}
}
enumerator->destroy(enumerator);
+ if (!found)
+ {
+ this->lock->unlock(this->lock);
+ }
dbg_nas_user(nas_id, user_name, !found, "found");
return found;
}
+METHOD(tnc_pdp_connections_t, unlock, void,
+ private_tnc_pdp_connections_t *this)
+{
+ this->lock->unlock(this->lock);
+}
+
METHOD(tnc_pdp_connections_t, destroy, void,
private_tnc_pdp_connections_t *this)
{
+ this->lock->destroy(this->lock);
this->list->destroy_function(this->list, (void*)free_entry);
free(this);
}
@@ -211,11 +292,14 @@ tnc_pdp_connections_t *tnc_pdp_connections_create(void)
.add = _add,
.remove = _remove_,
.get_state = _get_state,
+ .unlock = _unlock,
.destroy = _destroy,
},
.list = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .timeout = lib->settings->get_int(lib->settings,
+ "%s.plugins.tnc-pdp.timeout", DEFAULT_TIMEOUT, charon->name),
);
return &this->public;
}
-