kernel-wfp: Triggering expire events for SAs to rekey/delete
This commit is contained in:
@@ -20,9 +20,11 @@
|
|||||||
#include "kernel_wfp_ipsec.h"
|
#include "kernel_wfp_ipsec.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
|
#include <hydra.h>
|
||||||
#include <threading/mutex.h>
|
#include <threading/mutex.h>
|
||||||
#include <collections/array.h>
|
#include <collections/array.h>
|
||||||
#include <collections/hashtable.h>
|
#include <collections/hashtable.h>
|
||||||
|
#include <processing/jobs/callback_job.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct private_kernel_wfp_ipsec_t private_kernel_wfp_ipsec_t;
|
typedef struct private_kernel_wfp_ipsec_t private_kernel_wfp_ipsec_t;
|
||||||
@@ -1012,6 +1014,103 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
|
|||||||
return NOT_SUPPORTED;
|
return NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for an expire callback job
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/* backref to kernel backend */
|
||||||
|
private_kernel_wfp_ipsec_t *this;
|
||||||
|
/* SPI of expiring SA */
|
||||||
|
u_int32_t spi;
|
||||||
|
/* destination address of expiring SA */
|
||||||
|
host_t *dst;
|
||||||
|
/* is this a hard expire, or a rekey request? */
|
||||||
|
bool hard;
|
||||||
|
} expire_data_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up expire data
|
||||||
|
*/
|
||||||
|
static void expire_data_destroy(expire_data_t *data)
|
||||||
|
{
|
||||||
|
data->dst->destroy(data->dst);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback job for SA expiration
|
||||||
|
*/
|
||||||
|
static job_requeue_t expire_job(expire_data_t *data)
|
||||||
|
{
|
||||||
|
private_kernel_wfp_ipsec_t *this = data->this;
|
||||||
|
u_int32_t reqid = 0;
|
||||||
|
u_int8_t protocol;
|
||||||
|
entry_t *entry;
|
||||||
|
sa_entry_t key = {
|
||||||
|
.spi = data->spi,
|
||||||
|
.dst = data->dst,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (data->hard)
|
||||||
|
{
|
||||||
|
this->mutex->lock(this->mutex);
|
||||||
|
entry = this->isas->remove(this->isas, &key);
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
protocol = entry->isa.protocol;
|
||||||
|
reqid = entry->reqid;
|
||||||
|
if (entry->osa.dst)
|
||||||
|
{
|
||||||
|
key.dst = entry->osa.dst;
|
||||||
|
key.spi = entry->osa.spi;
|
||||||
|
this->osas->remove(this->osas, &key);
|
||||||
|
}
|
||||||
|
entry_destroy(this, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->mutex->lock(this->mutex);
|
||||||
|
entry = this->isas->get(this->isas, &key);
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
protocol = entry->isa.protocol;
|
||||||
|
reqid = entry->reqid;
|
||||||
|
}
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reqid)
|
||||||
|
{
|
||||||
|
hydra->kernel_interface->expire(hydra->kernel_interface,
|
||||||
|
reqid, protocol, data->spi, data->hard);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JOB_REQUEUE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule an expire event for an SA
|
||||||
|
*/
|
||||||
|
static void schedule_expire(private_kernel_wfp_ipsec_t *this, u_int32_t spi,
|
||||||
|
host_t *dst, u_int32_t lifetime, bool hard)
|
||||||
|
{
|
||||||
|
expire_data_t *data;
|
||||||
|
|
||||||
|
INIT(data,
|
||||||
|
.this = this,
|
||||||
|
.spi = spi,
|
||||||
|
.dst = dst->clone(dst),
|
||||||
|
.hard = hard,
|
||||||
|
);
|
||||||
|
|
||||||
|
lib->scheduler->schedule_job(lib->scheduler, (job_t*)
|
||||||
|
callback_job_create((void*)expire_job, data,
|
||||||
|
(void*)expire_data_destroy, NULL),
|
||||||
|
lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(kernel_ipsec_t, add_sa, status_t,
|
METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||||
private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
|
private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
|
u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
|
||||||
@@ -1052,6 +1151,15 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
|||||||
.encap = encap,
|
.encap = encap,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (lifetime->time.life)
|
||||||
|
{
|
||||||
|
schedule_expire(this, spi, local, lifetime->time.life, TRUE);
|
||||||
|
}
|
||||||
|
if (lifetime->time.rekey && lifetime->time.rekey != lifetime->time.life)
|
||||||
|
{
|
||||||
|
schedule_expire(this, spi, local, lifetime->time.rekey, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
this->mutex->lock(this->mutex);
|
this->mutex->lock(this->mutex);
|
||||||
this->tsas->put(this->tsas, (void*)(uintptr_t)reqid, entry);
|
this->tsas->put(this->tsas, (void*)(uintptr_t)reqid, entry);
|
||||||
this->isas->put(this->isas, &entry->isa, entry);
|
this->isas->put(this->isas, &entry->isa, entry);
|
||||||
|
|||||||
Reference in New Issue
Block a user