Added a stroke rekey command to trigger IKE/CHILD_SA rekeying manually
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user