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:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user