added possibility to route CHILD_SAs, without to set them up

support for auto=route parameter
	support for ipsec route and ipsec unroute
	initiating of CHILD and/or IKE_SAs based on kernel acquires
This commit is contained in:
Martin Willi
2006-07-21 13:31:53 +00:00
parent c0593835f4
commit 45f76a7ddd
26 changed files with 1011 additions and 142 deletions
+2
View File
@@ -46,6 +46,8 @@ queues/jobs/send_keepalive_job.c queues/jobs/send_keepalive_job.h \
queues/jobs/rekey_child_sa_job.c queues/jobs/rekey_child_sa_job.h \
queues/jobs/delete_child_sa_job.c queues/jobs/delete_child_sa_job.h \
queues/jobs/send_dpd_job.c queues/jobs/send_dpd_job.h \
queues/jobs/route_job.c queues/jobs/route_job.h \
queues/jobs/acquire_job.c queues/jobs/acquire_job.h \
queues/job_queue.c queues/event_queue.c queues/send_queue.h queues/job_queue.h queues/event_queue.h \
queues/send_queue.c threads/kernel_interface.c threads/thread_pool.c threads/scheduler.c threads/sender.c \
threads/sender.h threads/kernel_interface.h threads/scheduler.h threads/receiver.c threads/stroke_interface.c \
+24
View File
@@ -247,6 +247,29 @@ static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_
return NULL;
}
/**
* implements traffic_selector_t.equals
*/
static bool equals(private_traffic_selector_t *this, private_traffic_selector_t *other)
{
if (this->type != other->type)
{
return FALSE;
}
if (this->type == TS_IPV4_ADDR_RANGE)
{
if (this->from_addr_ipv4 == other->from_addr_ipv4 &&
this->to_addr_ipv4 == other->to_addr_ipv4 &&
this->from_port == other->from_port &&
this->to_port == other->to_port &&
this->protocol == other->protocol)
{
return TRUE;
}
}
return FALSE;
}
/**
* Implements traffic_selector_t.get_from_address.
*/
@@ -518,6 +541,7 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts
/* public functions */
this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
this->public.equals = (bool(*)(traffic_selector_t*,traffic_selector_t*))equals;
this->public.get_string = (char*(*)(traffic_selector_t*))get_string;
this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address;
this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address;
+9
View File
@@ -183,6 +183,15 @@ struct traffic_selector_t {
*/
char* (*get_string) (traffic_selector_t *this);
/**
* @brief Compare two traffic selectors for equality.
*
* @param this first to compare
* @param other second to compare with first
* @return pointer to a string.
*/
bool (*equals) (traffic_selector_t *this, traffic_selector_t *other);
/**
* @brief Destroys the ts object
*
+104
View File
@@ -0,0 +1,104 @@
/**
* @file acquire_job.c
*
* @brief Implementation of acquire_job_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "acquire_job.h"
#include <daemon.h>
typedef struct private_acquire_job_t private_acquire_job_t;
/**
* Private data of an acquire_job_t object.
*/
struct private_acquire_job_t {
/**
* Public acquire_job_t interface.
*/
acquire_job_t public;
/**
* reqid of the child to rekey
*/
u_int32_t reqid;
/**
* Logger ref
*/
logger_t *logger;
};
/**
* Implementation of job_t.get_type.
*/
static job_type_t get_type(private_acquire_job_t *this)
{
return ACQUIRE;
}
/**
* Implementation of job_t.execute.
*/
static status_t execute(private_acquire_job_t *this)
{
ike_sa_t *ike_sa;
ike_sa = charon->ike_sa_manager->checkout_by_child(charon->ike_sa_manager,
this->reqid);
if (ike_sa == NULL)
{
this->logger->log(this->logger, ERROR|LEVEL1,
"CHILD_SA not found for acquiring");
return DESTROY_ME;
}
ike_sa->acquire(ike_sa, this->reqid);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
return DESTROY_ME;
}
/**
* Implementation of job_t.destroy.
*/
static void destroy(private_acquire_job_t *this)
{
free(this);
}
/*
* Described in header
*/
acquire_job_t *acquire_job_create(u_int32_t reqid)
{
private_acquire_job_t *this = malloc_thing(private_acquire_job_t);
/* interface functions */
this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
/* private variables */
this->reqid = reqid;
this->logger = logger_manager->get_logger(logger_manager, WORKER);
return &(this->public);
}
+61
View File
@@ -0,0 +1,61 @@
/**
* @file acquire_job.h
*
* @brief Interface of acquire_job_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef ACQUIRE_JOB_H_
#define ACQUIRE_JOB_H_
#include <types.h>
#include <queues/jobs/job.h>
typedef struct acquire_job_t acquire_job_t;
/**
* @brief Class representing an ACQUIRE Job.
*
* This job initiates a CHILD SA on kernel request.
*
* @b Constructors:
* - acquire_job_create()
*
* @ingroup jobs
*/
struct acquire_job_t {
/**
* The job_t interface.
*/
job_t job_interface;
};
/**
* @brief Creates a job of type ACQUIRE.
*
* We use the reqid to find the routed CHILD_SA.
*
* @param reqid reqid of the CHILD_SA to acquire
* @return acquire_job_t object
*
* @ingroup jobs
*/
acquire_job_t *acquire_job_create(u_int32_t reqid);
#endif /* REKEY_CHILD_SA_JOB_H_ */
+12 -6
View File
@@ -36,6 +36,11 @@ struct private_delete_child_sa_job_t {
*/
delete_child_sa_job_t public;
/**
* reqid of the CHILD_SA
*/
u_int32_t reqid;
/**
* protocol of the CHILD_SA (ESP/AH)
*/
@@ -66,12 +71,10 @@ static job_type_t get_type(private_delete_child_sa_job_t *this)
static status_t execute(private_delete_child_sa_job_t *this)
{
ike_sa_t *ike_sa;
status_t status;
status = charon->ike_sa_manager->checkout_by_child(charon->ike_sa_manager,
this->protocol, this->spi,
&ike_sa);
if (status != SUCCESS)
ike_sa = charon->ike_sa_manager->checkout_by_child(charon->ike_sa_manager,
this->reqid);
if (ike_sa == NULL)
{
this->logger->log(this->logger, ERROR|LEVEL1,
"CHILD_SA not found for delete");
@@ -94,7 +97,9 @@ static void destroy(private_delete_child_sa_job_t *this)
/*
* Described in header
*/
delete_child_sa_job_t *delete_child_sa_job_create(protocol_id_t protocol, u_int32_t spi)
delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
protocol_id_t protocol,
u_int32_t spi)
{
private_delete_child_sa_job_t *this = malloc_thing(private_delete_child_sa_job_t);
@@ -104,6 +109,7 @@ delete_child_sa_job_t *delete_child_sa_job_create(protocol_id_t protocol, u_int3
this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
/* private variables */
this->reqid = reqid;
this->protocol = protocol;
this->spi = spi;
this->logger = logger_manager->get_logger(logger_manager, WORKER);
+5 -2
View File
@@ -51,15 +51,18 @@ struct delete_child_sa_job_t {
/**
* @brief Creates a job of type DELETE_CHILD_SA.
*
* The CHILD_SA is identified by its protocol (AH/ESP) and its
* The CHILD_SA is identified by its reqid, protocol (AH/ESP) and its
* inbound SPI.
*
* @param reqid reqid of the CHILD_SA, as used in kernel
* @param protocol protocol of the CHILD_SA
* @param spi security parameter index of the CHILD_SA
* @return delete_child_sa_job_t object
*
* @ingroup jobs
*/
delete_child_sa_job_t *delete_child_sa_job_create(protocol_id_t protocol, u_int32_t spi);
delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
protocol_id_t protocol,
u_int32_t spi);
#endif /* DELETE_CHILD_SA_JOB_H_ */
+14
View File
@@ -57,6 +57,20 @@ enum job_type_t {
*/
INITIATE,
/**
* Install SPD entries.
*
* Job is implemented in class route_job_t
*/
ROUTE,
/**
* React on a acquire message from the kernel (e.g. setup CHILD_SA)
*
* Job is implemented in class acquire_job_t
*/
ACQUIRE,
/**
* Delete an ike sa which is still not established.
*
+12 -6
View File
@@ -36,6 +36,11 @@ struct private_rekey_child_sa_job_t {
*/
rekey_child_sa_job_t public;
/**
* reqid of the child to rekey
*/
u_int32_t reqid;
/**
* protocol of the CHILD_SA (ESP/AH)
*/
@@ -66,12 +71,10 @@ static job_type_t get_type(private_rekey_child_sa_job_t *this)
static status_t execute(private_rekey_child_sa_job_t *this)
{
ike_sa_t *ike_sa;
status_t status;
status = charon->ike_sa_manager->checkout_by_child(charon->ike_sa_manager,
this->protocol, this->spi,
&ike_sa);
if (status != SUCCESS)
ike_sa = charon->ike_sa_manager->checkout_by_child(charon->ike_sa_manager,
this->reqid);
if (ike_sa == NULL)
{
this->logger->log(this->logger, ERROR|LEVEL1,
"CHILD_SA not found for rekeying");
@@ -94,7 +97,9 @@ static void destroy(private_rekey_child_sa_job_t *this)
/*
* Described in header
*/
rekey_child_sa_job_t *rekey_child_sa_job_create(protocol_id_t protocol, u_int32_t spi)
rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid,
protocol_id_t protocol,
u_int32_t spi)
{
private_rekey_child_sa_job_t *this = malloc_thing(private_rekey_child_sa_job_t);
@@ -104,6 +109,7 @@ rekey_child_sa_job_t *rekey_child_sa_job_create(protocol_id_t protocol, u_int32_
this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
/* private variables */
this->reqid = reqid;
this->protocol = protocol;
this->spi = spi;
this->logger = logger_manager->get_logger(logger_manager, WORKER);
+2 -1
View File
@@ -54,12 +54,13 @@ struct rekey_child_sa_job_t {
* The CHILD_SA is identified by its protocol (AH/ESP) and its
* inbound SPI.
*
* @param reqid reqid of the CHILD_SA to rekey
* @param protocol protocol of the CHILD_SA
* @param spi security parameter index of the CHILD_SA
* @return rekey_child_sa_job_t object
*
* @ingroup jobs
*/
rekey_child_sa_job_t *rekey_child_sa_job_create(protocol_id_t protocol, u_int32_t spi);
rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid, protocol_id_t protocol, u_int32_t spi);
#endif /* REKEY_CHILD_SA_JOB_H_ */
+133
View File
@@ -0,0 +1,133 @@
/**
* @file route_job.c
*
* @brief Implementation of route_job_t.
*
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stdlib.h>
#include "route_job.h"
#include <daemon.h>
typedef struct private_route_job_t private_route_job_t;
/**
* Private data of an route_job_t Object
*/
struct private_route_job_t {
/**
* public route_job_t interface
*/
route_job_t public;
/**
* associated connection to route
*/
connection_t *connection;
/**
* associated policy to route
*/
policy_t *policy;
/**
* route or unroute?
*/
bool route;
/**
* logger
*/
logger_t *logger;
};
/**
* Implements route_job_t.get_type.
*/
static job_type_t get_type(private_route_job_t *this)
{
return ROUTE;
}
/**
* Implementation of job_t.execute.
*/
static status_t execute(private_route_job_t *this)
{
ike_sa_t *ike_sa;
this->logger->log(this->logger, CONTROL|LEVEL2, "getting an IKE SA");
ike_sa = charon->ike_sa_manager->checkout_by_ids(charon->ike_sa_manager,
this->policy->get_my_id(this->policy),
this->policy->get_other_id(this->policy));
if (this->route)
{
if (ike_sa->route(ike_sa, this->connection, this->policy) != SUCCESS)
{
this->logger->log(this->logger, ERROR,
"routing failed");
}
}
else
{
if (ike_sa->unroute(ike_sa, this->policy) == DESTROY_ME)
{
this->logger->log(this->logger, ERROR,
"removing IKE_SA, as last routed CHILD_SA unrouted");
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
return DESTROY_ME;
}
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
return DESTROY_ME;
}
/**
* Implements job_t.destroy.
*/
static void destroy(private_route_job_t *this)
{
this->connection->destroy(this->connection);
this->policy->destroy(this->policy);
free(this);
}
/*
* Described in header
*/
route_job_t *route_job_create(connection_t *connection, policy_t *policy, bool route)
{
private_route_job_t *this = malloc_thing(private_route_job_t);
/* interface functions */
this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
/* private variables */
this->connection = connection;
this->policy = policy;
this->route = route;
this->logger = logger_manager->get_logger(logger_manager, WORKER);
return &this->public;
}
+60
View File
@@ -0,0 +1,60 @@
/**
* @file route_job.h
*
* @brief Interface of route_job_t.
*/
/*
* Copyright (C) 2005-2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef ROUTE_JOB_H_
#define ROUTE_JOB_H_
#include <types.h>
#include <queues/jobs/job.h>
#include <config/policies/policy.h>
#include <config/connections/connection.h>
typedef struct route_job_t route_job_t;
/**
* @brief Class representing an ROUTE Job.
*
* @b Constructors:
* - route_job_create()
*
* @ingroup jobs
*/
struct route_job_t {
/**
* implements job_t interface
*/
job_t job_interface;
};
/**
* @brief Creates a job of type ROUTE.
*
* @param connection connection used for routing
* @param policy policy to set up
* @param route TRUE to route, FALSE to unroute
* @return route_job_t object
*
* @ingroup jobs
*/
route_job_t *route_job_create(connection_t *connection, policy_t *policy, bool route);
#endif /*ROUTE_JOB_H_*/
+66 -49
View File
@@ -33,6 +33,7 @@
mapping_t child_sa_state_m[] = {
{CHILD_CREATED, "CREATED"},
{CHILD_INSTALLED, "INSTALLED"},
{CHILD_ROUTED, "ROUTED"},
{CHILD_REKEYING, "REKEYING"},
{CHILD_DELETING, "DELETING"},
{MAPPING_END, NULL}
@@ -502,6 +503,13 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
}
my_iter->destroy(my_iter);
other_iter->destroy(other_iter);
/* switch to routed state if no SAD entry set up */
if (this->state == CHILD_CREATED)
{
this->state = CHILD_ROUTED;
}
return SUCCESS;
}
@@ -597,66 +605,75 @@ static void log_status(private_child_sa_t *this, logger_t *logger, char* name)
}
now = (u_int32_t)time(NULL);
/* query SA times */
status = charon->kernel_interface->query_sa(charon->kernel_interface,
this->me.addr, this->me.spi, this->protocol, &use_in);
if (status == SUCCESS && use_in)
if (this->state == CHILD_INSTALLED)
{
snprintf(use_in_str, sizeof(use_in_str), "%ds", now - use_in);
}
status = charon->kernel_interface->query_sa(charon->kernel_interface,
this->other.addr, this->other.spi, this->protocol, &use_out);
if (status == SUCCESS && use_out)
{
snprintf(use_out_str, sizeof(use_out_str), "%ds", now - use_out);
}
/* calculate rekey times */
if (this->soft_lifetime)
{
rekeying = this->soft_lifetime - (now - this->install_time);
snprintf(rekey_str, sizeof(rekey_str), "%ds", (int)rekeying);
}
/* algorithms used */
if (this->protocol == PROTO_ESP)
{
if (this->encryption.key_size)
/* query SA times */
status = charon->kernel_interface->query_sa(charon->kernel_interface,
this->me.addr, this->me.spi, this->protocol, &use_in);
if (status == SUCCESS && use_in)
{
snprintf(enc_str, sizeof(enc_str), "%s-%d,",
mapping_find(encryption_algorithm_m, this->encryption.algorithm),
this->encryption.key_size);
snprintf(use_in_str, sizeof(use_in_str), "%ds", now - use_in);
}
status = charon->kernel_interface->query_sa(charon->kernel_interface,
this->other.addr, this->other.spi, this->protocol, &use_out);
if (status == SUCCESS && use_out)
{
snprintf(use_out_str, sizeof(use_out_str), "%ds", now - use_out);
}
/* calculate rekey times */
if (this->soft_lifetime)
{
rekeying = this->soft_lifetime - (now - this->install_time);
snprintf(rekey_str, sizeof(rekey_str), "%ds", (int)rekeying);
}
/* algorithms used */
if (this->protocol == PROTO_ESP)
{
if (this->encryption.key_size)
{
snprintf(enc_str, sizeof(enc_str), "%s-%d,",
mapping_find(encryption_algorithm_m, this->encryption.algorithm),
this->encryption.key_size);
}
else
{
snprintf(enc_str, sizeof(enc_str), "%s,",
mapping_find(encryption_algorithm_m, this->encryption.algorithm));
}
}
if (this->integrity.key_size)
{
snprintf(int_str, sizeof(int_str), "%s-%d",
mapping_find(integrity_algorithm_m, this->integrity.algorithm),
this->integrity.key_size);
}
else
{
snprintf(enc_str, sizeof(enc_str), "%s,",
mapping_find(encryption_algorithm_m, this->encryption.algorithm));
snprintf(int_str, sizeof(int_str), "%s",
mapping_find(integrity_algorithm_m, this->integrity.algorithm));
}
}
if (this->integrity.key_size)
{
snprintf(int_str, sizeof(int_str), "%s-%d",
mapping_find(integrity_algorithm_m, this->integrity.algorithm),
this->integrity.key_size);
logger->log(logger, CONTROL|LEVEL1,
" \"%s\": state: %s, reqid: %d, ",
name, mapping_find(child_sa_state_m, this->state), this->reqid);
logger->log(logger, CONTROL|LEVEL1,
" \"%s\": %s (%s%s), SPIs (in/out): 0x%x/0x%x",
name, this->protocol == PROTO_ESP ? "ESP" : "AH",
enc_str, int_str,
htonl(this->me.spi), htonl(this->other.spi));
logger->log(logger, CONTROL|LEVEL1,
" \"%s\": rekeying: %s, key age (in/out): %s/%s",
name, rekey_str, use_in_str, use_out_str);
}
else
{
snprintf(int_str, sizeof(int_str), "%s",
mapping_find(integrity_algorithm_m, this->integrity.algorithm));
logger->log(logger, CONTROL|LEVEL1, " \"%s\": state: %s, reqid: %d",
name, mapping_find(child_sa_state_m, this->state),
this->reqid);
}
logger->log(logger, CONTROL|LEVEL1,
" \"%s\": %s (%s%s), SPIs (in/out): 0x%x/0x%x, reqid: %d",
name,
this->protocol == PROTO_ESP ? "ESP" : "AH",
enc_str, int_str,
htonl(this->me.spi), htonl(this->other.spi),
this->reqid);
logger->log(logger, CONTROL|LEVEL1,
" \"%s\": state: %s, rekeying: %s, key age (in/out): %s/%s",
name, mapping_find(child_sa_state_m, this->state),
rekey_str, use_in_str, use_out_str);
iterator = this->policies->create_iterator(this->policies, TRUE);
while (iterator->has_next(iterator))
{
+5
View File
@@ -48,6 +48,11 @@ enum child_sa_state_t {
*/
CHILD_CREATED,
/**
* Installed SPD, but no SAD entries
*/
CHILD_ROUTED,
/**
* Installed an in-use CHILD_SA
*/
+320 -30
View File
@@ -329,10 +329,13 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
child_sa_t *child_sa = NULL;
host_diff_t my_diff, other_diff;
if (this->my_host == NULL || this->other_host == NULL)
if (this->my_host->is_anyaddr(this->my_host) ||
this->other_host->is_anyaddr(this->other_host))
{
/* on first received message */
this->my_host->destroy(this->my_host);
this->my_host = me->clone(me);
this->other_host->destroy(this->other_host);
this->other_host = other->clone(other);
return;
}
@@ -792,9 +795,14 @@ static status_t initiate(private_ike_sa_t *this,
*/
ike_sa_init_t *ike_sa_init;
this->logger->log(this->logger, CONTROL,
"initiating IKE_SA");
set_name(this, connection->get_name(connection));
DESTROY_IF(this->my_host);
this->my_host = connection->get_my_host(connection);
this->my_host = this->my_host->clone(this->my_host);
DESTROY_IF(this->other_host);
this->other_host = connection->get_other_host(connection);
this->other_host = this->other_host->clone(this->other_host);
@@ -806,6 +814,8 @@ static status_t initiate(private_ike_sa_t *this,
case IKE_DELETING:
{
/* if we are in DELETING, we deny set up of a policy. */
this->logger->log(this->logger, CONTROL,
"creating CHILD_SA discarded, as IKE_SA is deleting");
policy->destroy(policy);
connection->destroy(connection);
return FAILED;
@@ -820,6 +830,9 @@ static status_t initiate(private_ike_sa_t *this,
*/
create_child_sa_t *create_child;
this->logger->log(this->logger, CONTROL,
"initiating CHILD_SA");
connection->destroy(connection);
create_child = create_child_sa_create(&this->public);
create_child->set_policy(create_child, policy);
@@ -834,33 +847,275 @@ static status_t initiate(private_ike_sa_t *this,
*/
static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
{
/* - get TS from child with reqid
* - get a policy from TS
* - get connection from policy
*/
connection_t *connection;
policy_t *policy;
iterator_t *iterator;
child_sa_t *current, *child_sa = NULL;
linked_list_t *my_ts, *other_ts;
if (this->state == IKE_DELETING)
{
this->logger->log(this->logger, CONTROL,
"acquiring CHILD_SA with reqid %d discarded, as IKE_SA is deleting",
reqid);
return FAILED;
}
/* find CHILD_SA */
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&current))
{
if (current->get_reqid(current) == reqid)
{
iterator->remove(iterator);
child_sa = current;
break;
}
}
iterator->destroy(iterator);
if (!child_sa)
{
this->logger->log(this->logger, ERROR,
"CHILD_SA with reqid %d not found, unable to acquire",
reqid);
return FAILED;
}
my_ts = child_sa->get_my_traffic_selectors(child_sa);
other_ts = child_sa->get_other_traffic_selectors(child_sa);
policy = charon->policies->get_policy(charon->policies,
this->my_id, this->other_id,
my_ts, other_ts,
this->my_host, this->other_host);
child_sa->destroy(child_sa);
if (policy == NULL)
{
this->logger->log(this->logger, ERROR,
"no policy found to acquire CHILD_SA with reqid %d",
reqid);
return FAILED;
}
switch (this->state)
{
case IKE_CREATED:
/* ike_sa_init */
break;
{
ike_sa_init_t *ike_sa_init;
this->logger->log(this->logger, CONTROL,
"acquiring CHILD_SA with reqid %d, IKE_SA setup needed",
reqid);
connection = charon->connections->get_connection_by_hosts(
charon->connections, this->my_host, this->other_host);
if (connection == NULL)
{
this->logger->log(this->logger, ERROR,
"no connection found to acquire IKE_SA for CHILD_SA with reqid %d",
reqid);
policy->destroy(policy);
return FAILED;
}
this->message_id_out = 1;
ike_sa_init = ike_sa_init_create(&this->public);
ike_sa_init->set_config(ike_sa_init, connection, policy);
return queue_transaction(this, (transaction_t*)ike_sa_init, TRUE);
}
case IKE_CONNECTING:
case IKE_ESTABLISHED:
/* queue create_child_sa */
break;
case IKE_DELETING:
/* deny */
{
create_child_sa_t *create_child;
this->logger->log(this->logger, CONTROL,
"acquiring CHILD_SA with reqid %d",
reqid);
create_child = create_child_sa_create(&this->public);
create_child->set_policy(create_child, policy);
return queue_transaction(this, (transaction_t*)create_child, FALSE);
}
default:
break;
}
return FAILED;
}
/**
* destroy a list of traffic selectors
*/
static void ts_list_destroy(linked_list_t *list)
{
traffic_selector_t *ts;
while (list->remove_last(list, (void**)&ts) == SUCCESS)
{
ts->destroy(ts);
}
list->destroy(list);
}
/**
* compare two lists of traffic selectors for equality
*/
static bool ts_list_equals(linked_list_t *l1, linked_list_t *l2)
{
bool equals = TRUE;
iterator_t *i1, *i2;
traffic_selector_t *t1, *t2;
i1 = l1->create_iterator(l1, TRUE);
i2 = l2->create_iterator(l2, TRUE);
while (i1->iterate(i1, (void**)&t1) && i2->iterate(i2, (void**)&t2))
{
if (!t1->equals(t1, t2))
{
equals = FALSE;
break;
}
}
/* check if one iterator is not at the end */
if (i1->has_next(i1) || i2->has_next(i2))
{
equals = FALSE;
}
i1->destroy(i1);
i2->destroy(i2);
return equals;
}
/**
* Implementation of ike_sa_t.route.
*/
static status_t route(private_ike_sa_t *this, policy_t *policy)
static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t *policy)
{
/* TODO: create CHILD_SA, add policy */
return FAILED;
child_sa_t *child_sa = NULL;
iterator_t *iterator;
linked_list_t *my_ts, *other_ts;
status_t status;
/* check if not already routed*/
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
linked_list_t *my_ts_conf, *other_ts_conf;
my_ts = child_sa->get_my_traffic_selectors(child_sa);
other_ts = child_sa->get_other_traffic_selectors(child_sa);
my_ts_conf = policy->get_my_traffic_selectors(policy, this->my_host);
other_ts_conf = policy->get_other_traffic_selectors(policy, this->other_host);
if (ts_list_equals(my_ts, my_ts_conf) &&
ts_list_equals(other_ts, other_ts_conf))
{
ts_list_destroy(my_ts_conf);
ts_list_destroy(other_ts_conf);
iterator->destroy(iterator);
this->logger->log(this->logger, CONTROL,
"a CHILD_SA with such a policy already routed");
return FAILED;
}
ts_list_destroy(my_ts_conf);
ts_list_destroy(other_ts_conf);
}
iterator->destroy(iterator);
switch (this->state)
{
case IKE_CREATED:
case IKE_CONNECTING:
/* we update IKE_SA information as good as possible,
* this allows us to set up the SA later when an acquire comes in. */
if (this->my_id->get_type(this->my_id) == ID_ANY)
{
this->my_id->destroy(this->my_id);
this->my_id = policy->get_my_id(policy);
this->my_id = this->my_id->clone(this->my_id);
}
if (this->other_id->get_type(this->other_id) == ID_ANY)
{
this->other_id->destroy(this->other_id);
this->other_id = policy->get_other_id(policy);
this->other_id = this->other_id->clone(this->other_id);
}
if (this->my_host->is_anyaddr(this->my_host))
{
this->my_host->destroy(this->my_host);
this->my_host = connection->get_my_host(connection);
this->my_host = this->my_host->clone(this->my_host);
}
if (this->other_host->is_anyaddr(this->other_host))
{
this->other_host->destroy(this->other_host);
this->other_host = connection->get_other_host(connection);
this->other_host = this->other_host->clone(this->other_host);
}
set_name(this, connection->get_name(connection));
break;
case IKE_ESTABLISHED:
/* nothing to do */
break;
case IKE_DELETING:
/* deny */
return FAILED;
}
child_sa = child_sa_create(0, this->my_host, this->other_host, 0, 0, FALSE);
my_ts = policy->get_my_traffic_selectors(policy, this->my_host);
other_ts = policy->get_other_traffic_selectors(policy, this->other_host);
status = child_sa->add_policies(child_sa, my_ts, other_ts);
ts_list_destroy(my_ts);
ts_list_destroy(other_ts);
this->child_sas->insert_last(this->child_sas, child_sa);
return status;
}
/**
* Implementation of ike_sa_t.unroute.
*/
static status_t unroute(private_ike_sa_t *this, policy_t *policy)
{
iterator_t *iterator;
child_sa_t *child_sa = NULL;
linked_list_t *my_ts, *other_ts, *my_ts_conf, *other_ts_conf;
/* find CHILD_SA in ROUTED state */
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
if (child_sa->get_state(child_sa) == CHILD_ROUTED)
{
my_ts = child_sa->get_my_traffic_selectors(child_sa);
other_ts = child_sa->get_other_traffic_selectors(child_sa);
my_ts_conf = policy->get_my_traffic_selectors(policy, this->my_host);
other_ts_conf = policy->get_other_traffic_selectors(policy, this->other_host);
if (ts_list_equals(my_ts, my_ts_conf) &&
ts_list_equals(other_ts, other_ts_conf))
{
iterator->remove(iterator);
child_sa->destroy(child_sa);
ts_list_destroy(my_ts_conf);
ts_list_destroy(other_ts_conf);
break;
}
ts_list_destroy(my_ts_conf);
ts_list_destroy(other_ts_conf);
}
}
iterator->destroy(iterator);
/* if we are not established, and we have no more routed childs, remove whole SA */
if (this->state == IKE_CREATED &&
this->child_sas->get_count(this->child_sas) == 0)
{
return DESTROY_ME;
}
return SUCCESS;
}
/**
@@ -1217,6 +1472,28 @@ static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa)
this->child_sas->insert_last(this->child_sas, child_sa);
}
/**
* Implementation of protected_ike_sa_t.has_child_sa.
*/
static bool has_child_sa(private_ike_sa_t *this, u_int32_t reqid)
{
iterator_t *iterator;
child_sa_t *current;
bool found = FALSE;
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&current))
{
if (current->get_reqid(current) == reqid)
{
found = TRUE;
break;
}
}
iterator->destroy(iterator);
return found;
}
/**
* Implementation of protected_ike_sa_t.get_child_sa.
*/
@@ -1226,12 +1503,12 @@ static child_sa_t* get_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
iterator_t *iterator;
child_sa_t *current, *found = NULL;
iterator = this->child_sas->create_iterator(this->child_sas, FALSE);
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&current);
if (current->get_spi(current, inbound) == spi &&
current->get_protocol(current) == protocol)
current->get_protocol(current) == protocol)
{
found = current;
}
@@ -1353,17 +1630,28 @@ static void log_status(private_ike_sa_t *this, logger_t *logger, char *name)
*/
static status_t delete_(private_ike_sa_t *this)
{
delete_ike_sa_t *delete_ike_sa;
delete_ike_sa = delete_ike_sa_create(&this->public);
if (this->transaction_out)
switch (this->state)
{
/* already a transaction in progress. As this may hang
* around a while, we don't inform the other peer. */
return DESTROY_ME;
case IKE_CONNECTING:
case IKE_ESTABLISHED:
{
delete_ike_sa_t *delete_ike_sa;
delete_ike_sa = delete_ike_sa_create(&this->public);
if (this->transaction_out)
{
/* already a transaction in progress. As this may hang
* around a while, we don't inform the other peer. */
return DESTROY_ME;
}
return queue_transaction(this, (transaction_t*)delete_ike_sa, FALSE);
}
case IKE_CREATED:
case IKE_DELETING:
default:
{
return DESTROY_ME;
}
}
return queue_transaction(this, (transaction_t*)delete_ike_sa, FALSE);
}
/**
@@ -1483,7 +1771,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.set_name = (void(*)(ike_sa_t*,char*))set_name;
this->public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
this->public.initiate = (status_t(*)(ike_sa_t*,connection_t*,policy_t*)) initiate;
this->public.route = (status_t(*)(ike_sa_t*,policy_t*)) route;
this->public.route = (status_t(*)(ike_sa_t*,connection_t*,policy_t*)) route;
this->public.unroute = (status_t(*)(ike_sa_t*,policy_t*)) unroute;
this->public.acquire = (status_t(*)(ike_sa_t*,u_int32_t)) acquire;
this->public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
this->public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host;
@@ -1505,6 +1794,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.get_prf_auth_r = (prf_t *(*) (ike_sa_t *)) get_prf_auth_r;
this->public.build_transforms = (status_t (*) (ike_sa_t *,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t,bool)) build_transforms;
this->public.add_child_sa = (void (*) (ike_sa_t*,child_sa_t*)) add_child_sa;
this->public.has_child_sa = (bool(*)(ike_sa_t*,u_int32_t)) has_child_sa;
this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa;
this->public.rekey_child_sa = (status_t(*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa;
this->public.delete_child_sa = (status_t(*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa;
@@ -1517,10 +1807,10 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
this->name = strdup("(uninitialized)");
this->child_sas = linked_list_create();
this->my_host = NULL;
this->other_host = NULL;
this->my_id = NULL;
this->other_id = NULL;
this->my_host = host_create(AF_INET, "0.0.0.0", 0);
this->other_host = host_create(AF_INET, "0.0.0.0", 0);
this->my_id = identification_create_from_encoding(ID_ANY, CHUNK_INITIALIZER);
this->other_id = identification_create_from_encoding(ID_ANY, CHUNK_INITIALIZER);
this->crypter_in = NULL;
this->crypter_out = NULL;
this->signer_in = NULL;
+25 -5
View File
@@ -237,16 +237,27 @@ struct ike_sa_t {
*
* Installs the policies in the kernel. If traffic matches,
* the kernel requests connection setup from the IKE_SA via acquire().
* The policy is owned by the IKE_SA after the call, so
* do not modify or destroy it.
*
* @param this calling object
* @param connection connection definition used for routing
* @param policy policy to route
* @return
* - SUCCESS if routed successfully
* - FAILED if routing failed
*/
status_t (*route) (ike_sa_t *this, connection_t *connection, policy_t *policy);
/**
* @brief Unroute a policy in the kernel previously routed.
*
* @param this calling object
* @param policy policy to route
* @return
* - SUCCESS if initialization started
* - DESTROY_ME if initialization failed and IKE_SA MUST be deleted
* - SUCCESS if route removed
* - DESTROY_ME if last route was removed from
* an IKE_SA which was not established
*/
status_t (*route) (ike_sa_t *this, policy_t *policy);
status_t (*unroute) (ike_sa_t *this, policy_t *policy);
/**
* @brief Acquire connection setup for a policy.
@@ -435,6 +446,15 @@ struct ike_sa_t {
*/
void (*add_child_sa) (ike_sa_t *this, child_sa_t *child_sa);
/**
* @brief Check if an IKE_SA has one or more CHILD_SAs with a given reqid.
*
* @param this calling object
* @param reqid reqid of the CHILD
* @return TRUE if it has such a CHILD, FALSE if not
*/
bool (*has_child_sa) (ike_sa_t *this, u_int32_t reqid);
/**
* @brief Get a CHILD_SA identified by protocol and SPI.
*
+7 -9
View File
@@ -554,12 +554,11 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id
/**
* Implementation of of ike_sa_manager.checkout_by_child.
*/
static status_t checkout_by_child(private_ike_sa_manager_t *this,
protocol_id_t protocol, u_int32_t spi,
ike_sa_t **ike_sa)
static ike_sa_t* checkout_by_child(private_ike_sa_manager_t *this,
u_int32_t reqid)
{
iterator_t *iterator;
status_t status = NOT_FOUND;
ike_sa_t *ike_sa = NULL;
pthread_mutex_lock(&(this->mutex));
@@ -572,12 +571,11 @@ static status_t checkout_by_child(private_ike_sa_manager_t *this,
if (wait_for_entry(this, entry))
{
/* ok, access is exclusive for us, check for child */
if (entry->ike_sa->get_child_sa(entry->ike_sa, protocol, spi, TRUE) != NULL)
if (entry->ike_sa->has_child_sa(entry->ike_sa, reqid))
{
/* match */
entry->checked_out = TRUE;
*ike_sa = entry->ike_sa;
status = SUCCESS;
ike_sa = entry->ike_sa;
break;
}
}
@@ -585,7 +583,7 @@ static status_t checkout_by_child(private_ike_sa_manager_t *this,
iterator->destroy(iterator);
pthread_mutex_unlock(&(this->mutex));
return status;
return ike_sa;
}
/**
@@ -915,7 +913,7 @@ ike_sa_manager_t *ike_sa_manager_create()
this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
this->public.checkout_by_ids = (ike_sa_t*(*)(ike_sa_manager_t*,identification_t*,identification_t*))checkout_by_ids;
this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
this->public.checkout_by_child = (status_t(*)(ike_sa_manager_t*,protocol_id_t,u_int32_t,ike_sa_t**))checkout_by_child;
this->public.checkout_by_child = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t))checkout_by_child;
this->public.get_ike_sa_list = (linked_list_t*(*)(ike_sa_manager_t*))get_ike_sa_list;
this->public.get_ike_sa_list_by_name = (linked_list_t*(*)(ike_sa_manager_t*,const char*))get_ike_sa_list_by_name;
this->public.log_status = (void(*)(ike_sa_manager_t*,logger_t*,char*))log_status;
+4 -7
View File
@@ -92,15 +92,12 @@ struct ike_sa_manager_t {
* CHILD_SA the kernel wants to modify.
*
* @param this the manager object
* @param protocol protocol of the CHILD_SA
* @param spi SPI of the CHILD_SA
* @param[out] ike_sa checked out SA
* @param reqid reqid of the CHILD_SA
* @return
* - NOT_FOUND, if no IKE SA with such a child found
* - SUCCESS, if ike_sa set
* - checked out IKE_SA, if found
* - NULL, if not found
*/
status_t (*checkout_by_child) (ike_sa_manager_t* this, protocol_id_t protocol,
u_int32_t spi, ike_sa_t **ike_sa);
ike_sa_t* (*checkout_by_child) (ike_sa_manager_t* this, u_int32_t reqid);
/**
* @brief Get a list of all IKE_SA SAs currently set up.
+40 -20
View File
@@ -43,6 +43,7 @@
#include <utils/linked_list.h>
#include <queues/jobs/delete_child_sa_job.h>
#include <queues/jobs/rekey_child_sa_job.h>
#include <queues/jobs/acquire_job.h>
/** kernel level protocol identifiers */
#define KERNEL_ESP 50
@@ -342,44 +343,65 @@ static void receive_messages(private_kernel_interface_t *this)
break;
}
/* we handle ACQUIRE and EXPIRE messages directly
*/
/* we handle ACQUIRE and EXPIRE messages directly */
hdr = (struct nlmsghdr*)response;
if (hdr->nlmsg_type == XFRM_MSG_ACQUIRE)
{
struct xfrm_user_acquire *acquire;
acquire = (struct xfrm_user_acquire*)NLMSG_DATA(hdr);
this->logger->log(this->logger, CONTROL,
"Received a XFRM_MSG_ACQUIRE with index %d. Ignored",
acquire->policy.index);
u_int32_t reqid = 0;
job_t *job;
struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_user_acquire);
size_t rtsize = XFRM_PAYLOAD(hdr, struct xfrm_user_tmpl);
if (RTA_OK(rthdr, rtsize))
{
if (rthdr->rta_type == XFRMA_TMPL)
{
struct xfrm_user_tmpl* tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr);
reqid = tmpl->reqid;
}
}
if (reqid == 0)
{
this->logger->log(this->logger, ERROR,
"Received a XFRM_MSG_ACQUIRE, but no reqid found");
}
else
{
this->logger->log(this->logger, CONTROL|LEVEL1,
"Received a XFRM_MSG_ACQUIRE");
this->logger->log(this->logger, CONTROL,
"creating acquire job for CHILD_SA with reqid %d",
reqid);
job = (job_t*)acquire_job_create(reqid);
charon->job_queue->add(charon->job_queue, job);
}
}
else if (hdr->nlmsg_type == XFRM_MSG_EXPIRE)
{
job_t *job;
protocol_id_t protocol;
u_int32_t spi;
u_int32_t spi, reqid;
struct xfrm_user_expire *expire;
expire = (struct xfrm_user_expire*)NLMSG_DATA(hdr);
protocol = expire->state.id.proto == KERNEL_ESP ?
PROTO_ESP : PROTO_AH;
spi = expire->state.id.spi;
reqid = expire->state.reqid;
this->logger->log(this->logger, CONTROL|LEVEL1,
"Received a XFRM_MSG_EXPIRE");
this->logger->log(this->logger, CONTROL,
"creating %s job for %s CHILD_SA 0x%x",
"creating %s job for %s CHILD_SA 0x%x (reqid %d)",
expire->hard ? "delete" : "rekey",
mapping_find(protocol_id_m, protocol), ntohl(spi));
mapping_find(protocol_id_m, protocol), ntohl(spi),
reqid);
if (expire->hard)
{
job = (job_t*)delete_child_sa_job_create(protocol, spi);
job = (job_t*)delete_child_sa_job_create(reqid, protocol, spi);
}
else
{
job = (job_t*)rekey_child_sa_job_create(protocol, spi);
job = (job_t*)rekey_child_sa_job_create(reqid, protocol, spi);
}
charon->job_queue->add(charon->job_queue, job);
}
@@ -670,7 +692,7 @@ static status_t update_sa(
sa_id->spi = spi;
sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
sa_id->family = dst->get_family(dst);
POS;
if (send_message(this, hdr, &update) != SUCCESS)
{
this->logger->log(this->logger, ERROR, "netlink communication failed");
@@ -695,7 +717,6 @@ static status_t update_sa(
free(update);
return FAILED;
}
POS;
this->logger->log(this->logger, CONTROL|LEVEL2, "updating SA");
update->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
@@ -731,7 +752,7 @@ static status_t update_sa(
rthdr = RTA_NEXT(rthdr, rtsize);
}
}
POS;
if (send_message(this, update, &response) != SUCCESS)
{
this->logger->log(this->logger, ERROR, "netlink communication failed");
@@ -754,8 +775,7 @@ static status_t update_sa(
this->logger->log(this->logger, CONTROL|LEVEL2, "deleting old SA");
status = this->public.del_sa(&this->public, dst, spi, protocol);
}
POS;
free(update);
free(response);
return status;
@@ -1052,7 +1072,7 @@ static status_t add_policy(private_kernel_interface_t *this,
struct xfrm_user_tmpl *tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr);
tmpl->reqid = reqid;
tmpl->id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
tmpl->id.proto = (protocol == PROTO_AH) ? KERNEL_AH : KERNEL_ESP;
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
tmpl->mode = TRUE;
+57
View File
@@ -38,6 +38,7 @@
#include <daemon.h>
#include <crypto/x509.h>
#include <queues/jobs/initiate_job.h>
#include <queues/jobs/route_job.h>
#define IKE_PORT 500
#define PATH_BUF 256
@@ -518,6 +519,56 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
charon->job_queue->add(charon->job_queue, (job_t*)job);
}
/**
* route/unroute a policy (install SPD entries)
*/
static void stroke_route(private_stroke_t *this, stroke_msg_t *msg, bool route)
{
route_job_t *job;
connection_t *connection;
policy_t *policy;
pop_string(msg, &(msg->route.name));
this->logger->log(this->logger, CONTROL,
"received stroke: %s \"%s\"",
route ? "route" : "unroute",
msg->route.name);
/* we wouldn't need a connection, but we only want to route policies
* whose connections are keyexchange=ikev2. */
connection = charon->connections->get_connection_by_name(charon->connections,
msg->route.name);
if (connection == NULL)
{
this->stroke_logger->log(this->stroke_logger, ERROR,
"no connection named \"%s\"",
msg->route.name);
return;
}
if (!connection->is_ikev2(connection))
{
connection->destroy(connection);
return;
}
policy = charon->policies->get_policy_by_name(charon->policies,
msg->route.name);
if (policy == NULL)
{
this->stroke_logger->log(this->stroke_logger, ERROR,
"no policy named \"%s\"",
msg->route.name);
connection->destroy(connection);
return;
}
this->stroke_logger->log(this->stroke_logger, CONTROL,
"%s policy \"%s\"",
route ? "routing" : "unrouting",
msg->route.name);
job = route_job_create(connection, policy, route);
charon->job_queue->add(charon->job_queue, (job_t*)job);
}
/**
* terminate a connection by name
*/
@@ -795,6 +846,12 @@ static void stroke_receive(private_stroke_t *this)
case STR_INITIATE:
stroke_initiate(this, msg);
break;
case STR_ROUTE:
stroke_route(this, msg, TRUE);
break;
case STR_UNROUTE:
stroke_route(this, msg, FALSE);
break;
case STR_TERMINATE:
stroke_terminate(this, msg);
break;
+4
View File
@@ -174,6 +174,10 @@ route|unroute)
then
$IPSEC_WHACK --name "$1" "--$op"
fi
if test -e $IPSEC_CHARON_PID
then
$IPSEC_STROKE "$op" "$1"
fi
exit 0
;;
scencrypt|scdecrypt)
+3 -3
View File
@@ -159,7 +159,7 @@ int starter_stroke_del_conn(starter_conn_t *conn)
msg.type = STR_DEL_CONN;
msg.length = offsetof(stroke_msg_t, buffer);
msg.install.name = push_string(&msg, connection_name(conn));
msg.del_conn.name = push_string(&msg, connection_name(conn));
return send_stroke_msg(&msg);
}
@@ -167,9 +167,9 @@ int starter_stroke_route_conn(starter_conn_t *conn)
{
stroke_msg_t msg;
msg.type = STR_INSTALL;
msg.type = STR_ROUTE;
msg.length = offsetof(stroke_msg_t, buffer);
msg.install.name = push_string(&msg, connection_name(conn));
msg.route.name = push_string(&msg, connection_name(conn));
return send_stroke_msg(&msg);
}
+34
View File
@@ -169,6 +169,26 @@ static int terminate_connection(char *name)
return send_stroke_msg(&msg);
}
static int route_connection(char *name)
{
stroke_msg_t msg;
msg.type = STR_ROUTE;
msg.length = offsetof(stroke_msg_t, buffer);
msg.route.name = push_string(&msg, name);
return send_stroke_msg(&msg);
}
static int unroute_connection(char *name)
{
stroke_msg_t msg;
msg.type = STR_UNROUTE;
msg.length = offsetof(stroke_msg_t, buffer);
msg.unroute.name = push_string(&msg, name);
return send_stroke_msg(&msg);
}
static int show_status(stroke_keyword_t kw, char *connection)
{
stroke_msg_t msg;
@@ -336,6 +356,20 @@ int main(int argc, char *argv[])
}
res = terminate_connection(argv[2]);
break;
case STROKE_ROUTE:
if (argc < 3)
{
exit_usage("\"route\" needs a connection name");
}
res = route_connection(argv[2]);
break;
case STROKE_UNROUTE:
if (argc < 3)
{
exit_usage("\"unroute\" needs a connection name");
}
res = unroute_connection(argv[2]);
break;
case STROKE_LOGTYPE:
if (argc < 5)
{
+6 -4
View File
@@ -99,8 +99,10 @@ struct stroke_msg_t {
enum {
/* initiate a connection */
STR_INITIATE,
/* install SPD entries for a connection */
STR_INSTALL,
/* install SPD entries for a policy */
STR_ROUTE,
/* uninstall SPD entries for a policy */
STR_UNROUTE,
/* add a connection */
STR_ADD_CONN,
/* delete a connection */
@@ -123,10 +125,10 @@ struct stroke_msg_t {
} type;
union {
/* data for STR_INITIATE, STR_INSTALL, STR_UP, STR_DOWN, ... */
/* data for STR_INITIATE, STR_ROUTE, STR_UP, STR_DOWN, ... */
struct {
char *name;
} initiate, install, terminate, status, del_conn;
} initiate, route, unroute, terminate, status, del_conn;
/* data for STR_ADD_CONN */
struct {
+1
View File
@@ -23,6 +23,7 @@ typedef enum {
STROKE_DEL,
STROKE_DELETE,
STROKE_ROUTE,
STROKE_UNROUTE,
STROKE_UP,
STROKE_DOWN,
STROKE_LOGTYPE,
+1
View File
@@ -30,6 +30,7 @@ add, STROKE_ADD
del, STROKE_DEL
delete, STROKE_DELETE
route, STROKE_ROUTE
unroute, STROKE_UNROUTE
up, STROKE_UP
down, STROKE_DOWN
logtype, STROKE_LOGTYPE