- retransmitting of requests implemented

This commit is contained in:
Jan Hutter
2005-12-02 14:07:36 +00:00
parent ccb37df25d
commit 0df63d6be4
12 changed files with 188 additions and 22 deletions
+30 -1
View File
@@ -123,6 +123,17 @@ struct private_configuration_manager_t {
* Assigned logger object. * Assigned logger object.
*/ */
logger_t *logger; logger_t *logger;
/**
* Max number of retransmitted requests.
*/
u_int32_t max_retransmit_count;
/**
* First retransmit timeout in ms.
*/
u_int32_t first_retransmit_timeout;
/** /**
* Load default configuration * Load default configuration
@@ -457,6 +468,21 @@ static void add_new_configuration (private_configuration_manager_t *this, char *
this->configurations->insert_first(this->configurations,configuration_entry_create(name,init_config,sa_config)); this->configurations->insert_first(this->configurations,configuration_entry_create(name,init_config,sa_config));
} }
static status_t get_retransmit_timeout (private_configuration_manager_t *this, u_int32_t retransmit_count, u_int32_t *timeout)
{
if ((retransmit_count > this->max_retransmit_count) && (this->max_retransmit_count != 0))
{
return FAILED;
}
/**
* TODO implement a good retransmit policy
*/
*timeout = this->first_retransmit_timeout * (retransmit_count + 1);
return SUCCESS;
}
/** /**
* Implementation of configuration_manager_t.destroy. * Implementation of configuration_manager_t.destroy.
*/ */
@@ -499,7 +525,7 @@ static void destroy(private_configuration_manager_t *this)
/* /*
* Described in header-file * Described in header-file
*/ */
configuration_manager_t *configuration_manager_create() configuration_manager_t *configuration_manager_create(u_int32_t first_retransmit_timeout,u_int32_t max_retransmit_count)
{ {
private_configuration_manager_t *this = allocator_alloc_thing(private_configuration_manager_t); private_configuration_manager_t *this = allocator_alloc_thing(private_configuration_manager_t);
@@ -509,6 +535,7 @@ configuration_manager_t *configuration_manager_create()
this->public.get_init_config_for_host = (status_t (*) (configuration_manager_t *, host_t *, host_t *,init_config_t **)) get_init_config_for_host; this->public.get_init_config_for_host = (status_t (*) (configuration_manager_t *, host_t *, host_t *,init_config_t **)) get_init_config_for_host;
this->public.get_sa_config_for_name =(status_t (*) (configuration_manager_t *, char *, sa_config_t **)) get_sa_config_for_name; this->public.get_sa_config_for_name =(status_t (*) (configuration_manager_t *, char *, sa_config_t **)) get_sa_config_for_name;
this->public.get_sa_config_for_init_config_and_id =(status_t (*) (configuration_manager_t *, init_config_t *, identification_t *, identification_t *,sa_config_t **)) get_sa_config_for_init_config_and_id; this->public.get_sa_config_for_init_config_and_id =(status_t (*) (configuration_manager_t *, init_config_t *, identification_t *, identification_t *,sa_config_t **)) get_sa_config_for_init_config_and_id;
this->public.get_retransmit_timeout = (status_t (*) (configuration_manager_t *, u_int32_t retransmit_count, u_int32_t *timeout))get_retransmit_timeout;
/* private functions */ /* private functions */
this->load_default_config = load_default_config; this->load_default_config = load_default_config;
@@ -519,6 +546,8 @@ configuration_manager_t *configuration_manager_create()
this->configurations = linked_list_create(); this->configurations = linked_list_create();
this->sa_configs = linked_list_create(); this->sa_configs = linked_list_create();
this->init_configs = linked_list_create(); this->init_configs = linked_list_create();
this->max_retransmit_count = max_retransmit_count;
this->first_retransmit_timeout = first_retransmit_timeout;
this->load_default_config(this); this->load_default_config(this);
+22 -5
View File
@@ -39,7 +39,7 @@ typedef struct configuration_manager_t configuration_manager_t;
struct configuration_manager_t { struct configuration_manager_t {
/** /**
* Gets the configuration information needed for IKE_SA_INIT exchange * Get the configuration information needed for IKE_SA_INIT exchange
* for a specific configuration name. * for a specific configuration name.
* *
* The returned init_config_t object MUST NOT be destroyed cause it's the original one. * The returned init_config_t object MUST NOT be destroyed cause it's the original one.
@@ -55,7 +55,7 @@ struct configuration_manager_t {
status_t (*get_init_config_for_name) (configuration_manager_t *this, char *name, init_config_t **init_config); status_t (*get_init_config_for_name) (configuration_manager_t *this, char *name, init_config_t **init_config);
/** /**
* Gets the configuration information needed for IKE_SA_INIT exchange * Get the configuration information needed for IKE_SA_INIT exchange
* for specific host informations. * for specific host informations.
* *
* The returned init_config_t object MUST NOT be destroyed cause it's the original one. * The returned init_config_t object MUST NOT be destroyed cause it's the original one.
@@ -72,7 +72,7 @@ struct configuration_manager_t {
status_t (*get_init_config_for_host) (configuration_manager_t *this, host_t *my_host, host_t *other_host,init_config_t **init_config); status_t (*get_init_config_for_host) (configuration_manager_t *this, host_t *my_host, host_t *other_host,init_config_t **init_config);
/** /**
* Gets the configuration information needed after IKE_SA_INIT exchange. * Get the configuration information needed after IKE_SA_INIT exchange.
* *
* The returned sa_config_t object MUST not be destroyed cause it's the original one. * The returned sa_config_t object MUST not be destroyed cause it's the original one.
* *
@@ -87,7 +87,7 @@ struct configuration_manager_t {
status_t (*get_sa_config_for_name) (configuration_manager_t *this, char *name, sa_config_t **sa_config); status_t (*get_sa_config_for_name) (configuration_manager_t *this, char *name, sa_config_t **sa_config);
/** /**
* Gets the configuration information needed after IKE_SA_INIT exchange * Get the configuration information needed after IKE_SA_INIT exchange
* for specific init_config_t and ID data. * for specific init_config_t and ID data.
* *
* The returned sa_config_t object MUST NOT be destroyed cause it's the original one. * The returned sa_config_t object MUST NOT be destroyed cause it's the original one.
@@ -104,6 +104,21 @@ struct configuration_manager_t {
*/ */
status_t (*get_sa_config_for_init_config_and_id) (configuration_manager_t *this, init_config_t *init_config, identification_t *other_id, identification_t *my_id,sa_config_t **sa_config); status_t (*get_sa_config_for_init_config_and_id) (configuration_manager_t *this, init_config_t *init_config, identification_t *other_id, identification_t *my_id,sa_config_t **sa_config);
/**
* Get the retransmit timeout.
*
* The timeout values are managed by the configuration manager.
*
* @param this calling object
* @param retransmit_count number of times a message was allready retransmitted
* @param[out] timeout the new retransmit timeout in milliseconds
*
* @return
* - FAILED if the message should not be resent again
* - SUCCESS
*/
status_t (*get_retransmit_timeout) (configuration_manager_t *this, u_int32_t retransmit_count, u_int32_t *timeout);
/** /**
* Destroys configuration manager * Destroys configuration manager
* *
@@ -118,12 +133,14 @@ struct configuration_manager_t {
/** /**
* Creates the mighty configuration manager * Creates the mighty configuration manager
* *
* @param first_retransmit_timeout first retransmit timeout in milliseconds
* @param max_retransmit_count max number of retransmitted requests (0 for infinite)
* @return * @return
* - pointer to created manager object if succeeded * - pointer to created manager object if succeeded
* - NULL if memory allocation failed * - NULL if memory allocation failed
* *
* @ingroup config * @ingroup config
*/ */
configuration_manager_t *configuration_manager_create(); configuration_manager_t *configuration_manager_create(u_int32_t first_retransmit_timeout,u_int32_t max_retransmit_count);
#endif /*CONFIGURATION_MANAGER_H_*/ #endif /*CONFIGURATION_MANAGER_H_*/
+1 -1
View File
@@ -174,7 +174,7 @@ static void initialize(private_daemon_t *this)
this->public.job_queue = job_queue_create(); this->public.job_queue = job_queue_create();
this->public.event_queue = event_queue_create(); this->public.event_queue = event_queue_create();
this->public.send_queue = send_queue_create(); this->public.send_queue = send_queue_create();
this->public.configuration_manager = configuration_manager_create(); this->public.configuration_manager = configuration_manager_create(RETRANSMIT_TIMEOUT,MAX_RETRANSMIT_COUNT);
this->public.sender = sender_create(); this->public.sender = sender_create();
this->public.receiver = receiver_create(); this->public.receiver = receiver_create();
+11 -1
View File
@@ -52,10 +52,20 @@
/** /**
* Port on which the daemon will * Port on which the daemon will
* listen for incoming traffic * listen for incoming traffic.
*/ */
#define IKEV2_UDP_PORT 4500 #define IKEV2_UDP_PORT 4500
/**
* First retransmit timeout in milliseconds.
*/
#define RETRANSMIT_TIMEOUT 3000
/**
* Max retransmit count. 0 for infinite.
*/
#define MAX_RETRANSMIT_COUNT 0
/** /**
* Default loglevel to use. This is the * Default loglevel to use. This is the
* maximum allowed level for ever context, the definiton * maximum allowed level for ever context, the definiton
@@ -46,6 +46,11 @@ struct private_retransmit_request_job_t {
* ID of the IKE_SA which the message belongs to. * ID of the IKE_SA which the message belongs to.
*/ */
ike_sa_id_t *ike_sa_id; ike_sa_id_t *ike_sa_id;
/**
* Number of times a request was retransmitted
*/
u_int32_t retransmit_count;
}; };
@@ -65,6 +70,22 @@ static ike_sa_id_t *get_ike_sa_id(private_retransmit_request_job_t *this)
return this->ike_sa_id; return this->ike_sa_id;
} }
/**
* 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;
}
/**
* Implements retransmit_request_job_t.increase_retransmit_count.
*/
static void increase_retransmit_count(private_retransmit_request_job_t *this)
{
this->retransmit_count++;
}
/** /**
* Implements retransmit_request_job_t.get_message_id. * Implements retransmit_request_job_t.get_message_id.
*/ */
@@ -100,9 +121,12 @@ retransmit_request_job_t *retransmit_request_job_create(u_int32_t message_id,ike
this->public.get_ike_sa_id = (ike_sa_id_t * (*)(retransmit_request_job_t *)) get_ike_sa_id; 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.get_message_id = (u_int32_t (*)(retransmit_request_job_t *)) get_message_id;
this->public.destroy = (void (*)(retransmit_request_job_t *)) destroy; 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 */ /* private variables */
this->message_id = message_id; this->message_id = message_id;
this->retransmit_count = 0;
this->ike_sa_id = ike_sa_id->clone(ike_sa_id); this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
return &(this->public); return &(this->public);
@@ -41,6 +41,21 @@ struct retransmit_request_job_t {
*/ */
job_t job_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 * @brief Returns the message_id of the request to be resent
* *
+50 -6
View File
@@ -40,6 +40,7 @@
#include <sa/states/initiator_init.h> #include <sa/states/initiator_init.h>
#include <sa/states/responder_init.h> #include <sa/states/responder_init.h>
#include <queues/jobs/delete_ike_sa_job.h> #include <queues/jobs/delete_ike_sa_job.h>
#include <queues/jobs/retransmit_request_job.h>
@@ -197,15 +198,20 @@ struct private_ike_sa_t {
} secrets; } secrets;
/** /**
* next message id to receive * next message id to receive.
*/ */
u_int32_t message_id_in; u_int32_t message_id_in;
/** /**
* next message id to send * next message id to send.
*/ */
u_int32_t message_id_out; u_int32_t message_id_out;
/**
* Last message id which was successfully replied.
*/
u_int32_t last_replied_message_id;
/** /**
* a logger for this IKE_SA * a logger for this IKE_SA
*/ */
@@ -430,8 +436,18 @@ status_t retransmit_request (private_ike_sa_t *this, u_int32_t message_id)
{ {
return NOT_FOUND; return NOT_FOUND;
} }
if (message_id == this->last_replied_message_id)
{
return NOT_FOUND;
}
packet = this->last_responded_message->get_packet(this->last_responded_message); if (this->last_requested_message == NULL)
{
return NOT_FOUND;
}
packet = this->last_requested_message->get_packet(this->last_requested_message);
charon->send_queue->add(charon->send_queue, packet); charon->send_queue->add(charon->send_queue, packet);
return SUCCESS; return SUCCESS;
@@ -650,6 +666,8 @@ static status_t send_request (private_ike_sa_t *this,message_t * message)
{ {
packet_t *packet; packet_t *packet;
status_t status; status_t status;
retransmit_request_job_t *retransmit_job;
u_int32_t timeout;
if (message->get_message_id(message) != this->message_id_out) if (message->get_message_id(message) != this->message_id_out)
{ {
@@ -678,7 +696,22 @@ static status_t send_request (private_ike_sa_t *this,message_t * message)
this->logger->log(this->logger, CONTROL|MOST, "replace last requested message with new one"); this->logger->log(this->logger, CONTROL|MOST, "replace last requested message with new one");
this->last_requested_message = message; this->last_requested_message = message;
retransmit_job = retransmit_request_job_create(this->message_id_out,this->ike_sa_id);
status = charon->configuration_manager->get_retransmit_timeout (charon->configuration_manager,retransmit_job->get_retransmit_count(retransmit_job),&timeout);
if (status != SUCCESS)
{
this->logger->log(this->logger, CONTROL|MOST, "No retransmit job for message created!");
retransmit_job->destroy(retransmit_job);
}
else
{
this->logger->log(this->logger, CONTROL|MOST, "Request will be retransmitted in %d ms.",timeout);
charon->event_queue->add_relative(charon->event_queue,(job_t *) retransmit_job,timeout);
}
/* message counter can now be increased */ /* message counter can now be increased */
this->logger->log(this->logger, CONTROL|MOST, "Increase message counter for outgoing messages"); this->logger->log(this->logger, CONTROL|MOST, "Increase message counter for outgoing messages");
this->message_id_out++; this->message_id_out++;
@@ -726,7 +759,15 @@ static status_t send_response (private_ike_sa_t *this,message_t * message)
} }
/** /**
* Implementation of protected_ike_sa_t.destroy. * Implementation of protected_ike_sa_t.set_last_replied_message_id.
*/
static void set_last_replied_message_id (private_ike_sa_t *this,u_int32_t message_id)
{
this->last_replied_message_id = message_id;
}
/**
* Implementation of protected_ike_sa_t.reset_message_buffers.
*/ */
static void reset_message_buffers (private_ike_sa_t *this) static void reset_message_buffers (private_ike_sa_t *this)
{ {
@@ -747,6 +788,7 @@ static void reset_message_buffers (private_ike_sa_t *this)
this->message_id_out = 0; this->message_id_out = 0;
this->message_id_in = 0; this->message_id_in = 0;
this->last_replied_message_id = -1;
} }
/** /**
@@ -879,7 +921,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->protected.get_crypter_responder = (crypter_t *(*) (protected_ike_sa_t *)) get_crypter_responder; this->protected.get_crypter_responder = (crypter_t *(*) (protected_ike_sa_t *)) get_crypter_responder;
this->protected.get_signer_responder = (signer_t *(*) (protected_ike_sa_t *)) get_signer_responder; this->protected.get_signer_responder = (signer_t *(*) (protected_ike_sa_t *)) get_signer_responder;
this->protected.reset_message_buffers = (void (*) (protected_ike_sa_t *)) reset_message_buffers; this->protected.reset_message_buffers = (void (*) (protected_ike_sa_t *)) reset_message_buffers;
this->protected.set_last_replied_message_id = (void (*) (protected_ike_sa_t *,u_int32_t)) set_last_replied_message_id;
/* private functions */ /* private functions */
this->resend_last_reply = resend_last_reply; this->resend_last_reply = resend_last_reply;
this->create_delete_job = create_delete_job; this->create_delete_job = create_delete_job;
@@ -897,6 +940,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->last_responded_message = NULL; this->last_responded_message = NULL;
this->message_id_out = 0; this->message_id_out = 0;
this->message_id_in = 0; this->message_id_in = 0;
this->last_replied_message_id = -1;
this->secrets.d_key = CHUNK_INITIALIZER; this->secrets.d_key = CHUNK_INITIALIZER;
this->secrets.ai_key = CHUNK_INITIALIZER; this->secrets.ai_key = CHUNK_INITIALIZER;
this->secrets.ar_key = CHUNK_INITIALIZER; this->secrets.ar_key = CHUNK_INITIALIZER;
+8
View File
@@ -280,6 +280,14 @@ struct protected_ike_sa_t {
*/ */
void (*set_new_state) (protected_ike_sa_t *this,state_t *state); void (*set_new_state) (protected_ike_sa_t *this,state_t *state);
/**
* Sets the last replied message id.
*
* @param this calling object
* @param message_id message id
*/
void (*set_last_replied_message_id) (protected_ike_sa_t *this,u_int32_t message_id);
/** /**
* Gets the internal stored initiator crypter_t object. * Gets the internal stored initiator crypter_t object.
* *
@@ -193,6 +193,7 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *r
return status; return status;
} }
this->ike_sa->set_last_replied_message_id(this->ike_sa,request->get_message_id(request));
this->logger->log(this->logger, CONTROL | MORE, "IKE_AUTH response successfully handled. IKE_SA established."); this->logger->log(this->logger, CONTROL | MORE, "IKE_AUTH response successfully handled. IKE_SA established.");
/* create new state */ /* create new state */
@@ -391,6 +391,7 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t
request->destroy(request); request->destroy(request);
return DELETE_ME; return DELETE_ME;
} }
this->ike_sa->set_last_replied_message_id(this->ike_sa,request->get_message_id(request));
/* state can now be changed */ /* state can now be changed */
this->logger->log(this->logger, CONTROL|MOST, "Create next state object"); this->logger->log(this->logger, CONTROL|MOST, "Create next state object");
+1 -1
View File
@@ -142,7 +142,7 @@ daemon_t *daemon_create()
charon->job_queue = job_queue_create(); charon->job_queue = job_queue_create();
charon->event_queue = event_queue_create(); charon->event_queue = event_queue_create();
charon->send_queue = send_queue_create(); charon->send_queue = send_queue_create();
charon->configuration_manager = configuration_manager_create(); charon->configuration_manager = configuration_manager_create(RETRANSMIT_TIMEOUT,MAX_RETRANSMIT_COUNT);
charon->sender = NULL; charon->sender = NULL;
charon->receiver = NULL; charon->receiver = NULL;
charon->scheduler = NULL; charon->scheduler = NULL;
+24 -7
View File
@@ -153,7 +153,6 @@ static void process_jobs(private_thread_pool_t *this)
case RETRANSMIT_REQUEST: case RETRANSMIT_REQUEST:
{ {
this->process_retransmit_request_job(this, (retransmit_request_job_t*)job); this->process_retransmit_request_job(this, (retransmit_request_job_t*)job);
job->destroy(job);
break; break;
} }
default: default:
@@ -327,10 +326,13 @@ static void process_delete_ike_sa_job(private_thread_pool_t *this, delete_ike_sa
*/ */
static void process_retransmit_request_job(private_thread_pool_t *this, retransmit_request_job_t *job) static void process_retransmit_request_job(private_thread_pool_t *this, retransmit_request_job_t *job)
{ {
status_t status;
ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job); ike_sa_id_t *ike_sa_id = job->get_ike_sa_id(job);
u_int32_t message_id = job->get_message_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; ike_sa_t *ike_sa;
status_t status;
this->worker_logger->log(this->worker_logger, CONTROL|MOST, "checking out IKE SA %lld:%lld, role %s", this->worker_logger->log(this->worker_logger, CONTROL|MOST, "checking out IKE SA %lld:%lld, role %s",
ike_sa_id->get_initiator_spi(ike_sa_id), ike_sa_id->get_initiator_spi(ike_sa_id),
@@ -348,7 +350,8 @@ static void process_retransmit_request_job(private_thread_pool_t *this, retransm
if (status != SUCCESS) if (status != SUCCESS)
{ {
this->worker_logger->log(this->worker_logger, CONTROL | MOST, "Message does'nt have to be retransmitted"); this->worker_logger->log(this->worker_logger, CONTROL | MOST, "Message doesn't have to be retransmitted");
stop_retransmitting = TRUE;
} }
this->worker_logger->log(this->worker_logger, CONTROL|MOST, "Checkin IKE SA %lld:%lld, role %s", this->worker_logger->log(this->worker_logger, CONTROL|MOST, "Checkin IKE SA %lld:%lld, role %s",
@@ -361,11 +364,25 @@ static void process_retransmit_request_job(private_thread_pool_t *this, retransm
{ {
this->worker_logger->log(this->worker_logger, ERROR, "Checkin of IKE SA failed!"); this->worker_logger->log(this->worker_logger, ERROR, "Checkin of IKE SA failed!");
} }
/*
u_int32_t message_id = message->get_message_id(message);
retransmit_request_job_t *new_job = retransmit_request_job_create(message_id,ike_sa_id);
charon->event_queue->add_relative(charon->event_queue,(job_t *) new_job,5000);*/
if (stop_retransmitting)
{
job->destroy(job);
return;
}
job->increase_retransmit_count(job);
status = charon->configuration_manager->get_retransmit_timeout (charon->configuration_manager,job->get_retransmit_count(job),&timeout);
if (status != SUCCESS)
{
this->worker_logger->log(this->worker_logger, CONTROL | MOST, "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);
} }
/** /**