diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/charon/config/configuration_manager.c | 31 | ||||
-rw-r--r-- | Source/charon/config/configuration_manager.h | 27 | ||||
-rw-r--r-- | Source/charon/daemon.c | 2 | ||||
-rw-r--r-- | Source/charon/daemon.h | 12 | ||||
-rw-r--r-- | Source/charon/queues/jobs/retransmit_request_job.c | 24 | ||||
-rw-r--r-- | Source/charon/queues/jobs/retransmit_request_job.h | 15 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa.c | 56 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa.h | 8 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_auth_requested.c | 1 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_sa_init_requested.c | 1 | ||||
-rw-r--r-- | Source/charon/testcases/testcases.c | 2 | ||||
-rw-r--r-- | Source/charon/threads/thread_pool.c | 31 |
12 files changed, 188 insertions, 22 deletions
diff --git a/Source/charon/config/configuration_manager.c b/Source/charon/config/configuration_manager.c index f3c3cd4cc..2f7fc099f 100644 --- a/Source/charon/config/configuration_manager.c +++ b/Source/charon/config/configuration_manager.c @@ -123,6 +123,17 @@ struct private_configuration_manager_t { * Assigned logger object. */ 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 @@ -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)); } +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. */ @@ -499,7 +525,7 @@ static void destroy(private_configuration_manager_t *this) /* * 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); @@ -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_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_retransmit_timeout = (status_t (*) (configuration_manager_t *, u_int32_t retransmit_count, u_int32_t *timeout))get_retransmit_timeout; /* private functions */ this->load_default_config = load_default_config; @@ -519,6 +546,8 @@ configuration_manager_t *configuration_manager_create() this->configurations = linked_list_create(); this->sa_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); diff --git a/Source/charon/config/configuration_manager.h b/Source/charon/config/configuration_manager.h index 9cc6a313b..bc6c6e81f 100644 --- a/Source/charon/config/configuration_manager.h +++ b/Source/charon/config/configuration_manager.h @@ -39,7 +39,7 @@ typedef struct configuration_manager_t 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. * * 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); /** - * Gets the configuration information needed for IKE_SA_INIT exchange + * Get the configuration information needed for IKE_SA_INIT exchange * for specific host informations. * * 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); /** - * 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. * @@ -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); /** - * 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. * * The returned sa_config_t object MUST NOT be destroyed cause it's the original one. @@ -105,6 +105,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); /** + * 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 * * @@ -118,12 +133,14 @@ struct configuration_manager_t { /** * 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 * - pointer to created manager object if succeeded * - NULL if memory allocation failed * * @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_*/ diff --git a/Source/charon/daemon.c b/Source/charon/daemon.c index 7fe3d5b28..d1e0c13c2 100644 --- a/Source/charon/daemon.c +++ b/Source/charon/daemon.c @@ -174,7 +174,7 @@ static void initialize(private_daemon_t *this) this->public.job_queue = job_queue_create(); this->public.event_queue = event_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.receiver = receiver_create(); diff --git a/Source/charon/daemon.h b/Source/charon/daemon.h index 8da5eb5eb..1b5048282 100644 --- a/Source/charon/daemon.h +++ b/Source/charon/daemon.h @@ -52,11 +52,21 @@ /** * Port on which the daemon will - * listen for incoming traffic + * listen for incoming traffic. */ #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 * maximum allowed level for ever context, the definiton * of the context may be less verbose. diff --git a/Source/charon/queues/jobs/retransmit_request_job.c b/Source/charon/queues/jobs/retransmit_request_job.c index f54de361d..089ebbfec 100644 --- a/Source/charon/queues/jobs/retransmit_request_job.c +++ b/Source/charon/queues/jobs/retransmit_request_job.c @@ -46,6 +46,11 @@ struct private_retransmit_request_job_t { * ID of the IKE_SA which the message belongs to. */ ike_sa_id_t *ike_sa_id; + + /** + * Number of times a request was retransmitted + */ + u_int32_t retransmit_count; }; @@ -66,6 +71,22 @@ static ike_sa_id_t *get_ike_sa_id(private_retransmit_request_job_t *this) } /** + * 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. */ static u_int32_t get_message_id(private_retransmit_request_job_t *this) @@ -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_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); return &(this->public); diff --git a/Source/charon/queues/jobs/retransmit_request_job.h b/Source/charon/queues/jobs/retransmit_request_job.h index 591c79864..0573f04ec 100644 --- a/Source/charon/queues/jobs/retransmit_request_job.h +++ b/Source/charon/queues/jobs/retransmit_request_job.h @@ -42,6 +42,21 @@ struct retransmit_request_job_t { 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 diff --git a/Source/charon/sa/ike_sa.c b/Source/charon/sa/ike_sa.c index a974ce3e8..6abed041c 100644 --- a/Source/charon/sa/ike_sa.c +++ b/Source/charon/sa/ike_sa.c @@ -40,6 +40,7 @@ #include <sa/states/initiator_init.h> #include <sa/states/responder_init.h> #include <queues/jobs/delete_ike_sa_job.h> +#include <queues/jobs/retransmit_request_job.h> @@ -197,16 +198,21 @@ struct private_ike_sa_t { } secrets; /** - * next message id to receive + * next message id to receive. */ u_int32_t message_id_in; /** - * next message id to send + * next message id to send. */ 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 */ logger_t *logger; @@ -430,8 +436,18 @@ status_t retransmit_request (private_ike_sa_t *this, u_int32_t message_id) { 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); return SUCCESS; @@ -650,6 +666,8 @@ static status_t send_request (private_ike_sa_t *this,message_t * message) { packet_t *packet; status_t status; + retransmit_request_job_t *retransmit_job; + u_int32_t timeout; 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->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 */ this->logger->log(this->logger, CONTROL|MOST, "Increase message counter for outgoing messages"); 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) { @@ -747,6 +788,7 @@ static void reset_message_buffers (private_ike_sa_t *this) this->message_id_out = 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_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.set_last_replied_message_id = (void (*) (protected_ike_sa_t *,u_int32_t)) set_last_replied_message_id; + /* private functions */ this->resend_last_reply = resend_last_reply; 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->message_id_out = 0; this->message_id_in = 0; + this->last_replied_message_id = -1; this->secrets.d_key = CHUNK_INITIALIZER; this->secrets.ai_key = CHUNK_INITIALIZER; this->secrets.ar_key = CHUNK_INITIALIZER; diff --git a/Source/charon/sa/ike_sa.h b/Source/charon/sa/ike_sa.h index 6a12aaf8d..b8a897af5 100644 --- a/Source/charon/sa/ike_sa.h +++ b/Source/charon/sa/ike_sa.h @@ -281,6 +281,14 @@ struct protected_ike_sa_t { 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. * * @param this calling object diff --git a/Source/charon/sa/states/ike_auth_requested.c b/Source/charon/sa/states/ike_auth_requested.c index 82d7ca934..9fe7b1b9f 100644 --- a/Source/charon/sa/states/ike_auth_requested.c +++ b/Source/charon/sa/states/ike_auth_requested.c @@ -193,6 +193,7 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *r 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."); /* create new state */ diff --git a/Source/charon/sa/states/ike_sa_init_requested.c b/Source/charon/sa/states/ike_sa_init_requested.c index b5ebd1283..ebca25ffc 100644 --- a/Source/charon/sa/states/ike_sa_init_requested.c +++ b/Source/charon/sa/states/ike_sa_init_requested.c @@ -391,6 +391,7 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t request->destroy(request); return DELETE_ME; } + this->ike_sa->set_last_replied_message_id(this->ike_sa,request->get_message_id(request)); /* state can now be changed */ this->logger->log(this->logger, CONTROL|MOST, "Create next state object"); diff --git a/Source/charon/testcases/testcases.c b/Source/charon/testcases/testcases.c index 28eea6eca..f02d9d4a0 100644 --- a/Source/charon/testcases/testcases.c +++ b/Source/charon/testcases/testcases.c @@ -142,7 +142,7 @@ daemon_t *daemon_create() charon->job_queue = job_queue_create(); charon->event_queue = event_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->receiver = NULL; charon->scheduler = NULL; diff --git a/Source/charon/threads/thread_pool.c b/Source/charon/threads/thread_pool.c index 649679fc3..87f25233f 100644 --- a/Source/charon/threads/thread_pool.c +++ b/Source/charon/threads/thread_pool.c @@ -153,7 +153,6 @@ static void process_jobs(private_thread_pool_t *this) case RETRANSMIT_REQUEST: { this->process_retransmit_request_job(this, (retransmit_request_job_t*)job); - job->destroy(job); break; } 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) { - status_t status; + 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|MOST, "checking out IKE SA %lld:%lld, role %s", 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) { - 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", @@ -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!"); } -/* - 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); } /** |