aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/plugins/stroke
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2010-11-03 15:12:05 +0100
committerMartin Willi <martin@revosec.ch>2010-11-03 15:12:05 +0100
commit851d60484ea9f3d61d133fbd0eecea7eff015b3c (patch)
treea7e50781153f2dcdba9da42dcbf816c9d247153f /src/libcharon/plugins/stroke
parent49a9028201f3d2be9b3b7e640eae5de65ce9b5cd (diff)
downloadstrongswan-851d60484ea9f3d61d133fbd0eecea7eff015b3c.tar.bz2
strongswan-851d60484ea9f3d61d133fbd0eecea7eff015b3c.tar.xz
Added a stroke rekey command to trigger IKE/CHILD_SA rekeying manually
Diffstat (limited to 'src/libcharon/plugins/stroke')
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.c134
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.h7
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c14
3 files changed, 128 insertions, 27 deletions
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index e0398ba78..11c1103a2 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -17,6 +17,8 @@
#include <daemon.h>
#include <processing/jobs/delete_ike_sa_job.h>
+#include <processing/jobs/rekey_ike_sa_job.h>
+#include <processing/jobs/rekey_child_sa_job.h>
typedef struct private_stroke_control_t private_stroke_control_t;
@@ -137,76 +139,91 @@ static void initiate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *ou
}
/**
- * Implementation of stroke_control_t.terminate.
+ * Parse a terminate/rekey specifier
*/
-static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+static bool parse_specifier(char *string, u_int32_t *id,
+ char **name, bool *child, bool *all)
{
- char *string, *pos = NULL, *name = NULL;
- u_int32_t id = 0;
- bool child, all = FALSE;
int len;
- ike_sa_t *ike_sa;
- enumerator_t *enumerator;
- linked_list_t *ike_list, *child_list;
- stroke_log_info_t info;
- uintptr_t del;
+ char *pos = NULL;
- string = msg->terminate.name;
+ *id = 0;
+ *name = NULL;
+ *all = FALSE;
len = strlen(string);
if (len < 1)
{
- DBG1(DBG_CFG, "error parsing string");
- return;
+ return FALSE;
}
switch (string[len-1])
{
case '}':
- child = TRUE;
+ *child = TRUE;
pos = strchr(string, '{');
break;
case ']':
- child = FALSE;
+ *child = FALSE;
pos = strchr(string, '[');
break;
default:
- name = string;
- child = FALSE;
+ *name = string;
+ *child = FALSE;
break;
}
- if (name)
+ if (*name)
{
/* is a single name */
}
else if (pos == string + len - 2)
{ /* is name[] or name{} */
string[len-2] = '\0';
- name = string;
+ *name = string;
}
else
{
if (!pos)
{
- DBG1(DBG_CFG, "error parsing string");
- return;
+ return FALSE;
}
if (*(pos + 1) == '*')
{ /* is name[*] */
- all = TRUE;
+ *all = TRUE;
*pos = '\0';
- name = string;
+ *name = string;
}
else
{ /* is name[123] or name{23} */
- id = atoi(pos + 1);
- if (id == 0)
+ *id = atoi(pos + 1);
+ if (*id == 0)
{
- DBG1(DBG_CFG, "error parsing string");
- return;
+ return FALSE;
}
}
}
+ return TRUE;
+}
+
+/**
+ * Implementation of stroke_control_t.terminate.
+ */
+static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+{
+ char *name;
+ u_int32_t id;
+ bool child, all;
+ ike_sa_t *ike_sa;
+ enumerator_t *enumerator;
+ linked_list_t *ike_list, *child_list;
+ stroke_log_info_t info;
+ uintptr_t del;
+
+ if (!parse_specifier(msg->terminate.name, &id, &name, &child, &all))
+ {
+ DBG1(DBG_CFG, "error parsing specifier string");
+ return;
+ }
info.out = out;
info.level = msg->output_verbosity;
@@ -294,6 +311,68 @@ static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *o
}
/**
+ * Implementation of stroke_control_t.rekey.
+ */
+static void rekey(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
+{
+ char *name;
+ u_int32_t id;
+ bool child, all, finished = FALSE;
+ ike_sa_t *ike_sa;
+ enumerator_t *enumerator;
+
+ if (!parse_specifier(msg->terminate.name, &id, &name, &child, &all))
+ {
+ DBG1(DBG_CFG, "error parsing specifier string");
+ return;
+ }
+ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ child_sa_t *child_sa;
+ iterator_t *children;
+
+ if (child)
+ {
+ children = ike_sa->create_child_sa_iterator(ike_sa);
+ while (children->iterate(children, (void**)&child_sa))
+ {
+ if ((name && streq(name, child_sa->get_name(child_sa))) ||
+ (id && id == child_sa->get_reqid(child_sa)))
+ {
+ lib->processor->queue_job(lib->processor,
+ (job_t*)rekey_child_sa_job_create(
+ child_sa->get_reqid(child_sa),
+ child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE)));
+ if (!all)
+ {
+ finished = TRUE;
+ break;
+ }
+ }
+ }
+ children->destroy(children);
+ }
+ else if ((name && streq(name, ike_sa->get_name(ike_sa))) ||
+ (id && id == ike_sa->get_unique_id(ike_sa)))
+ {
+ lib->processor->queue_job(lib->processor,
+ (job_t*)rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE));
+ if (!all)
+ {
+ finished = TRUE;
+ }
+ }
+ if (finished)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
* Implementation of stroke_control_t.terminate_srcip.
*/
static void terminate_srcip(private_stroke_control_t *this,
@@ -486,6 +565,7 @@ stroke_control_t *stroke_control_create()
this->public.initiate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))initiate;
this->public.terminate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))terminate;
this->public.terminate_srcip = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))terminate_srcip;
+ this->public.rekey = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))rekey;
this->public.purge_ike = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))purge_ike;
this->public.route = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))route;
this->public.unroute = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))unroute;
diff --git a/src/libcharon/plugins/stroke/stroke_control.h b/src/libcharon/plugins/stroke/stroke_control.h
index 9b49bdc31..869aab3d3 100644
--- a/src/libcharon/plugins/stroke/stroke_control.h
+++ b/src/libcharon/plugins/stroke/stroke_control.h
@@ -54,6 +54,13 @@ struct stroke_control_t {
void (*terminate_srcip)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
/**
+ * Rekey a connection.
+ *
+ * @param msg stroke message
+ */
+ void (*rekey)(stroke_control_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
* Delete IKE_SAs without a CHILD_SA.
*
* @param msg stroke message
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 0a5110fd3..2e321f8b0 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -246,6 +246,17 @@ static void stroke_terminate_srcip(private_stroke_socket_t *this,
}
/**
+ * rekey a connection by name/id
+ */
+static void stroke_rekey(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->terminate.name);
+ DBG1(DBG_CFG, "received stroke: rekey '%s'", msg->rekey.name);
+
+ this->control->rekey(this->control, msg, out);
+}
+
+/**
* route a policy (install SPD entries)
*/
static void stroke_route(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
@@ -510,6 +521,9 @@ static job_requeue_t process(stroke_job_context_t *ctx)
case STR_TERMINATE_SRCIP:
stroke_terminate_srcip(this, msg, out);
break;
+ case STR_REKEY:
+ stroke_rekey(this, msg, out);
+ break;
case STR_STATUS:
stroke_status(this, msg, out, FALSE);
break;