job management:
moved job code from thread_pool to job, jobs have an "execute" method now added two new jobs: delete_child_sa & rekey_child_sa kernel interface: listens now for ACQUIRE & EXPIRE supports hard and soft lifetimes fires jobs for delete and rekey child sa ike sa manager: can checkout IKE SAs by requid of owned CHILD SAs we have now the infrastructure to do the rekeying... :-)
This commit is contained in:
parent
6f2aba1322
commit
32b6500fbf
|
@ -38,6 +38,8 @@ queues/jobs/delete_established_ike_sa_job.c queues/jobs/retransmit_request_job.h
|
|||
queues/jobs/incoming_packet_job.c queues/jobs/delete_half_open_ike_sa_job.c \
|
||||
queues/jobs/delete_established_ike_sa_job.h queues/jobs/delete_half_open_ike_sa_job.h \
|
||||
queues/jobs/incoming_packet_job.h queues/jobs/retransmit_request_job.c queues/jobs/initiate_ike_sa_job.c \
|
||||
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/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 \
|
||||
|
|
|
@ -184,6 +184,32 @@ static payload_rule_t informational_r_payload_rules[] = {
|
|||
{DELETE,0,1,TRUE,FALSE},
|
||||
};
|
||||
|
||||
/**
|
||||
* Message rule for CREATE_CHILD_SA from initiator.
|
||||
*/
|
||||
static payload_rule_t create_child_sa_r_payload_rules[] = {
|
||||
{NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE},
|
||||
{SECURITY_ASSOCIATION,1,1,TRUE,FALSE},
|
||||
{NONCE,1,1,TRUE,FALSE},
|
||||
{KEY_EXCHANGE,0,1,TRUE,FALSE},
|
||||
{TRAFFIC_SELECTOR_INITIATOR,0,1,TRUE,FALSE},
|
||||
{TRAFFIC_SELECTOR_RESPONDER,0,1,TRUE,FALSE},
|
||||
{CONFIGURATION,0,1,TRUE,FALSE},
|
||||
};
|
||||
|
||||
/**
|
||||
* Message rule for CREATE_CHILD_SA from responder.
|
||||
*/
|
||||
static payload_rule_t create_child_sa_i_payload_rules[] = {
|
||||
{NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE},
|
||||
{SECURITY_ASSOCIATION,1,1,TRUE,FALSE},
|
||||
{NONCE,1,1,TRUE,FALSE},
|
||||
{KEY_EXCHANGE,0,1,TRUE,FALSE},
|
||||
{TRAFFIC_SELECTOR_INITIATOR,0,1,TRUE,FALSE},
|
||||
{TRAFFIC_SELECTOR_RESPONDER,0,1,TRUE,FALSE},
|
||||
{CONFIGURATION,0,1,TRUE,FALSE},
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Message rules, defines allowed payloads.
|
||||
|
|
|
@ -306,7 +306,7 @@ static void event_queue_destroy(private_event_queue_t *this)
|
|||
this->list->destroy(this->list);
|
||||
break;
|
||||
}
|
||||
event->job->destroy_all(event->job);
|
||||
event->job->destroy(event->job);
|
||||
event->destroy(event);
|
||||
}
|
||||
this->list->destroy(this->list);
|
||||
|
|
|
@ -121,7 +121,7 @@ static void job_queue_destroy (private_job_queue_t *this)
|
|||
this->list->destroy(this->list);
|
||||
break;
|
||||
}
|
||||
job->destroy_all(job);
|
||||
job->destroy(job);
|
||||
}
|
||||
this->list->destroy(this->list);
|
||||
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* @file delete_child_sa_job.c
|
||||
*
|
||||
* @brief Implementation of delete_child_sa_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 "delete_child_sa_job.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
|
||||
typedef struct private_delete_child_sa_job_t private_delete_child_sa_job_t;
|
||||
|
||||
/**
|
||||
* Private data of an delete_child_sa_job_t object.
|
||||
*/
|
||||
struct private_delete_child_sa_job_t {
|
||||
/**
|
||||
* Public delete_child_sa_job_t interface.
|
||||
*/
|
||||
delete_child_sa_job_t public;
|
||||
|
||||
/**
|
||||
* reqid of the sa to delete.
|
||||
*/
|
||||
u_int32_t reqid;
|
||||
|
||||
/**
|
||||
* Logger ref
|
||||
*/
|
||||
logger_t *logger;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of job_t.get_type.
|
||||
*/
|
||||
static job_type_t get_type(private_delete_child_sa_job_t *this)
|
||||
{
|
||||
return DELETE_CHILD_SA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of job_t.execute.
|
||||
*/
|
||||
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_reqid(charon->ike_sa_manager, this->reqid, &ike_sa);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL, "CHILD SA didn't exist anymore");
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
|
||||
status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of job_t.destroy.
|
||||
*/
|
||||
static void destroy(private_delete_child_sa_job_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid)
|
||||
{
|
||||
private_delete_child_sa_job_t *this = malloc_thing(private_delete_child_sa_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);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* @file delete_child_sa_job.h
|
||||
*
|
||||
* @brief Interface of delete_child_sa_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 DELETE_CHILD_SA_JOB_H_
|
||||
#define DELETE_CHILD_SA_JOB_H_
|
||||
|
||||
#include <types.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
#include <queues/jobs/job.h>
|
||||
|
||||
|
||||
typedef struct delete_child_sa_job_t delete_child_sa_job_t;
|
||||
|
||||
/**
|
||||
* @brief Class representing an DELETE_CHILD_SA Job.
|
||||
*
|
||||
* This job initiates the deletion of an CHILD_SA. The SA
|
||||
* to delete is specified via the unique reqid used in kernel.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - delete_child_sa_job_create()
|
||||
*
|
||||
* @ingroup jobs
|
||||
*/
|
||||
struct delete_child_sa_job_t {
|
||||
/**
|
||||
* The job_t interface.
|
||||
*/
|
||||
job_t job_interface;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a job of type DELETE_CHILD_SA.
|
||||
*
|
||||
* To find the targeted CHILD_SA, the uniqe reqid used in
|
||||
* the kernel is used.
|
||||
*
|
||||
* @param reqid reqid CHILD_SA to rekey
|
||||
*
|
||||
* @ingroup jobs
|
||||
*/
|
||||
delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid);
|
||||
|
||||
#endif /* DELETE_CHILD_SA_JOB_H_ */
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "delete_established_ike_sa_job.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
|
||||
typedef struct private_delete_established_ike_sa_job_t private_delete_established_ike_sa_job_t;
|
||||
|
@ -39,6 +40,11 @@ struct private_delete_established_ike_sa_job_t {
|
|||
* ID of the ike_sa to delete.
|
||||
*/
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
|
||||
/**
|
||||
* Logger ref
|
||||
*/
|
||||
logger_t *logger;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -49,12 +55,21 @@ static job_type_t get_type(private_delete_established_ike_sa_job_t *this)
|
|||
return DELETE_ESTABLISHED_IKE_SA;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of delete_established_ike_sa_job_t.get_ike_sa_id
|
||||
* Implementation of job_t.execute.
|
||||
*/
|
||||
static ike_sa_id_t *get_ike_sa_id(private_delete_established_ike_sa_job_t *this)
|
||||
static status_t execute(private_delete_established_ike_sa_job_t *this)
|
||||
{
|
||||
return this->ike_sa_id;
|
||||
ike_sa_t *ike_sa;
|
||||
status_t status;
|
||||
|
||||
status = charon->ike_sa_manager->delete(charon->ike_sa_manager, this->ike_sa_id);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL, "IKE SA didn't exist anymore");
|
||||
}
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,16 +90,12 @@ delete_established_ike_sa_job_t *delete_established_ike_sa_job_create(ike_sa_id_
|
|||
|
||||
/* interface functions */
|
||||
this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
|
||||
/* same as destroy */
|
||||
this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy;
|
||||
this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
|
||||
this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
|
||||
|
||||
/* public functions */
|
||||
this->public.get_ike_sa_id = (ike_sa_id_t * (*)(delete_established_ike_sa_job_t *)) get_ike_sa_id;
|
||||
this->public.destroy = (void (*)(delete_established_ike_sa_job_t *)) destroy;
|
||||
|
||||
|
||||
/* private variables */
|
||||
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
|
||||
this->logger = logger_manager->get_logger(logger_manager, WORKER);
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
|
|
|
@ -46,23 +46,6 @@ struct delete_established_ike_sa_job_t {
|
|||
* The job_t interface.
|
||||
*/
|
||||
job_t job_interface;
|
||||
|
||||
/**
|
||||
* @brief Returns the currently set ike_sa_id.
|
||||
*
|
||||
* @warning Returned object is not copied.
|
||||
*
|
||||
* @param this calling delete_established_ike_sa_job_t object
|
||||
* @return ike_sa_id_t object
|
||||
*/
|
||||
ike_sa_id_t * (*get_ike_sa_id) (delete_established_ike_sa_job_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys an delete_established_ike_sa_job_t object (including assigned data).
|
||||
*
|
||||
* @param this delete_established_ike_sa_job_t object to destroy
|
||||
*/
|
||||
void (*destroy) (delete_established_ike_sa_job_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "delete_half_open_ike_sa_job.h"
|
||||
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct private_delete_half_open_ike_sa_job_t private_delete_half_open_ike_sa_job_t;
|
||||
|
||||
|
@ -39,6 +39,11 @@ struct private_delete_half_open_ike_sa_job_t {
|
|||
* ID of the ike_sa to delete
|
||||
*/
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
|
||||
/**
|
||||
* logger ref
|
||||
*/
|
||||
logger_t *logger;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -50,11 +55,48 @@ static job_type_t get_type(private_delete_half_open_ike_sa_job_t *this)
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements elete_ike_sa_job_t.get_ike_sa_id
|
||||
* Implementation of job_t.execute.
|
||||
*/
|
||||
static ike_sa_id_t *get_ike_sa_id(private_delete_half_open_ike_sa_job_t *this)
|
||||
static status_t execute(private_delete_half_open_ike_sa_job_t *this)
|
||||
{
|
||||
return this->ike_sa_id;
|
||||
ike_sa_t *ike_sa;
|
||||
status_t status;
|
||||
|
||||
status = charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->ike_sa_id, &ike_sa);
|
||||
if ((status != SUCCESS) && (status != CREATED))
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "IKE SA seems to be already deleted");
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
switch (ike_sa->get_state(ike_sa))
|
||||
{
|
||||
case INITIATOR_INIT:
|
||||
case RESPONDER_INIT:
|
||||
case IKE_SA_INIT_REQUESTED:
|
||||
case IKE_SA_INIT_RESPONDED:
|
||||
case IKE_AUTH_REQUESTED:
|
||||
case DELETE_REQUESTED:
|
||||
{
|
||||
/* IKE_SA is half open and gets deleted! */
|
||||
status = charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "Could not checkin and delete checked out IKE_SA!");
|
||||
}
|
||||
return DESTROY_ME;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* IKE_SA is established and so is not getting deleted! */
|
||||
status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "Could not checkin a checked out IKE_SA!");
|
||||
}
|
||||
return DESTROY_ME;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,16 +117,12 @@ delete_half_open_ike_sa_job_t *delete_half_open_ike_sa_job_create(ike_sa_id_t *i
|
|||
|
||||
/* interface functions */
|
||||
this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
|
||||
/* same as destroy */
|
||||
this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy;
|
||||
this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
|
||||
this->public.job_interface.destroy = (void (*)(job_t *)) destroy;;
|
||||
|
||||
/* public functions */
|
||||
this->public.get_ike_sa_id = (ike_sa_id_t * (*)(delete_half_open_ike_sa_job_t *)) get_ike_sa_id;
|
||||
this->public.destroy = (void (*)(delete_half_open_ike_sa_job_t *)) destroy;
|
||||
|
||||
/* private variables */
|
||||
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
|
||||
this->logger = logger_manager->get_logger(logger_manager, WORKER);
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
|
|
|
@ -47,23 +47,6 @@ struct delete_half_open_ike_sa_job_t {
|
|||
* The job_t interface.
|
||||
*/
|
||||
job_t job_interface;
|
||||
|
||||
/**
|
||||
* @brief Returns the currently set ike_sa_id.
|
||||
*
|
||||
* @warning Returned object is not copied.
|
||||
*
|
||||
* @param this calling delete_half_open_ike_sa_job_t object
|
||||
* @return ike_sa_id_t object
|
||||
*/
|
||||
ike_sa_id_t * (*get_ike_sa_id) (delete_half_open_ike_sa_job_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys an delete_half_open_ike_sa_job_t object (including assigned data).
|
||||
*
|
||||
* @param this delete_half_open_ike_sa_job_t object to destroy
|
||||
*/
|
||||
void (*destroy) (delete_half_open_ike_sa_job_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "incoming_packet_job.h"
|
||||
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct private_incoming_packet_job_t private_incoming_packet_job_t;
|
||||
|
||||
|
@ -40,6 +40,11 @@ struct private_incoming_packet_job_t {
|
|||
* Assigned packet
|
||||
*/
|
||||
packet_t *packet;
|
||||
|
||||
/**
|
||||
* logger
|
||||
*/
|
||||
logger_t *logger;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -50,32 +55,133 @@ static job_type_t get_type(private_incoming_packet_job_t *this)
|
|||
return INCOMING_PACKET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of job_t.execute.
|
||||
*/
|
||||
static status_t execute(private_incoming_packet_job_t *this)
|
||||
{
|
||||
message_t *message;
|
||||
ike_sa_t *ike_sa;
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
status_t status;
|
||||
packet_t *packet;
|
||||
|
||||
message = message_create_from_packet(this->packet->clone(this->packet));
|
||||
status = message->parse_header(message);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "Message header could not be verified!");
|
||||
message->destroy(message);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Message is a %s %s",
|
||||
mapping_find(exchange_type_m, message->get_exchange_type(message)),
|
||||
message->get_request(message) ? "request" : "reply");
|
||||
|
||||
if ((message->get_major_version(message) != IKE_MAJOR_VERSION) ||
|
||||
(message->get_minor_version(message) != IKE_MINOR_VERSION))
|
||||
{
|
||||
this->logger->log(this->logger, ERROR | LEVEL2,
|
||||
"IKE version %d.%d not supported",
|
||||
message->get_major_version(message),
|
||||
message->get_minor_version(message));
|
||||
if ((message->get_exchange_type(message) == IKE_SA_INIT) && (message->get_request(message)))
|
||||
{
|
||||
message_t *response;
|
||||
message->get_ike_sa_id(message, &ike_sa_id);
|
||||
ike_sa_id->switch_initiator(ike_sa_id);
|
||||
response = message_create_notify_reply(message->get_destination(message),
|
||||
message->get_source(message),
|
||||
IKE_SA_INIT, FALSE, ike_sa_id,
|
||||
INVALID_MAJOR_VERSION);
|
||||
message->destroy(message);
|
||||
ike_sa_id->destroy(ike_sa_id);
|
||||
status = response->generate(response, NULL, NULL, &packet);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "Could not generate packet from message");
|
||||
response->destroy(response);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
this->logger->log(this->logger, ERROR, "Send notify reply of type INVALID_MAJOR_VERSION");
|
||||
charon->send_queue->add(charon->send_queue, packet);
|
||||
response->destroy(response);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
message->destroy(message);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
message->get_ike_sa_id(message, &ike_sa_id);
|
||||
ike_sa_id->switch_initiator(ike_sa_id);
|
||||
this->logger->log(this->logger, CONTROL|LEVEL3, "Checking out IKE SA %lld:%lld, role %s",
|
||||
ike_sa_id->get_initiator_spi(ike_sa_id),
|
||||
ike_sa_id->get_responder_spi(ike_sa_id),
|
||||
ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
|
||||
|
||||
status = charon->ike_sa_manager->checkout(charon->ike_sa_manager, ike_sa_id, &ike_sa);
|
||||
if ((status != SUCCESS) && (status != CREATED))
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "IKE SA could not be checked out");
|
||||
ike_sa_id->destroy(ike_sa_id);
|
||||
message->destroy(message);
|
||||
|
||||
/* TODO: send notify reply of type INVALID_IKE_SPI if SPI could not be found ? */
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
if (status == CREATED)
|
||||
{
|
||||
job_t *delete_job;
|
||||
this->logger->log(this->logger, CONTROL|LEVEL3,
|
||||
"Create Job to delete half open IKE_SA.");
|
||||
|
||||
delete_job = (job_t *) delete_half_open_ike_sa_job_create(ike_sa_id);
|
||||
charon->event_queue->add_relative(charon->event_queue, delete_job,
|
||||
charon->configuration->get_half_open_ike_sa_timeout(charon->configuration));
|
||||
}
|
||||
|
||||
status = ike_sa->process_message(ike_sa, message);
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL3, "%s IKE SA %lld:%lld, role %s",
|
||||
status == DESTROY_ME ? "Checkin and delete" : "Checkin",
|
||||
ike_sa_id->get_initiator_spi(ike_sa_id),
|
||||
ike_sa_id->get_responder_spi(ike_sa_id),
|
||||
ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
|
||||
ike_sa_id->destroy(ike_sa_id);
|
||||
|
||||
if (status == DESTROY_ME)
|
||||
{
|
||||
status = charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "Checkin of IKE SA failed!");
|
||||
}
|
||||
message->destroy(message);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements incoming_packet_job_t.get_packet.
|
||||
*/
|
||||
static packet_t *get_packet(private_incoming_packet_job_t *this)
|
||||
static packet_t* get_packet(private_incoming_packet_job_t *this)
|
||||
{
|
||||
return this->packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements job_t.destroy_all.
|
||||
*/
|
||||
static void destroy_all(private_incoming_packet_job_t *this)
|
||||
{
|
||||
if (this->packet != NULL)
|
||||
{
|
||||
this->packet->destroy(this->packet);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements job_t.destroy.
|
||||
*/
|
||||
static void destroy(job_t *job)
|
||||
static void destroy(private_incoming_packet_job_t *this)
|
||||
{
|
||||
private_incoming_packet_job_t *this = (private_incoming_packet_job_t *) job;
|
||||
this->packet->destroy(this->packet);
|
||||
free(this);
|
||||
}
|
||||
|
||||
|
@ -88,15 +194,14 @@ incoming_packet_job_t *incoming_packet_job_create(packet_t *packet)
|
|||
|
||||
/* interface functions */
|
||||
this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
|
||||
this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy_all;
|
||||
this->public.job_interface.destroy = destroy;
|
||||
this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
|
||||
this->public.job_interface.destroy = (void(*)(job_t*))destroy;
|
||||
|
||||
/* public functions */
|
||||
this->public.get_packet = (packet_t * (*)(incoming_packet_job_t *)) get_packet;
|
||||
this->public.destroy = (void (*)(incoming_packet_job_t *)) destroy;
|
||||
this->public.get_packet = (packet_t*(*)(incoming_packet_job_t*)) get_packet;
|
||||
|
||||
/* private variables */
|
||||
this->packet = packet;
|
||||
this->logger = logger_manager->get_logger(logger_manager, WORKER);
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
|
|
|
@ -48,21 +48,12 @@ struct incoming_packet_job_t {
|
|||
job_t job_interface;
|
||||
|
||||
/**
|
||||
* @brief Returns the assigned packet_t object
|
||||
*
|
||||
* @warning Returned packet is not cloned and has to get destroyed by the caller.
|
||||
* @brief Get associated packet.
|
||||
*
|
||||
* @param this calling incoming_packet_job_t object
|
||||
* @return assigned packet
|
||||
* @param this calling object
|
||||
* @return associated packet
|
||||
*/
|
||||
packet_t *(*get_packet) (incoming_packet_job_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys an incoming_packet_job_t object.
|
||||
*
|
||||
* @param this incoming_packet_job_t object to destroy
|
||||
*/
|
||||
void (*destroy) (incoming_packet_job_t *this);
|
||||
packet_t *(*get_packet)(incoming_packet_job_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include "initiate_ike_sa_job.h"
|
||||
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct private_initiate_ike_sa_job_t private_initiate_ike_sa_job_t;
|
||||
|
||||
|
@ -42,9 +42,13 @@ struct private_initiate_ike_sa_job_t {
|
|||
* associated connection object to initiate
|
||||
*/
|
||||
connection_t *connection;
|
||||
|
||||
/**
|
||||
* logger
|
||||
*/
|
||||
logger_t *logger;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Implements initiate_ike_sa_job_t.get_type.
|
||||
*/
|
||||
|
@ -54,20 +58,46 @@ static job_type_t get_type(private_initiate_ike_sa_job_t *this)
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements initiate_ike_sa_job_t.get_configuration_name.
|
||||
* Implementation of job_t.execute.
|
||||
*/
|
||||
static connection_t *get_connection(private_initiate_ike_sa_job_t *this)
|
||||
static status_t execute(private_initiate_ike_sa_job_t *this)
|
||||
{
|
||||
return this->connection;
|
||||
}
|
||||
/*
|
||||
* Initiatie an IKE_SA:
|
||||
* - is defined by a name of a configuration
|
||||
* - create an empty IKE_SA via manager
|
||||
* - call initiate_connection on this sa
|
||||
*/
|
||||
ike_sa_t *ike_sa;
|
||||
status_t status;
|
||||
job_t *delete_job;
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Creating and checking out IKE SA");
|
||||
charon->ike_sa_manager->create_and_checkout(charon->ike_sa_manager, &ike_sa);
|
||||
|
||||
status = ike_sa->initiate_connection(ike_sa, this->connection->clone(this->connection));
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "Initiation returned %s, going to delete IKE_SA.",
|
||||
mapping_find(status_m, status));
|
||||
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL3, "Create Job to delete half open IKE_SA.");
|
||||
|
||||
delete_job = (job_t *) delete_half_open_ike_sa_job_create(ike_sa->get_id(ike_sa));
|
||||
charon->event_queue->add_relative(charon->event_queue, delete_job,
|
||||
charon->configuration->get_half_open_ike_sa_timeout(charon->configuration));
|
||||
|
||||
/**
|
||||
* Implements job_t.destroy.
|
||||
*/
|
||||
static void destroy_all(private_initiate_ike_sa_job_t *this)
|
||||
{
|
||||
this->connection->destroy(this->connection);
|
||||
free(this);
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Checking in IKE SA");
|
||||
status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "Could not checkin IKE_SA (%s)",
|
||||
mapping_find(status_m, status));
|
||||
}
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,6 +105,7 @@ static void destroy_all(private_initiate_ike_sa_job_t *this)
|
|||
*/
|
||||
static void destroy(private_initiate_ike_sa_job_t *this)
|
||||
{
|
||||
this->connection->destroy(this->connection);
|
||||
free(this);
|
||||
}
|
||||
|
||||
|
@ -87,15 +118,12 @@ initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection)
|
|||
|
||||
/* interface functions */
|
||||
this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
|
||||
this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy_all;
|
||||
this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
|
||||
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||
|
||||
/* public functions */
|
||||
this->public.get_connection = (connection_t* (*)(initiate_ike_sa_job_t *)) get_connection;
|
||||
this->public.destroy = (void (*)(initiate_ike_sa_job_t *)) destroy;
|
||||
|
||||
/* private variables */
|
||||
this->connection = connection;
|
||||
this->logger = logger_manager->get_logger(logger_manager, WORKER);
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
|
|
|
@ -45,21 +45,6 @@ struct initiate_ike_sa_job_t {
|
|||
* implements job_t interface
|
||||
*/
|
||||
job_t job_interface;
|
||||
|
||||
/**
|
||||
* @brief Returns the connection_t to initialize
|
||||
*
|
||||
* @param this calling initiate_ike_sa_job_t object
|
||||
* @return connection_t
|
||||
*/
|
||||
connection_t *(*get_connection) (initiate_ike_sa_job_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys an initiate_ike_sa_job_t object.
|
||||
*
|
||||
* @param this initiate_ike_sa_job_t object to destroy
|
||||
*/
|
||||
void (*destroy) (initiate_ike_sa_job_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,43 +32,57 @@ typedef enum job_type_t job_type_t;
|
|||
/**
|
||||
* @brief Definition of the various job types.
|
||||
*
|
||||
* @todo add more jobs, such as rekeying.
|
||||
*
|
||||
* @ingroup jobs
|
||||
*/
|
||||
enum job_type_t {
|
||||
/**
|
||||
* Process an incoming IKEv2-Message.
|
||||
*
|
||||
* Job is implemented in class type incoming_packet_job_t
|
||||
* Job is implemented in class incoming_packet_job_t
|
||||
*/
|
||||
INCOMING_PACKET,
|
||||
|
||||
/**
|
||||
* Retransmit an IKEv2-Message.
|
||||
*
|
||||
* Job is implemented in class retransmit_request_job_t
|
||||
*/
|
||||
RETRANSMIT_REQUEST,
|
||||
|
||||
/**
|
||||
* Establish an ike sa as initiator.
|
||||
*
|
||||
* Job is implemented in class type initiate_ike_sa_job_t
|
||||
* Job is implemented in class initiate_ike_sa_job_t
|
||||
*/
|
||||
INITIATE_IKE_SA,
|
||||
|
||||
/**
|
||||
* Delete an ike sa which is still not established.
|
||||
*
|
||||
* Job is implemented in class type delete_half_open_ike_sa_job_t
|
||||
* Job is implemented in class delete_half_open_ike_sa_job_t
|
||||
*/
|
||||
DELETE_HALF_OPEN_IKE_SA,
|
||||
|
||||
/**
|
||||
* Delete an ike sa which is established.
|
||||
*
|
||||
* Job is implemented in class type delete_established_ike_sa_job_t
|
||||
* Job is implemented in class delete_established_ike_sa_job_t
|
||||
*/
|
||||
DELETE_ESTABLISHED_IKE_SA
|
||||
DELETE_ESTABLISHED_IKE_SA,
|
||||
|
||||
/**
|
||||
* Delete a child sa.
|
||||
*
|
||||
* Job is implemented in class delete_child_sa_job_t
|
||||
*/
|
||||
DELETE_CHILD_SA,
|
||||
|
||||
/**
|
||||
* Rekey a child sa.
|
||||
*
|
||||
* Job is implemented in class rekey_child_sa_job_t
|
||||
*/
|
||||
REKEY_CHILD_SA,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -102,11 +116,16 @@ struct job_t {
|
|||
job_type_t (*get_type) (job_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys a job_t object and all assigned data!
|
||||
* @brief Execute a job.
|
||||
*
|
||||
* @param job_t calling object
|
||||
* Call the internall job routine to process the
|
||||
* job. If this method returns DESTROY_ME, the job
|
||||
* must be destroyed by the caller.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return status of job execution
|
||||
*/
|
||||
void (*destroy_all) (job_t *job);
|
||||
status_t (*execute) (job_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys a job_t object
|
||||
|
@ -117,4 +136,4 @@ struct job_t {
|
|||
};
|
||||
|
||||
|
||||
#endif /*JOB_H_*/
|
||||
#endif /* JOB_H_ */
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* @file rekey_child_sa_job.c
|
||||
*
|
||||
* @brief Implementation of rekey_child_sa_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 "rekey_child_sa_job.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
|
||||
typedef struct private_rekey_child_sa_job_t private_rekey_child_sa_job_t;
|
||||
|
||||
/**
|
||||
* Private data of an rekey_child_sa_job_t object.
|
||||
*/
|
||||
struct private_rekey_child_sa_job_t {
|
||||
/**
|
||||
* Public rekey_child_sa_job_t interface.
|
||||
*/
|
||||
rekey_child_sa_job_t public;
|
||||
|
||||
/**
|
||||
* reqid of the child sa, as used in the kernel
|
||||
*/
|
||||
u_int32_t reqid;
|
||||
|
||||
/**
|
||||
* Logger ref
|
||||
*/
|
||||
logger_t *logger;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of job_t.get_type.
|
||||
*/
|
||||
static job_type_t get_type(private_rekey_child_sa_job_t *this)
|
||||
{
|
||||
return REKEY_CHILD_SA;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of job_t.execute.
|
||||
*/
|
||||
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_reqid(charon->ike_sa_manager, this->reqid, &ike_sa);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL, "CHILD SA didn't exist anymore");
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
|
||||
status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of job_t.destroy.
|
||||
*/
|
||||
static void destroy(private_rekey_child_sa_job_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid)
|
||||
{
|
||||
private_rekey_child_sa_job_t *this = malloc_thing(private_rekey_child_sa_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);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* @file rekey_child_sa_job.h
|
||||
*
|
||||
* @brief Interface of rekey_child_sa_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 REKEY_CHILD_SA_JOB_H_
|
||||
#define REKEY_CHILD_SA_JOB_H_
|
||||
|
||||
#include <types.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
#include <queues/jobs/job.h>
|
||||
|
||||
|
||||
typedef struct rekey_child_sa_job_t rekey_child_sa_job_t;
|
||||
|
||||
/**
|
||||
* @brief Class representing an REKEY_CHILD_SA Job.
|
||||
*
|
||||
* This job initiates the rekeying of a CHILD SA.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - rekey_child_sa_job_create()
|
||||
*
|
||||
* @ingroup jobs
|
||||
*/
|
||||
struct rekey_child_sa_job_t {
|
||||
/**
|
||||
* The job_t interface.
|
||||
*/
|
||||
job_t job_interface;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a job of type REKEY_CHILD_SA.
|
||||
*
|
||||
* To find the targeted CHILD_SA, the uniqe reqid used in
|
||||
* the kernel is used.
|
||||
*
|
||||
* @param reqid reqid CHILD_SA to rekey
|
||||
* @return rekey_child_sa_job_t object
|
||||
*
|
||||
* @ingroup jobs
|
||||
*/
|
||||
rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid);
|
||||
|
||||
#endif /* REKEY_CHILD_SA_JOB_H_ */
|
|
@ -22,8 +22,7 @@
|
|||
|
||||
#include "retransmit_request_job.h"
|
||||
|
||||
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct private_retransmit_request_job_t private_retransmit_request_job_t;
|
||||
|
||||
|
@ -50,9 +49,13 @@ struct private_retransmit_request_job_t {
|
|||
* Number of times a request was retransmitted
|
||||
*/
|
||||
u_int32_t retransmit_count;
|
||||
|
||||
/**
|
||||
* Logger reference
|
||||
*/
|
||||
logger_t *logger;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Implements job_t.get_type.
|
||||
*/
|
||||
|
@ -62,38 +65,64 @@ static job_type_t get_type(private_retransmit_request_job_t *this)
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements retransmit_request_job_t.get_ike_sa_id.
|
||||
* Implementation of job_t.execute.
|
||||
*/
|
||||
static ike_sa_id_t *get_ike_sa_id(private_retransmit_request_job_t *this)
|
||||
static status_t execute(private_retransmit_request_job_t *this)
|
||||
{
|
||||
return this->ike_sa_id;
|
||||
}
|
||||
bool stop_retransmitting = FALSE;
|
||||
u_int32_t timeout;
|
||||
ike_sa_t *ike_sa;
|
||||
status_t status;
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Checking out IKE SA %lld:%lld, role %s",
|
||||
this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
|
||||
this->ike_sa_id->get_responder_spi(this->ike_sa_id),
|
||||
this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
|
||||
|
||||
status = charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->ike_sa_id, &ike_sa);
|
||||
if ((status != SUCCESS) && (status != CREATED))
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1,
|
||||
"IKE SA could not be checked out. Already deleted?");
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
status = ike_sa->retransmit_request(ike_sa, this->message_id);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL|LEVEL3,
|
||||
"Message doesn't have to be retransmitted");
|
||||
stop_retransmitting = TRUE;
|
||||
}
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Checkin IKE SA %lld:%lld, role %s",
|
||||
this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
|
||||
this->ike_sa_id->get_responder_spi(this->ike_sa_id),
|
||||
this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
|
||||
|
||||
/**
|
||||
* Implements retransmit_request_job_t.get_retransmit_count.
|
||||
*/
|
||||
static u_int32_t get_retransmit_count(private_retransmit_request_job_t *this)
|
||||
{
|
||||
return this->retransmit_count;
|
||||
}
|
||||
status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "Checkin of IKE SA failed!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements retransmit_request_job_t.increase_retransmit_count.
|
||||
*/
|
||||
static void increase_retransmit_count(private_retransmit_request_job_t *this)
|
||||
{
|
||||
if (stop_retransmitting)
|
||||
{
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
this->retransmit_count++;
|
||||
status = charon->configuration->get_retransmit_timeout(charon->configuration,
|
||||
this->retransmit_count, &timeout);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Message will not be retransmitted anymore");
|
||||
return DESTROY_ME;
|
||||
}
|
||||
charon->event_queue->add_relative(charon->event_queue, (job_t *)this, timeout);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements retransmit_request_job_t.get_message_id.
|
||||
*/
|
||||
static u_int32_t get_message_id(private_retransmit_request_job_t *this)
|
||||
{
|
||||
return this->message_id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements job_t.destroy.
|
||||
*/
|
||||
|
@ -112,21 +141,14 @@ retransmit_request_job_t *retransmit_request_job_create(u_int32_t message_id,ike
|
|||
|
||||
/* interface functions */
|
||||
this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
|
||||
/* same as destroy */
|
||||
this->public.job_interface.destroy_all = (void (*) (job_t *)) destroy;
|
||||
this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
|
||||
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||
|
||||
/* public functions */
|
||||
this->public.get_ike_sa_id = (ike_sa_id_t * (*)(retransmit_request_job_t *)) get_ike_sa_id;
|
||||
this->public.get_message_id = (u_int32_t (*)(retransmit_request_job_t *)) get_message_id;
|
||||
this->public.destroy = (void (*)(retransmit_request_job_t *)) destroy;
|
||||
this->public.get_retransmit_count = (u_int32_t (*)(retransmit_request_job_t *)) get_retransmit_count;
|
||||
this->public.increase_retransmit_count = (void (*)(retransmit_request_job_t *)) increase_retransmit_count;
|
||||
|
||||
|
||||
/* private variables */
|
||||
this->message_id = message_id;
|
||||
this->retransmit_count = 0;
|
||||
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
|
||||
this->logger = logger_manager->get_logger(logger_manager, WORKER);
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
|
|
|
@ -47,48 +47,6 @@ struct retransmit_request_job_t {
|
|||
* The job_t interface.
|
||||
*/
|
||||
job_t job_interface;
|
||||
|
||||
/**
|
||||
* @brief Returns the retransmit count for a specific request.
|
||||
*
|
||||
* @param this calling retransmit_request_job_t object
|
||||
* @return retransmit count of request
|
||||
*/
|
||||
u_int32_t (*get_retransmit_count) (retransmit_request_job_t *this);
|
||||
|
||||
/**
|
||||
* @brief Increases number of retransmitt attemps.
|
||||
*
|
||||
* @param this calling retransmit_request_job_t object
|
||||
*/
|
||||
void (*increase_retransmit_count) (retransmit_request_job_t *this);
|
||||
|
||||
/**
|
||||
* @brief Returns the message_id of the request to be resent
|
||||
*
|
||||
* @param this calling retransmit_request_job_t object
|
||||
* @return message id of the request to resend
|
||||
*/
|
||||
u_int32_t (*get_message_id) (retransmit_request_job_t *this);
|
||||
|
||||
/**
|
||||
* @brief Returns the ike_sa_id_t object of the IKE_SA
|
||||
* which the request belongs to
|
||||
*
|
||||
* @warning returned ike_sa_id_t object is getting destroyed in
|
||||
* retransmit_request_job_t.destroy.
|
||||
*
|
||||
* @param this calling retransmit_request_job_t object
|
||||
* @return ike_sa_id_t object to identify IKE_SA (gets NOT cloned)
|
||||
*/
|
||||
ike_sa_id_t *(*get_ike_sa_id) (retransmit_request_job_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys an retransmit_request_job_t object.
|
||||
*
|
||||
* @param this retransmit_request_job_t object to destroy
|
||||
*/
|
||||
void (*destroy) (retransmit_request_job_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -100,6 +58,7 @@ struct retransmit_request_job_t {
|
|||
*
|
||||
* @ingroup jobs
|
||||
*/
|
||||
retransmit_request_job_t *retransmit_request_job_create(u_int32_t message_id,ike_sa_id_t *ike_sa_id);
|
||||
retransmit_request_job_t *retransmit_request_job_create(u_int32_t message_id,
|
||||
ike_sa_id_t *ike_sa_id);
|
||||
|
||||
#endif /* RESEND_MESSAGE_JOB_H_ */
|
||||
|
|
|
@ -119,6 +119,14 @@ struct private_child_sa_t {
|
|||
logger_t *logger;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements child_sa_t.get_reqid
|
||||
*/
|
||||
static u_int32_t get_reqid(private_child_sa_t *this)
|
||||
{
|
||||
return this->reqid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements child_sa_t.alloc
|
||||
*/
|
||||
|
@ -300,6 +308,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus
|
|||
src, dst,
|
||||
spi, protocols[i],
|
||||
this->reqid,
|
||||
5, 30,
|
||||
enc_algo, enc_key,
|
||||
int_algo, int_key, mine);
|
||||
/* clean up for next round */
|
||||
|
@ -316,8 +325,6 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus
|
|||
{
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
|
@ -564,10 +571,11 @@ static void destroy(private_child_sa_t *this)
|
|||
*/
|
||||
child_sa_t * child_sa_create(host_t *me, host_t* other)
|
||||
{
|
||||
static u_int32_t reqid = 0xc0000000;
|
||||
static u_int32_t reqid = 2000000000;
|
||||
private_child_sa_t *this = malloc_thing(private_child_sa_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid;
|
||||
this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
|
||||
this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add;
|
||||
this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update;
|
||||
|
@ -583,7 +591,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other)
|
|||
this->my_esp_spi = 0;
|
||||
this->other_ah_spi = 0;
|
||||
this->other_esp_spi = 0;
|
||||
this->reqid = reqid++;
|
||||
this->reqid = ++reqid;
|
||||
this->policies = linked_list_create();
|
||||
|
||||
return (&this->public);
|
||||
|
|
|
@ -58,6 +58,17 @@ typedef struct child_sa_t child_sa_t;
|
|||
*/
|
||||
struct child_sa_t {
|
||||
|
||||
/**
|
||||
* @brief Get the unique reqid of the CHILD SA.
|
||||
*
|
||||
* Every CHILD_SA has a unique reqid, which is also
|
||||
* stored down in the kernel.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return reqid of the CHILD SA
|
||||
*/
|
||||
u_int32_t (*get_reqid)(child_sa_t *this);
|
||||
|
||||
/**
|
||||
* @brief Allocate SPIs for a given proposals.
|
||||
*
|
||||
|
|
|
@ -886,6 +886,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 ike_sa_t.get_child_sa.
|
||||
*/
|
||||
static child_sa_t *get_child_sa(private_ike_sa_t *this, u_int32_t reqid)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
child_sa_t *current, *found = NULL;
|
||||
|
||||
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
|
||||
while (iterator->has_next(iterator))
|
||||
{
|
||||
iterator->current(iterator, (void**)¤t);
|
||||
if (current->get_reqid(current) == reqid)
|
||||
{
|
||||
found = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of protected_ike_sa_t.reset_message_buffers.
|
||||
*/
|
||||
|
@ -929,18 +951,19 @@ static void log_status(private_ike_sa_t *this, logger_t *logger, char *name)
|
|||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
name = this->connection->get_name(this->connection);
|
||||
}
|
||||
|
||||
my_host = this->connection->get_my_host(this->connection);
|
||||
other_host = this->connection->get_other_host(this->connection);
|
||||
|
||||
/* use policy information, if available */
|
||||
if (this->policy)
|
||||
{
|
||||
my_id = this->policy->get_my_id(this->policy);
|
||||
other_id = this->policy->get_other_id(this->policy);
|
||||
name = this->policy->get_name(this->policy);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = this->connection->get_name(this->connection);
|
||||
}
|
||||
|
||||
if (logger == NULL)
|
||||
|
@ -1116,6 +1139,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
|
|||
/* Public functions */
|
||||
this->protected.public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
|
||||
this->protected.public.initiate_connection = (status_t(*)(ike_sa_t*,connection_t*)) initiate_connection;
|
||||
this->protected.public.get_child_sa = (child_sa_t*(*)(ike_sa_t*,u_int32_t))get_child_sa;
|
||||
this->protected.public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
|
||||
this->protected.public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host;
|
||||
this->protected.public.get_other_host = (host_t*(*)(ike_sa_t*)) get_other_host;
|
||||
|
|
|
@ -113,6 +113,19 @@ struct ike_sa_t {
|
|||
*/
|
||||
ike_sa_id_t* (*get_id) (ike_sa_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the CHILD_SA with the specified reqid.
|
||||
*
|
||||
* The reqid is a unique ID for a child SA, which is
|
||||
* generated on child SA creation.
|
||||
* Returned child_sa_t object is not cloned!
|
||||
*
|
||||
* @param this calling object
|
||||
* @param reqid reqid of the child SA, as used in the kernel
|
||||
* @return child_sa, or NULL if not found
|
||||
*/
|
||||
child_sa_t* (*get_child_sa) (ike_sa_t *this, u_int32_t reqid);
|
||||
|
||||
/**
|
||||
* @brief Get local peer address of the IKE_SA.
|
||||
*
|
||||
|
@ -184,7 +197,7 @@ struct ike_sa_t {
|
|||
* @brief Initiates the deletion of an IKE_SA.
|
||||
*
|
||||
* Sends a delete message to the remote peer and waits for
|
||||
* its response. If the response comes in, or a timeout occur,
|
||||
* its response. If the response comes in, or a timeout occurs,
|
||||
* the IKE SA gets deleted.
|
||||
*
|
||||
* @param this calling object
|
||||
|
|
|
@ -392,19 +392,19 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
|
|||
/* we SHOULD have an IKE_SA for these SPIs in the list,
|
||||
* if not, we can't handle the request...
|
||||
*/
|
||||
ike_sa_entry_t *entry;
|
||||
/* look for the entry */
|
||||
if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
|
||||
{
|
||||
/* can we give this ike_sa out to new requesters?*/
|
||||
if (entry->driveout_new_threads)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL|LEVEL1, "Drive out new thread for existing IKE_SA");
|
||||
/* no we can't */
|
||||
retval = NOT_FOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
ike_sa_entry_t *entry;
|
||||
/* look for the entry */
|
||||
if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
|
||||
{
|
||||
/* can we give this ike_sa out to new requesters?*/
|
||||
if (entry->driveout_new_threads)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL|LEVEL1, "Drive out new thread for existing IKE_SA");
|
||||
/* no we can't */
|
||||
retval = NOT_FOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* is this IKE_SA already checked out ??
|
||||
* are we welcome to get this SA ? */
|
||||
while (entry->checked_out && !entry->driveout_waiting_threads)
|
||||
|
@ -489,64 +489,55 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
|
|||
}
|
||||
|
||||
/**
|
||||
* Implementation of of ike_sa_manager.checkout_by_hosts.
|
||||
* Implementation of of ike_sa_manager.checkout_by_reqid.
|
||||
*/
|
||||
static status_t checkout_by_hosts(private_ike_sa_manager_t *this, host_t *me, host_t *other, ike_sa_t **ike_sa)
|
||||
static status_t checkout_by_reqid(private_ike_sa_manager_t *this, u_int32_t reqid, ike_sa_t **ike_sa)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
ike_sa_id_t *ike_sa_id = NULL;
|
||||
status_t status = NOT_FOUND;
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
|
||||
iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
|
||||
while (iterator->has_next(iterator))
|
||||
{
|
||||
ike_sa_entry_t *current;
|
||||
host_t *sa_me, *sa_other;
|
||||
ike_sa_entry_t *entry;
|
||||
|
||||
iterator->current(iterator, (void**)¤t);
|
||||
sa_me = current->ike_sa->get_my_host(current->ike_sa);
|
||||
sa_other = current->ike_sa->get_other_host(current->ike_sa);
|
||||
|
||||
/* one end may be default/any, but not both */
|
||||
if (me->is_anyaddr(me))
|
||||
iterator->current(iterator, (void**)&entry);
|
||||
if (entry->driveout_new_threads)
|
||||
{
|
||||
if (other->is_anyaddr(other))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (other->equals(other, sa_other))
|
||||
{
|
||||
/* other matches */
|
||||
ike_sa_id = current->ike_sa_id;
|
||||
}
|
||||
/* we are not allowed to get this, get next one */
|
||||
continue;
|
||||
}
|
||||
else if (other->is_anyaddr(other))
|
||||
while (entry->checked_out && !entry->driveout_waiting_threads)
|
||||
{
|
||||
if (me->equals(me, sa_me))
|
||||
{
|
||||
/* ME matches */
|
||||
ike_sa_id = current->ike_sa_id;
|
||||
}
|
||||
/* so wait until we can get it for us.
|
||||
* we register us as waiting. */
|
||||
entry->waiting_threads++;
|
||||
pthread_cond_wait(&(entry->condvar), &(this->mutex));
|
||||
entry->waiting_threads--;
|
||||
}
|
||||
else
|
||||
/* hm, a deletion request forbids us to get this SA, get next one */
|
||||
if (entry->driveout_waiting_threads)
|
||||
{
|
||||
if (me->equals(me, sa_me) && other->equals(other, sa_other))
|
||||
{
|
||||
/* both matches */
|
||||
ike_sa_id = current->ike_sa_id;
|
||||
}
|
||||
/* we must signal here, others may be waiting on it, too */
|
||||
pthread_cond_signal(&(entry->condvar));
|
||||
continue;
|
||||
}
|
||||
/* ok, access is exclusive for us, check reqid */
|
||||
if (entry->ike_sa->get_child_sa(entry->ike_sa, reqid) != NULL)
|
||||
{
|
||||
/* match */
|
||||
entry->checked_out = TRUE;
|
||||
*ike_sa = entry->ike_sa;
|
||||
status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
|
||||
if (ike_sa_id)
|
||||
{
|
||||
/* checkout is done in the checkout function, since its rather complex */
|
||||
return checkout(this, ike_sa_id, ike_sa);
|
||||
}
|
||||
return NOT_FOUND;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -840,7 +831,7 @@ ike_sa_manager_t *ike_sa_manager_create()
|
|||
this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
|
||||
this->public.create_and_checkout = (void(*)(ike_sa_manager_t*,ike_sa_t**))create_and_checkout;
|
||||
this->public.checkout = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t*,ike_sa_t**))checkout;
|
||||
this->public.checkout_by_hosts = (status_t(*)(ike_sa_manager_t*,host_t*,host_t*,ike_sa_t**))checkout_by_hosts;
|
||||
this->public.checkout_by_reqid = (status_t(*)(ike_sa_manager_t*,u_int32_t,ike_sa_t**))checkout_by_reqid;
|
||||
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;
|
||||
|
|
|
@ -81,21 +81,21 @@ struct ike_sa_manager_t {
|
|||
void (*create_and_checkout) (ike_sa_manager_t* this,ike_sa_t **ike_sa);
|
||||
|
||||
/**
|
||||
* @brief Check out an IKE_SA, defined be the two peers.
|
||||
*
|
||||
* Checking out an IKE_SA by their peer addresses may be necessary
|
||||
* for kernel traps, status querying and so on... one of the hosts
|
||||
* may be 0.0.0.0 (defaultroute/any), but not both.
|
||||
*
|
||||
* @param this the manager object
|
||||
* @param me host on local side
|
||||
* @param other host on remote side
|
||||
* @brief Check out an IKE_SA by the reqid of one of its CHILD_SAs.
|
||||
*
|
||||
* The kernel sends us expire messages for IPsec SAs. To fullfill
|
||||
* this request, we must check out the IKE SA which contains the
|
||||
* CHILD_SA the kernel wants to modify. We do this by the reqid, which
|
||||
* is unique to every CHILD_SA.
|
||||
*
|
||||
* @param this the manager object
|
||||
* @param reqid reqid of the IPsec SA
|
||||
* @param ike_sa[out] checked out SA
|
||||
* @return
|
||||
* - NOT_FOUND, if no such SA found
|
||||
* - SUCCESS, if SA found and ike_sa set appropriatly
|
||||
* - NOT_FOUND, if no IKE SA with such a child found
|
||||
* - SUCCESS, if ike_sa set
|
||||
*/
|
||||
status_t (*checkout_by_hosts) (ike_sa_manager_t* this, host_t *me, host_t *other, ike_sa_t **ike_sa);
|
||||
status_t (*checkout_by_reqid) (ike_sa_manager_t* this, u_int32_t reqid, ike_sa_t **ike_sa);
|
||||
|
||||
/**
|
||||
* @brief Get a list of all IKE_SA SAs currently set up.
|
||||
|
|
|
@ -29,6 +29,7 @@ $(top_srcdir)/src/charon/ke_payload.o $(top_srcdir)/src/charon/unknown_payload.o
|
|||
$(top_srcdir)/src/charon/delete_payload.o $(top_srcdir)/src/charon/sa_payload.o $(top_srcdir)/src/charon/certreq_payload.o $(top_srcdir)/src/charon/vendor_id_payload.o \
|
||||
$(top_srcdir)/src/charon/proposal_substructure.o $(top_srcdir)/src/charon/payload.o $(top_srcdir)/src/charon/message.o $(top_srcdir)/src/charon/generator.o \
|
||||
$(top_srcdir)/src/charon/parser.o $(top_srcdir)/src/charon/packet.o $(top_srcdir)/src/charon/socket.o $(top_srcdir)/src/charon/job.o \
|
||||
$(top_srcdir)/src/charon/delete_child_sa_job.o $(top_srcdir)/src/charon/rekey_child_sa_job.o \
|
||||
$(top_srcdir)/src/charon/delete_established_ike_sa_job.o $(top_srcdir)/src/charon/incoming_packet_job.o $(top_srcdir)/src/charon/delete_half_open_ike_sa_job.o \
|
||||
$(top_srcdir)/src/charon/retransmit_request_job.o $(top_srcdir)/src/charon/initiate_ike_sa_job.o $(top_srcdir)/src/charon/job_queue.o $(top_srcdir)/src/charon/event_queue.o \
|
||||
$(top_srcdir)/src/charon/send_queue.o $(top_srcdir)/src/charon/kernel_interface.o $(top_srcdir)/src/charon/thread_pool.o $(top_srcdir)/src/charon/scheduler.o \
|
||||
|
|
|
@ -65,20 +65,26 @@ void test_kernel_interface(protected_tester_t *tester)
|
|||
status = kernel_interface->get_spi(kernel_interface, me, other, 50, 1234, &spi);
|
||||
tester->assert_true(tester, status == SUCCESS, "spi get");
|
||||
|
||||
status = kernel_interface->add_sa(kernel_interface, me, other, spi, 50, 1234, ENCR_AES_CBC, enc_key,AUTH_UNDEFINED,inc_key,TRUE);
|
||||
status = kernel_interface->add_sa(kernel_interface, me, other, spi, 50, 1234, 5, 10, ENCR_AES_CBC, enc_key,AUTH_UNDEFINED,inc_key,TRUE);
|
||||
tester->assert_true(tester, status == SUCCESS, "add sa");
|
||||
|
||||
left = host_create(AF_INET, "10.1.0.0", 0);
|
||||
right = host_create(AF_INET, "10.2.0.0", 0);
|
||||
|
||||
status = kernel_interface->add_policy(kernel_interface, me, other, left, right, 16, 16, XFRM_POLICY_OUT, 0, TRUE, FALSE, 1234);
|
||||
tester->assert_true(tester, status == SUCCESS, "add policy");
|
||||
tester->assert_true(tester, status == SUCCESS, "add policy OUT");
|
||||
status = kernel_interface->add_policy(kernel_interface, me, other, left, right, 16, 16, XFRM_POLICY_IN, 0, TRUE, FALSE, 1234);
|
||||
tester->assert_true(tester, status == SUCCESS, "add policy IN");
|
||||
status = kernel_interface->add_policy(kernel_interface, me, other, left, right, 16, 16, XFRM_POLICY_FWD, 0, TRUE, FALSE, 1234);
|
||||
tester->assert_true(tester, status == SUCCESS, "add policy FWD");
|
||||
|
||||
me->destroy(me);
|
||||
other->destroy(other);
|
||||
left->destroy(left);
|
||||
right->destroy(right);
|
||||
|
||||
sleep(15);
|
||||
|
||||
kernel_interface->destroy(kernel_interface);
|
||||
|
||||
}
|
||||
|
|
|
@ -252,7 +252,7 @@ int main()
|
|||
tester_t *tester = tester_create(test_output, FALSE);
|
||||
|
||||
//tester->perform_tests(tester,all_tests);
|
||||
tester->perform_test(tester,&policy_test);
|
||||
tester->perform_test(tester,&kernel_interface_test);
|
||||
|
||||
|
||||
tester->destroy(tester);
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
#include <daemon.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <queues/jobs/delete_child_sa_job.h>
|
||||
#include <queues/jobs/rekey_child_sa_job.h>
|
||||
|
||||
|
||||
#define KERNEL_ESP 50
|
||||
|
@ -101,6 +103,8 @@ struct netlink_message_t {
|
|||
struct xfrm_userpolicy_id policy_id;
|
||||
/** message for policy installation */
|
||||
struct xfrm_userpolicy_info policy;
|
||||
/** expire message sent from kernel */
|
||||
struct xfrm_user_expire expire;
|
||||
};
|
||||
u_int8_t data[XFRM_DATA_LENGTH];
|
||||
};
|
||||
|
@ -205,7 +209,6 @@ mapping_t kernel_integrity_algs_m[] = {
|
|||
{MAPPING_END, NULL}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of kernel_interface_t.get_spi.
|
||||
*/
|
||||
|
@ -272,6 +275,8 @@ static status_t add_sa( private_kernel_interface_t *this,
|
|||
u_int32_t spi,
|
||||
int protocol,
|
||||
u_int32_t reqid,
|
||||
u_int64_t expire_soft,
|
||||
u_int64_t expire_hard,
|
||||
encryption_algorithm_t enc_alg,
|
||||
chunk_t encryption_key,
|
||||
integrity_algorithm_t int_alg,
|
||||
|
@ -296,10 +301,16 @@ static status_t add_sa( private_kernel_interface_t *this,
|
|||
request.sa.mode = TRUE; /* tunnel mode */
|
||||
request.sa.replay_window = 32;
|
||||
request.sa.reqid = reqid;
|
||||
/* we currently do not expire SAs by volume/packet count */
|
||||
request.sa.lft.soft_byte_limit = XFRM_INF;
|
||||
request.sa.lft.soft_packet_limit = XFRM_INF;
|
||||
request.sa.lft.hard_byte_limit = XFRM_INF;
|
||||
request.sa.lft.soft_packet_limit = XFRM_INF;
|
||||
request.sa.lft.hard_packet_limit = XFRM_INF;
|
||||
/* we use lifetimes since added, not since used */
|
||||
request.sa.lft.soft_add_expires_seconds = expire_soft;
|
||||
request.sa.lft.hard_add_expires_seconds = expire_hard;
|
||||
request.sa.lft.soft_use_expires_seconds = 0;
|
||||
request.sa.lft.hard_use_expires_seconds = 0;
|
||||
|
||||
request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa)));
|
||||
|
||||
|
@ -435,10 +446,15 @@ static status_t add_policy(private_kernel_interface_t *this,
|
|||
request.policy.action = XFRM_POLICY_ALLOW;
|
||||
request.policy.share = XFRM_SHARE_ANY;
|
||||
|
||||
/* policies currently don't expire */
|
||||
request.policy.lft.soft_byte_limit = XFRM_INF;
|
||||
request.policy.lft.soft_packet_limit = XFRM_INF;
|
||||
request.policy.lft.hard_byte_limit = XFRM_INF;
|
||||
request.policy.lft.hard_packet_limit = XFRM_INF;
|
||||
request.sa.lft.soft_add_expires_seconds = 0;
|
||||
request.sa.lft.hard_add_expires_seconds = 0;
|
||||
request.sa.lft.soft_use_expires_seconds = 0;
|
||||
request.sa.lft.hard_use_expires_seconds = 0;
|
||||
|
||||
if (esp || ah)
|
||||
{
|
||||
|
@ -645,30 +661,58 @@ static void receive_messages(private_kernel_interface_t *this)
|
|||
/* not from kernel. not interested, try another one */
|
||||
continue;
|
||||
}
|
||||
/* good message, handle it */
|
||||
break;
|
||||
}
|
||||
|
||||
/* got a valid message.
|
||||
* requests are handled on our own,
|
||||
* responses are listed for the requesters
|
||||
/* we handle ACQUIRE and EXPIRE messages directly
|
||||
*/
|
||||
if (response.hdr.nlmsg_flags & NLM_F_REQUEST)
|
||||
if (response.hdr.nlmsg_type == XFRM_MSG_ACQUIRE)
|
||||
{
|
||||
/* handle request */
|
||||
this->logger->log(this->logger, CONTROL,
|
||||
"Received a XFRM_MSG_ACQUIRE. Ignored");
|
||||
}
|
||||
else
|
||||
else if (response.hdr.nlmsg_type == XFRM_MSG_EXPIRE)
|
||||
{
|
||||
/* add response to queue */
|
||||
job_t *job;
|
||||
this->logger->log(this->logger, CONTROL|LEVEL1,
|
||||
"Received a XFRM_MSG_EXPIRE");
|
||||
this->logger->log(this->logger, CONTROL|LEVEL0,
|
||||
"creating %s job for CHILD_SA with reqid %d",
|
||||
response.expire.hard ? "delete" : "rekey",
|
||||
response.expire.state.reqid);
|
||||
if (response.expire.hard)
|
||||
{
|
||||
job = (job_t*)delete_child_sa_job_create(
|
||||
response.expire.state.reqid);
|
||||
}
|
||||
else
|
||||
{
|
||||
job = (job_t*)rekey_child_sa_job_create(
|
||||
response.expire.state.reqid);
|
||||
}
|
||||
charon->job_queue->add(charon->job_queue, job);
|
||||
}
|
||||
/* NLMSG_ERROR is send back for acknowledge (or on error), an
|
||||
* XFRM_MSG_NEWSA is returned when we alloc spis.
|
||||
* list these responses for the sender
|
||||
*/
|
||||
else if (response.hdr.nlmsg_type == NLMSG_ERROR ||
|
||||
response.hdr.nlmsg_type == XFRM_MSG_NEWSA)
|
||||
{
|
||||
/* add response to queue */
|
||||
listed_response = malloc(sizeof(response));
|
||||
memcpy(listed_response, &response, sizeof(response));
|
||||
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
this->responses->insert_last(this->responses, (void*)listed_response);
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
/* signal ALL waiting threads */
|
||||
pthread_cond_broadcast(&(this->condvar));
|
||||
}
|
||||
/* get the next one */
|
||||
/* we are not interested in anything other.
|
||||
* anyway, move on to the next message */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -689,11 +733,12 @@ static void destroy(private_kernel_interface_t *this)
|
|||
*/
|
||||
kernel_interface_t *kernel_interface_create()
|
||||
{
|
||||
struct sockaddr_nl addr;
|
||||
private_kernel_interface_t *this = malloc_thing(private_kernel_interface_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
|
||||
this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,encryption_algorithm_t,chunk_t,integrity_algorithm_t,chunk_t,bool))add_sa;
|
||||
this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,encryption_algorithm_t,chunk_t,integrity_algorithm_t,chunk_t,bool))add_sa;
|
||||
this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*, host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,bool,bool,u_int32_t))add_policy;
|
||||
this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
|
||||
this->public.del_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int))del_policy;
|
||||
|
@ -709,6 +754,8 @@ kernel_interface_t *kernel_interface_create()
|
|||
pthread_mutex_init(&(this->mutex),NULL);
|
||||
pthread_cond_init(&(this->condvar),NULL);
|
||||
this->seq = 0;
|
||||
|
||||
/* open netlink socket */
|
||||
this->socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_XFRM);
|
||||
if (this->socket <= 0)
|
||||
{
|
||||
|
@ -716,6 +763,17 @@ kernel_interface_t *kernel_interface_create()
|
|||
free(this);
|
||||
charon->kill(charon, "Unable to create netlink socket");
|
||||
}
|
||||
/* bind the socket and reqister for ACQUIRE & EXPIRE */
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_pid = getpid();
|
||||
addr.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE;
|
||||
if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) != 0)
|
||||
{
|
||||
this->responses->destroy(this->responses);
|
||||
close(this->socket);
|
||||
free(this);
|
||||
charon->kill(charon, "Unable to bind netlink socket");
|
||||
}
|
||||
|
||||
if (pthread_create(&(this->thread), NULL, (void*(*)(void*))this->receive_messages, this) != 0)
|
||||
{
|
||||
|
|
|
@ -68,30 +68,34 @@ struct kernel_interface_t {
|
|||
*
|
||||
* add_sa() may update an already allocated
|
||||
* SPI (via get_spi). In this case, the replace
|
||||
* flag must be set.
|
||||
* flag must be set.
|
||||
* This function does install a single SA for a
|
||||
* single protocol in one direction.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param src source address for this SA
|
||||
* @param dst destination address for this SA
|
||||
* @param spi SPI allocated by us or remote peer
|
||||
* @param protocol protocol for this SA (ESP/AH)
|
||||
* @param reqid unique ID for this SA
|
||||
* @param enc_alg Algorithm to use for encryption (ESP only)
|
||||
* @param enc_key Key to use for encryption
|
||||
* @param int_alg Algorithm to use for integrity protection
|
||||
* @param int_key Key for integrity protection
|
||||
* @param replace Should an already installed SA be updated?
|
||||
* @param this calling object
|
||||
* @param src source address for this SA
|
||||
* @param dst destination address for this SA
|
||||
* @param spi SPI allocated by us or remote peer
|
||||
* @param protocol protocol for this SA (ESP/AH)
|
||||
* @param reqid unique ID for this SA
|
||||
* @param expire_soft lifetime in seconds before rekeying
|
||||
* @param expire_hard lieftime in seconds before delete
|
||||
* @param enc_alg Algorithm to use for encryption (ESP only)
|
||||
* @param enc_key Key to use for encryption
|
||||
* @param int_alg Algorithm to use for integrity protection
|
||||
* @param int_key Key for integrity protection
|
||||
* @param replace Should an already installed SA be updated?
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - FAILED if kernel comm failed
|
||||
* - SUCCESS
|
||||
* - FAILED if kernel comm failed
|
||||
*/
|
||||
status_t (*add_sa)(kernel_interface_t *this,
|
||||
host_t *src, host_t *dst,
|
||||
u_int32_t spi,
|
||||
protocol_id_t protocol,
|
||||
u_int32_t reqid,
|
||||
u_int64_t expire_soft,
|
||||
u_int64_t expire_hard,
|
||||
encryption_algorithm_t enc_alg,
|
||||
chunk_t enc_key,
|
||||
integrity_algorithm_t int_alg,
|
||||
|
|
|
@ -48,68 +48,7 @@ struct private_thread_pool_t {
|
|||
* Public thread_pool_t interface.
|
||||
*/
|
||||
thread_pool_t public;
|
||||
|
||||
/**
|
||||
* @brief Main processing function for worker threads.
|
||||
*
|
||||
* Gets a job from the job queue and calls corresponding
|
||||
* function for processing.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*process_jobs) (private_thread_pool_t *this);
|
||||
|
||||
/**
|
||||
* @brief Process a INCOMING_PACKET job.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param job incoming_packet_job_t object
|
||||
*/
|
||||
void (*process_incoming_packet_job) (private_thread_pool_t *this, incoming_packet_job_t *job);
|
||||
|
||||
/**
|
||||
* @brief Process a INITIATE_IKE_SA job.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param job initiate_ike_sa_job_t object
|
||||
*/
|
||||
void (*process_initiate_ike_sa_job) (private_thread_pool_t *this, initiate_ike_sa_job_t *job);
|
||||
|
||||
/**
|
||||
* @brief Process a DELETE_HALF_OPEN_IKE_SA job.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param job delete__half_open_ike_sa_job_t object
|
||||
*/
|
||||
void (*process_delete_half_open_ike_sa_job) (private_thread_pool_t *this, delete_half_open_ike_sa_job_t *job);
|
||||
|
||||
/**
|
||||
* @brief Process a DELETE_ESTABLISHED_IKE_SA job.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param job delete_established_ike_sa_job_t object
|
||||
*/
|
||||
void (*process_delete_established_ike_sa_job) (private_thread_pool_t *this, delete_established_ike_sa_job_t *job);
|
||||
|
||||
/**
|
||||
* @brief Process a RETRANSMIT_REQUEST job.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param job retransmit_request_job_t object
|
||||
*/
|
||||
void (*process_retransmit_request_job) (private_thread_pool_t *this, retransmit_request_job_t *job);
|
||||
|
||||
/**
|
||||
* Creates a job of type DELETE_HALF_OPEN_IKE_SA.
|
||||
*
|
||||
* This job is used to delete IKE_SA's which are still in state INITIATOR_INIT,
|
||||
* RESPONDER_INIT, IKE_AUTH_REQUESTED, IKE_INIT_REQUESTED or IKE_INIT_RESPONDED.
|
||||
*
|
||||
* @param ike_sa_id ID of IKE_SA to delete
|
||||
* @param delay Delay in ms after a half open IKE_SA gets deleted!
|
||||
*/
|
||||
void (*create_delete_half_open_ike_sa_job) (private_thread_pool_t *this,ike_sa_id_t *ike_sa_id, u_int32_t delay);
|
||||
|
||||
/**
|
||||
* Number of running threads.
|
||||
*/
|
||||
|
@ -137,366 +76,26 @@ struct private_thread_pool_t {
|
|||
static void process_jobs(private_thread_pool_t *this)
|
||||
{
|
||||
job_t *job;
|
||||
job_type_t job_type;
|
||||
timeval_t start_time;
|
||||
timeval_t end_time;
|
||||
status_t status;
|
||||
|
||||
/* cancellation disabled by default */
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||
|
||||
this->worker_logger->log(this->worker_logger, CONTROL, "worker thread running, thread_ID: %06d", (int)pthread_self());
|
||||
|
||||
for (;;)
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
job = charon->job_queue->get(charon->job_queue);
|
||||
job_type = job->get_type(job);
|
||||
this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Process job of type %s",
|
||||
mapping_find(job_type_m,job_type));
|
||||
gettimeofday(&start_time,NULL);
|
||||
switch (job_type)
|
||||
{
|
||||
case INCOMING_PACKET:
|
||||
{
|
||||
this->process_incoming_packet_job(this, (incoming_packet_job_t*)job);
|
||||
job->destroy(job);
|
||||
break;
|
||||
}
|
||||
case INITIATE_IKE_SA:
|
||||
{
|
||||
this->process_initiate_ike_sa_job(this, (initiate_ike_sa_job_t*)job);
|
||||
job->destroy(job);
|
||||
break;
|
||||
}
|
||||
case DELETE_HALF_OPEN_IKE_SA:
|
||||
{
|
||||
this->process_delete_half_open_ike_sa_job(this, (delete_half_open_ike_sa_job_t*)job);
|
||||
job->destroy(job);
|
||||
break;
|
||||
}
|
||||
case DELETE_ESTABLISHED_IKE_SA:
|
||||
{
|
||||
this->process_delete_established_ike_sa_job(this, (delete_established_ike_sa_job_t*)job);
|
||||
job->destroy(job);
|
||||
break;
|
||||
}
|
||||
case RETRANSMIT_REQUEST:
|
||||
{
|
||||
this->process_retransmit_request_job(this, (retransmit_request_job_t*)job);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, ERROR, "Job of type %s not supported!",
|
||||
mapping_find(job_type_m,job_type));
|
||||
job->destroy(job);
|
||||
break;
|
||||
}
|
||||
}
|
||||
gettimeofday(&end_time,NULL);
|
||||
|
||||
this->worker_logger->log(this->worker_logger, CONTROL | LEVEL2, "Processed job of type %s in %d us",
|
||||
mapping_find(job_type_m,job_type),
|
||||
(((end_time.tv_sec - start_time.tv_sec) * 1000000) + (end_time.tv_usec - start_time.tv_usec)));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_thread_pool_t.process_incoming_packet_job.
|
||||
*/
|
||||
static void process_incoming_packet_job(private_thread_pool_t *this, incoming_packet_job_t *job)
|
||||
{
|
||||
packet_t *packet;
|
||||
message_t *message;
|
||||
ike_sa_t *ike_sa;
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
status_t status;
|
||||
|
||||
packet = job->get_packet(job);
|
||||
|
||||
message = message_create_from_packet(packet);
|
||||
status = message->parse_header(message);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, ERROR, "Message header could not be verified!");
|
||||
message->destroy(message);
|
||||
return;
|
||||
}
|
||||
|
||||
this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Message is a %s %s",
|
||||
mapping_find(exchange_type_m, message->get_exchange_type(message)),
|
||||
message->get_request(message) ? "request" : "reply");
|
||||
|
||||
if ((message->get_major_version(message) != IKE_MAJOR_VERSION) ||
|
||||
(message->get_minor_version(message) != IKE_MINOR_VERSION))
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, ERROR | LEVEL2,
|
||||
"IKE version %d.%d not supported",
|
||||
message->get_major_version(message),
|
||||
message->get_minor_version(message));
|
||||
if ((message->get_exchange_type(message) == IKE_SA_INIT) && (message->get_request(message)))
|
||||
{
|
||||
message_t *response;
|
||||
message->get_ike_sa_id(message, &ike_sa_id);
|
||||
ike_sa_id->switch_initiator(ike_sa_id);
|
||||
response = message_create_notify_reply(message->get_destination(message),
|
||||
message->get_source(message),
|
||||
IKE_SA_INIT, FALSE, ike_sa_id,
|
||||
INVALID_MAJOR_VERSION);
|
||||
message->destroy(message);
|
||||
ike_sa_id->destroy(ike_sa_id);
|
||||
status = response->generate(response, NULL, NULL, &packet);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, ERROR, "Could not generate packet from message");
|
||||
response->destroy(response);
|
||||
return;
|
||||
}
|
||||
this->worker_logger->log(this->worker_logger, ERROR, "Send notify reply of type INVALID_MAJOR_VERSION");
|
||||
charon->send_queue->add(charon->send_queue, packet);
|
||||
response->destroy(response);
|
||||
return;
|
||||
}
|
||||
message->destroy(message);
|
||||
return;
|
||||
}
|
||||
|
||||
message->get_ike_sa_id(message, &ike_sa_id);
|
||||
|
||||
ike_sa_id->switch_initiator(ike_sa_id);
|
||||
|
||||
this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, "Checking out IKE SA %lld:%lld, role %s",
|
||||
ike_sa_id->get_initiator_spi(ike_sa_id),
|
||||
ike_sa_id->get_responder_spi(ike_sa_id),
|
||||
ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
|
||||
|
||||
status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,ike_sa_id, &ike_sa);
|
||||
if ((status != SUCCESS) && (status != CREATED))
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, ERROR, "IKE SA could not be checked out");
|
||||
ike_sa_id->destroy(ike_sa_id);
|
||||
message->destroy(message);
|
||||
status = job->execute(job);
|
||||
|
||||
/* TODO: send notify reply of type INVALID_IKE_SPI if SPI could not be found ? */
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == CREATED)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3,
|
||||
"Create Job to delete half open IKE_SA.");
|
||||
this->create_delete_half_open_ike_sa_job(this,ike_sa_id,
|
||||
charon->configuration->get_half_open_ike_sa_timeout(charon->configuration));
|
||||
}
|
||||
|
||||
status = ike_sa->process_message(ike_sa, message);
|
||||
|
||||
this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, "%s IKE SA %lld:%lld, role %s",
|
||||
(status == DESTROY_ME) ? "Checkin and delete" : "Checkin",
|
||||
ike_sa_id->get_initiator_spi(ike_sa_id),
|
||||
ike_sa_id->get_responder_spi(ike_sa_id),
|
||||
ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
|
||||
ike_sa_id->destroy(ike_sa_id);
|
||||
|
||||
if (status == DESTROY_ME)
|
||||
{
|
||||
status = charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, ERROR, "Checkin of IKE SA failed!");
|
||||
}
|
||||
message->destroy(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_thread_pool_t.process_initiate_ike_sa_job.
|
||||
*/
|
||||
static void process_initiate_ike_sa_job(private_thread_pool_t *this, initiate_ike_sa_job_t *job)
|
||||
{
|
||||
/*
|
||||
* Initiatie an IKE_SA:
|
||||
* - is defined by a name of a configuration
|
||||
* - create an empty IKE_SA via manager
|
||||
* - call initiate_connection on this sa
|
||||
*/
|
||||
ike_sa_t *ike_sa;
|
||||
status_t status;
|
||||
|
||||
|
||||
this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Creating and checking out IKE SA");
|
||||
charon->ike_sa_manager->create_and_checkout(charon->ike_sa_manager, &ike_sa);
|
||||
|
||||
status = ike_sa->initiate_connection(ike_sa, job->get_connection(job));
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, ERROR, "Initiation returned %s, going to delete IKE_SA.",
|
||||
mapping_find(status_m, status));
|
||||
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
|
||||
return;
|
||||
}
|
||||
|
||||
this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, "Create Job to delete half open IKE_SA.");
|
||||
this->create_delete_half_open_ike_sa_job(this,ike_sa->get_id(ike_sa),
|
||||
charon->configuration->get_half_open_ike_sa_timeout(charon->configuration));
|
||||
|
||||
this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Checking in IKE SA");
|
||||
status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, ERROR, "Could not checkin IKE_SA (%s)",
|
||||
mapping_find(status_m, status));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_thread_pool_t.process_delete_ike_sa_job.
|
||||
*/
|
||||
static void process_delete_half_open_ike_sa_job(private_thread_pool_t *this, delete_half_open_ike_sa_job_t *job)
|
||||
{
|
||||
ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job);
|
||||
ike_sa_t *ike_sa;
|
||||
status_t status;
|
||||
status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,ike_sa_id, &ike_sa);
|
||||
if ((status != SUCCESS) && (status != CREATED))
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, CONTROL | LEVEL3, "IKE SA seems to be already deleted");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ike_sa->get_state(ike_sa))
|
||||
{
|
||||
case INITIATOR_INIT:
|
||||
case RESPONDER_INIT:
|
||||
case IKE_SA_INIT_REQUESTED:
|
||||
case IKE_SA_INIT_RESPONDED:
|
||||
case IKE_AUTH_REQUESTED:
|
||||
case DELETE_REQUESTED:
|
||||
if (status == DESTROY_ME)
|
||||
{
|
||||
/* IKE_SA is half open and gets deleted! */
|
||||
status = charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, ERROR, "Could not checkin and delete checked out IKE_SA!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* IKE_SA is established and so is not getting deleted! */
|
||||
status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, ERROR, "Could not checkin a checked out IKE_SA!");
|
||||
}
|
||||
break;
|
||||
job->destroy(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_thread_pool_t.process_delete_established_ike_sa_job.
|
||||
*/
|
||||
static void process_delete_established_ike_sa_job(private_thread_pool_t *this, delete_established_ike_sa_job_t *job)
|
||||
{
|
||||
ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job);
|
||||
ike_sa_t *ike_sa;
|
||||
status_t status;
|
||||
status = charon->ike_sa_manager->delete(charon->ike_sa_manager, ike_sa_id);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, CONTROL, "IKE SA didn't exist anymore");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_thread_pool_t.process_retransmit_request_job.
|
||||
*/
|
||||
static void process_retransmit_request_job(private_thread_pool_t *this, retransmit_request_job_t *job)
|
||||
{
|
||||
|
||||
ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job);
|
||||
u_int32_t message_id = job->get_message_id(job);
|
||||
bool stop_retransmitting = FALSE;
|
||||
u_int32_t timeout;
|
||||
ike_sa_t *ike_sa;
|
||||
status_t status;
|
||||
|
||||
this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Checking out IKE SA %lld:%lld, role %s",
|
||||
ike_sa_id->get_initiator_spi(ike_sa_id),
|
||||
ike_sa_id->get_responder_spi(ike_sa_id),
|
||||
ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
|
||||
|
||||
status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,ike_sa_id, &ike_sa);
|
||||
if ((status != SUCCESS) && (status != CREATED))
|
||||
{
|
||||
job->destroy(job);
|
||||
this->worker_logger->log(this->worker_logger, ERROR|LEVEL1, "IKE SA could not be checked out. Already deleted?");
|
||||
return;
|
||||
}
|
||||
|
||||
status = ike_sa->retransmit_request(ike_sa, message_id);
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, CONTROL|LEVEL3, "Message doesn't have to be retransmitted");
|
||||
stop_retransmitting = TRUE;
|
||||
}
|
||||
|
||||
this->worker_logger->log(this->worker_logger, CONTROL|LEVEL2, "Checkin IKE SA %lld:%lld, role %s",
|
||||
ike_sa_id->get_initiator_spi(ike_sa_id),
|
||||
ike_sa_id->get_responder_spi(ike_sa_id),
|
||||
ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
|
||||
|
||||
status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, ERROR, "Checkin of IKE SA failed!");
|
||||
}
|
||||
|
||||
if (stop_retransmitting)
|
||||
{
|
||||
job->destroy(job);
|
||||
return;
|
||||
}
|
||||
|
||||
job->increase_retransmit_count(job);
|
||||
status = charon->configuration->get_retransmit_timeout (charon->configuration,job->get_retransmit_count(job),&timeout);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->worker_logger->log(this->worker_logger, CONTROL | LEVEL2, "Message will not be anymore retransmitted");
|
||||
job->destroy(job);
|
||||
/*
|
||||
* TODO delete IKE_SA ?
|
||||
*/
|
||||
return;
|
||||
}
|
||||
charon->event_queue->add_relative(charon->event_queue,(job_t *) job,timeout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of private_thread_pool_t.create_delete_half_open_ike_sa_job.
|
||||
*/
|
||||
static void create_delete_half_open_ike_sa_job(private_thread_pool_t *this,ike_sa_id_t *ike_sa_id, u_int32_t delay)
|
||||
{
|
||||
job_t *delete_job;
|
||||
|
||||
this->worker_logger->log(this->worker_logger, CONTROL | LEVEL2, "Going to create job to delete half open IKE_SA in %d ms", delay);
|
||||
|
||||
delete_job = (job_t *) delete_half_open_ike_sa_job_create(ike_sa_id);
|
||||
charon->event_queue->add_relative(charon->event_queue,delete_job, delay);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of thread_pool_t.get_pool_size.
|
||||
*/
|
||||
|
@ -528,7 +127,7 @@ static void destroy(private_thread_pool_t *this)
|
|||
this->pool_logger->log(this->pool_logger, ERROR, "could not terminate worker thread #%d", current+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* free mem */
|
||||
free(this->threads);
|
||||
free(this);
|
||||
|
@ -540,33 +139,22 @@ static void destroy(private_thread_pool_t *this)
|
|||
thread_pool_t *thread_pool_create(size_t pool_size)
|
||||
{
|
||||
int current;
|
||||
|
||||
private_thread_pool_t *this = malloc_thing(private_thread_pool_t);
|
||||
|
||||
/* fill in public fields */
|
||||
this->public.destroy = (void(*)(thread_pool_t*))destroy;
|
||||
this->public.get_pool_size = (size_t(*)(thread_pool_t*))get_pool_size;
|
||||
|
||||
this->process_jobs = process_jobs;
|
||||
this->process_initiate_ike_sa_job = process_initiate_ike_sa_job;
|
||||
this->process_delete_half_open_ike_sa_job = process_delete_half_open_ike_sa_job;
|
||||
this->process_delete_established_ike_sa_job = process_delete_established_ike_sa_job;
|
||||
this->process_incoming_packet_job = process_incoming_packet_job;
|
||||
this->process_retransmit_request_job = process_retransmit_request_job;
|
||||
this->create_delete_half_open_ike_sa_job = create_delete_half_open_ike_sa_job;
|
||||
|
||||
/* initialze memeber */
|
||||
this->pool_size = pool_size;
|
||||
|
||||
this->threads = malloc(sizeof(pthread_t) * pool_size);
|
||||
|
||||
this->pool_logger = logger_manager->get_logger(logger_manager, THREAD_POOL);
|
||||
|
||||
this->worker_logger = logger_manager->get_logger(logger_manager, WORKER);
|
||||
|
||||
/* try to create as many threads as possible, up tu pool_size */
|
||||
for (current = 0; current < pool_size; current++)
|
||||
{
|
||||
if (pthread_create(&(this->threads[current]), NULL, (void*(*)(void*))this->process_jobs, this) == 0)
|
||||
if (pthread_create(&(this->threads[current]), NULL, (void*(*)(void*))process_jobs, this) == 0)
|
||||
{
|
||||
this->pool_logger->log(this->pool_logger, CONTROL, "created worker thread #%d", current+1);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue