Added a stroke rekey command to trigger IKE/CHILD_SA rekeying manually

This commit is contained in:
Martin Willi
2010-11-03 15:12:05 +01:00
parent 49a9028201
commit 851d60484e
7 changed files with 150 additions and 28 deletions
+107 -27
View File
@@ -17,6 +17,8 @@
#include <daemon.h> #include <daemon.h>
#include <processing/jobs/delete_ike_sa_job.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; 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; int len;
ike_sa_t *ike_sa; char *pos = NULL;
enumerator_t *enumerator;
linked_list_t *ike_list, *child_list;
stroke_log_info_t info;
uintptr_t del;
string = msg->terminate.name; *id = 0;
*name = NULL;
*all = FALSE;
len = strlen(string); len = strlen(string);
if (len < 1) if (len < 1)
{ {
DBG1(DBG_CFG, "error parsing string"); return FALSE;
return;
} }
switch (string[len-1]) switch (string[len-1])
{ {
case '}': case '}':
child = TRUE; *child = TRUE;
pos = strchr(string, '{'); pos = strchr(string, '{');
break; break;
case ']': case ']':
child = FALSE; *child = FALSE;
pos = strchr(string, '['); pos = strchr(string, '[');
break; break;
default: default:
name = string; *name = string;
child = FALSE; *child = FALSE;
break; break;
} }
if (name) if (*name)
{ {
/* is a single name */ /* is a single name */
} }
else if (pos == string + len - 2) else if (pos == string + len - 2)
{ /* is name[] or name{} */ { /* is name[] or name{} */
string[len-2] = '\0'; string[len-2] = '\0';
name = string; *name = string;
} }
else else
{ {
if (!pos) if (!pos)
{ {
DBG1(DBG_CFG, "error parsing string"); return FALSE;
return;
} }
if (*(pos + 1) == '*') if (*(pos + 1) == '*')
{ /* is name[*] */ { /* is name[*] */
all = TRUE; *all = TRUE;
*pos = '\0'; *pos = '\0';
name = string; *name = string;
} }
else else
{ /* is name[123] or name{23} */ { /* is name[123] or name{23} */
id = atoi(pos + 1); *id = atoi(pos + 1);
if (id == 0) if (*id == 0)
{ {
DBG1(DBG_CFG, "error parsing string"); return FALSE;
return;
} }
} }
} }
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.out = out;
info.level = msg->output_verbosity; info.level = msg->output_verbosity;
@@ -293,6 +310,68 @@ static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *o
child_list->destroy(child_list); child_list->destroy(child_list);
} }
/**
* 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. * Implementation of stroke_control_t.terminate_srcip.
*/ */
@@ -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.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 = (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.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.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.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; this->public.unroute = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))unroute;
@@ -53,6 +53,13 @@ struct stroke_control_t {
*/ */
void (*terminate_srcip)(stroke_control_t *this, stroke_msg_t *msg, FILE *out); 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. * Delete IKE_SAs without a CHILD_SA.
* *
@@ -245,6 +245,17 @@ static void stroke_terminate_srcip(private_stroke_socket_t *this,
this->control->terminate_srcip(this->control, msg, out); this->control->terminate_srcip(this->control, msg, out);
} }
/**
* 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) * route a policy (install SPD entries)
*/ */
@@ -510,6 +521,9 @@ static job_requeue_t process(stroke_job_context_t *ctx)
case STR_TERMINATE_SRCIP: case STR_TERMINATE_SRCIP:
stroke_terminate_srcip(this, msg, out); stroke_terminate_srcip(this, msg, out);
break; break;
case STR_REKEY:
stroke_rekey(this, msg, out);
break;
case STR_STATUS: case STR_STATUS:
stroke_status(this, msg, out, FALSE); stroke_status(this, msg, out, FALSE);
break; break;
+17
View File
@@ -197,6 +197,16 @@ static int terminate_connection_srcip(char *start, char *end)
return send_stroke_msg(&msg); return send_stroke_msg(&msg);
} }
static int rekey_connection(char *name)
{
stroke_msg_t msg;
msg.type = STR_REKEY;
msg.length = offsetof(stroke_msg_t, buffer);
msg.rekey.name = push_string(&msg, name);
return send_stroke_msg(&msg);
}
static int route_connection(char *name) static int route_connection(char *name)
{ {
stroke_msg_t msg; stroke_msg_t msg;
@@ -443,6 +453,13 @@ int main(int argc, char *argv[])
} }
res = terminate_connection_srcip(argv[2], argc > 3 ? argv[3] : NULL); res = terminate_connection_srcip(argv[2], argc > 3 ? argv[3] : NULL);
break; break;
case STROKE_REKEY:
if (argc < 3)
{
exit_usage("\"rekey\" needs a connection name");
}
res = rekey_connection(argv[2]);
break;
case STROKE_ROUTE: case STROKE_ROUTE:
if (argc < 3) if (argc < 3)
{ {
+1
View File
@@ -25,6 +25,7 @@ typedef enum {
STROKE_UP, STROKE_UP,
STROKE_DOWN, STROKE_DOWN,
STROKE_DOWN_SRCIP, STROKE_DOWN_SRCIP,
STROKE_REKEY,
STROKE_LOGLEVEL, STROKE_LOGLEVEL,
STROKE_STATUS, STROKE_STATUS,
STROKE_STATUSALL, STROKE_STATUSALL,
+1
View File
@@ -32,6 +32,7 @@ unroute, STROKE_UNROUTE
up, STROKE_UP up, STROKE_UP
down, STROKE_DOWN down, STROKE_DOWN
down-srcip, STROKE_DOWN_SRCIP down-srcip, STROKE_DOWN_SRCIP
rekey, STROKE_REKEY
loglevel, STROKE_LOGLEVEL loglevel, STROKE_LOGLEVEL
status, STROKE_STATUS status, STROKE_STATUS
statusall, STROKE_STATUSALL statusall, STROKE_STATUSALL
+3 -1
View File
@@ -183,6 +183,8 @@ struct stroke_msg_t {
STR_TERMINATE, STR_TERMINATE,
/* terminate connection by peers srcip/virtual ip */ /* terminate connection by peers srcip/virtual ip */
STR_TERMINATE_SRCIP, STR_TERMINATE_SRCIP,
/* rekey a connection */
STR_REKEY,
/* show connection status */ /* show connection status */
STR_STATUS, STR_STATUS,
/* show verbose connection status */ /* show verbose connection status */
@@ -215,7 +217,7 @@ struct stroke_msg_t {
/* data for STR_INITIATE, STR_ROUTE, STR_UP, STR_DOWN, ... */ /* data for STR_INITIATE, STR_ROUTE, STR_UP, STR_DOWN, ... */
struct { struct {
char *name; char *name;
} initiate, route, unroute, terminate, status, del_conn, del_ca; } initiate, route, unroute, terminate, rekey, status, del_conn, del_ca;
/* data for STR_TERMINATE_SRCIP */ /* data for STR_TERMINATE_SRCIP */
struct { struct {