diff options
Diffstat (limited to 'src/charon/sa/task_manager.c')
-rw-r--r-- | src/charon/sa/task_manager.c | 292 |
1 files changed, 156 insertions, 136 deletions
diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c index 0630647c9..e5c5fe178 100644 --- a/src/charon/sa/task_manager.c +++ b/src/charon/sa/task_manager.c @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: task_manager.c 4484 2008-10-27 11:13:33Z martin $ + * $Id: task_manager.c 4857 2009-02-09 10:45:51Z martin $ */ #include "task_manager.h" @@ -48,12 +48,12 @@ typedef struct exchange_t exchange_t; * An exchange in the air, used do detect and handle retransmission */ struct exchange_t { - + /** * Message ID used for this transaction */ u_int32_t mid; - + /** * generated packet for retransmission */ @@ -66,17 +66,17 @@ typedef struct private_task_manager_t private_task_manager_t; * private data of the task manager */ struct private_task_manager_t { - + /** * public functions */ task_manager_t public; - + /** * associated IKE_SA we are serving */ ike_sa_t *ike_sa; - + /** * Exchange we are currently handling as responder */ @@ -85,14 +85,14 @@ struct private_task_manager_t { * Message ID of the exchange */ u_int32_t mid; - + /** * packet for retransmission */ packet_t *packet; } responding; - + /** * Exchange we are currently handling as initiator */ @@ -118,17 +118,17 @@ struct private_task_manager_t { exchange_type_t type; } initiating; - + /** * List of queued tasks not yet in action */ linked_list_t *queued_tasks; - + /** * List of active tasks, initiated by ourselve */ linked_list_t *active_tasks; - + /** * List of tasks initiated by peer */ @@ -417,43 +417,48 @@ static status_t build_request(private_task_manager_t *this) message->set_exchange_type(message, exchange); this->initiating.type = exchange; this->initiating.retransmitted = 0; - + iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE); while (iterator->iterate(iterator, (void*)&task)) { - switch (task->build(task, message)) - { - case SUCCESS: - /* task completed, remove it */ - iterator->remove(iterator); - task->destroy(task); - break; - case NEED_MORE: - /* processed, but task needs another exchange */ - break; - case FAILED: - default: - /* critical failure, destroy IKE_SA */ - iterator->destroy(iterator); + switch (task->build(task, message)) + { + case SUCCESS: + /* task completed, remove it */ + iterator->remove(iterator); + task->destroy(task); + break; + case NEED_MORE: + /* processed, but task needs another exchange */ + break; + case FAILED: + default: + /* critical failure, destroy IKE_SA */ + iterator->destroy(iterator); message->destroy(message); flush(this); - return DESTROY_ME; - } + return DESTROY_ME; + } } iterator->destroy(iterator); - - DESTROY_IF(this->initiating.packet); + + /* update exchange type if a task changed it */ + this->initiating.type = message->get_exchange_type(message); + status = this->ike_sa->generate_message(this->ike_sa, message, &this->initiating.packet); - message->destroy(message); if (status != SUCCESS) { - /* message generation failed. There is nothing more to do than to + /* message generation failed. There is nothing more to do than to * close the SA */ + message->destroy(message); flush(this); - return DESTROY_ME; + return DESTROY_ME; } + charon->bus->message(charon->bus, message, FALSE); + message->destroy(message); + return retransmit(this, this->initiating.mid); } @@ -473,32 +478,34 @@ static status_t process_response(private_task_manager_t *this, exchange_type_names, this->initiating.type); return DESTROY_ME; } - + /* catch if we get resetted while processing */ this->reset = FALSE; iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE); while (iterator->iterate(iterator, (void*)&task)) { - switch (task->process(task, message)) - { - case SUCCESS: - /* task completed, remove it */ - iterator->remove(iterator); - task->destroy(task); - break; - case NEED_MORE: - /* processed, but task needs another exchange */ - break; - case FAILED: - default: - /* critical failure, destroy IKE_SA */ - iterator->destroy(iterator); - return DESTROY_ME; - } - if (this->reset) - { /* start all over again if we were reset */ - this->reset = FALSE; - iterator->destroy(iterator); + switch (task->process(task, message)) + { + case SUCCESS: + /* task completed, remove it */ + iterator->remove(iterator); + task->destroy(task); + break; + case NEED_MORE: + /* processed, but task needs another exchange */ + break; + case FAILED: + default: + /* critical failure, destroy IKE_SA */ + iterator->remove(iterator); + iterator->destroy(iterator); + task->destroy(task); + return DESTROY_ME; + } + if (this->reset) + { /* start all over again if we were reset */ + this->reset = FALSE; + iterator->destroy(iterator); return build_request(this); } } @@ -506,7 +513,9 @@ static status_t process_response(private_task_manager_t *this, this->initiating.mid++; this->initiating.type = EXCHANGE_TYPE_UNDEFINED; - + this->initiating.packet->destroy(this->initiating.packet); + this->initiating.packet = NULL; + return build_request(this); } @@ -525,34 +534,34 @@ static void handle_collisions(private_task_manager_t *this, task_t *task) if (type == IKE_REKEY || type == CHILD_REKEY || type == CHILD_DELETE || type == IKE_DELETE || type == IKE_REAUTH) { - /* find an exchange collision, and notify these tasks */ - iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE); - while (iterator->iterate(iterator, (void**)&active)) - { - switch (active->get_type(active)) - { - case IKE_REKEY: - if (type == IKE_REKEY || type == IKE_DELETE || - type == IKE_REAUTH) - { - ike_rekey_t *rekey = (ike_rekey_t*)active; - rekey->collide(rekey, task); - break; - } - continue; - case CHILD_REKEY: - if (type == CHILD_REKEY || type == CHILD_DELETE) - { - child_rekey_t *rekey = (child_rekey_t*)active; - rekey->collide(rekey, task); - break; - } - continue; - default: - continue; - } - iterator->destroy(iterator); - return; + /* find an exchange collision, and notify these tasks */ + iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE); + while (iterator->iterate(iterator, (void**)&active)) + { + switch (active->get_type(active)) + { + case IKE_REKEY: + if (type == IKE_REKEY || type == IKE_DELETE || + type == IKE_REAUTH) + { + ike_rekey_t *rekey = (ike_rekey_t*)active; + rekey->collide(rekey, task); + break; + } + continue; + case CHILD_REKEY: + if (type == CHILD_REKEY || type == CHILD_DELETE) + { + child_rekey_t *rekey = (child_rekey_t*)active; + rekey->collide(rekey, task); + break; + } + continue; + default: + continue; + } + iterator->destroy(iterator); + return; } iterator->destroy(iterator); } @@ -571,10 +580,10 @@ static status_t build_response(private_task_manager_t *this, message_t *request) host_t *me, *other; bool delete = FALSE; status_t status; - + me = request->get_destination(request); other = request->get_source(request); - + message = message_create(); message->set_exchange_type(message, request->get_exchange_type(request)); /* send response along the path the request came in */ @@ -582,29 +591,29 @@ static status_t build_response(private_task_manager_t *this, message_t *request) message->set_destination(message, other->clone(other)); message->set_message_id(message, this->responding.mid); message->set_request(message, FALSE); - + iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE); while (iterator->iterate(iterator, (void*)&task)) { - switch (task->build(task, message)) - { - case SUCCESS: - /* task completed, remove it */ - iterator->remove(iterator); + switch (task->build(task, message)) + { + case SUCCESS: + /* task completed, remove it */ + iterator->remove(iterator); handle_collisions(this, task); - case NEED_MORE: - /* processed, but task needs another exchange */ - break; - case FAILED: - default: - /* destroy IKE_SA, but SEND response first */ - delete = TRUE; - break; - } - if (delete) - { - break; - } + case NEED_MORE: + /* processed, but task needs another exchange */ + break; + case FAILED: + default: + /* destroy IKE_SA, but SEND response first */ + delete = TRUE; + break; + } + if (delete) + { + break; + } } iterator->destroy(iterator); @@ -614,7 +623,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request) ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa); id->set_responder_spi(id, 0); } - + /* message complete, send it */ DESTROY_IF(this->responding.packet); status = this->ike_sa->generate_message(this->ike_sa, message, @@ -623,7 +632,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request) message->destroy(message); if (status != SUCCESS) { - return DESTROY_ME; + return DESTROY_ME; } charon->sender->send(charon->sender, @@ -646,7 +655,7 @@ static status_t process_request(private_task_manager_t *this, payload_t *payload; notify_payload_t *notify; delete_payload_t *delete; - + /* create tasks depending on request type */ switch (message->get_exchange_type(message)) { @@ -713,7 +722,8 @@ static status_t process_request(private_task_manager_t *this, { if (notify_found) { - task = (task_t*)child_rekey_create(this->ike_sa, NULL); + task = (task_t*)child_rekey_create(this->ike_sa, + PROTO_NONE, 0); } else { @@ -770,7 +780,8 @@ static status_t process_request(private_task_manager_t *this, } else { - task = (task_t*)child_delete_create(this->ike_sa, NULL); + task = (task_t*)child_delete_create(this->ike_sa, + PROTO_NONE, 0); } break; } @@ -801,30 +812,32 @@ static status_t process_request(private_task_manager_t *this, default: break; } - + /* let the tasks process the message */ iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE); while (iterator->iterate(iterator, (void*)&task)) { - switch (task->process(task, message)) - { - case SUCCESS: - /* task completed, remove it */ - iterator->remove(iterator); - task->destroy(task); - break; - case NEED_MORE: - /* processed, but task needs at least another call to build() */ - break; - case FAILED: - default: - /* critical failure, destroy IKE_SA */ - iterator->destroy(iterator); - return DESTROY_ME; - } + switch (task->process(task, message)) + { + case SUCCESS: + /* task completed, remove it */ + iterator->remove(iterator); + task->destroy(task); + break; + case NEED_MORE: + /* processed, but task needs at least another call to build() */ + break; + case FAILED: + default: + /* critical failure, destroy IKE_SA */ + iterator->remove(iterator); + iterator->destroy(iterator); + task->destroy(task); + return DESTROY_ME; + } } iterator->destroy(iterator); - + return build_response(this, message); } @@ -834,7 +847,7 @@ static status_t process_request(private_task_manager_t *this, static status_t process_message(private_task_manager_t *this, message_t *msg) { u_int32_t mid = msg->get_message_id(msg); - + if (msg->get_request(msg)) { if (mid == this->responding.mid) @@ -919,7 +932,7 @@ static void queue_task(private_task_manager_t *this, task_t *task) static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *other) { task_t *task; - + /* move queued tasks from other to this */ while (other->queued_tasks->remove_last(other->queued_tasks, (void**)&task) == SUCCESS) @@ -950,7 +963,8 @@ static bool busy(private_task_manager_t *this) /** * Implementation of task_manager_t.reset */ -static void reset(private_task_manager_t *this) +static void reset(private_task_manager_t *this, + u_int32_t initiate, u_int32_t respond) { task_t *task; @@ -959,8 +973,14 @@ static void reset(private_task_manager_t *this) DESTROY_IF(this->initiating.packet); this->responding.packet = NULL; this->initiating.packet = NULL; - this->responding.mid = 0; - this->initiating.mid = 0; + if (initiate != UINT_MAX) + { + this->initiating.mid = initiate; + } + if (respond != UINT_MAX) + { + this->responding.mid = respond; + } this->initiating.type = EXCHANGE_TYPE_UNDEFINED; /* reset active tasks */ @@ -996,16 +1016,16 @@ static void destroy(private_task_manager_t *this) task_manager_t *task_manager_create(ike_sa_t *ike_sa) { private_task_manager_t *this = malloc_thing(private_task_manager_t); - + this->public.process_message = (status_t(*)(task_manager_t*,message_t*))process_message; this->public.queue_task = (void(*)(task_manager_t*,task_t*))queue_task; this->public.initiate = (status_t(*)(task_manager_t*))build_request; this->public.retransmit = (status_t(*)(task_manager_t*,u_int32_t))retransmit; - this->public.reset = (void(*)(task_manager_t*))reset; + this->public.reset = (void(*)(task_manager_t*,u_int32_t,u_int32_t))reset; this->public.adopt_tasks = (void(*)(task_manager_t*,task_manager_t*))adopt_tasks; this->public.busy = (bool(*)(task_manager_t*))busy; this->public.destroy = (void(*)(task_manager_t*))destroy; - + this->ike_sa = ike_sa; this->responding.packet = NULL; this->initiating.packet = NULL; @@ -1016,6 +1036,6 @@ task_manager_t *task_manager_create(ike_sa_t *ike_sa) this->active_tasks = linked_list_create(); this->passive_tasks = linked_list_create(); this->reset = FALSE; - + return &this->public; } |