4 * @brief Implementation of task_manager_t.
9 * Copyright (C) 2007 Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 #include "task_manager.h"
26 #include <sa/tasks/ike_init.h>
27 #include <sa/tasks/ike_natd.h>
28 #include <sa/tasks/ike_auth.h>
29 #include <sa/tasks/ike_cert.h>
30 #include <sa/tasks/ike_rekey.h>
31 #include <sa/tasks/ike_delete.h>
32 #include <sa/tasks/ike_config.h>
33 #include <sa/tasks/ike_dpd.h>
34 #include <sa/tasks/child_create.h>
35 #include <sa/tasks/child_rekey.h>
36 #include <sa/tasks/child_delete.h>
37 #include <encoding/payloads/delete_payload.h>
38 #include <processing/jobs/retransmit_job.h>
40 typedef struct exchange_t exchange_t
;
43 * An exchange in the air, used do detect and handle retransmission
48 * Message ID used for this transaction
53 * generated packet for retransmission
58 typedef struct private_task_manager_t private_task_manager_t
;
61 * private data of the task manager
63 struct private_task_manager_t
{
68 task_manager_t
public;
71 * associated IKE_SA we are serving
76 * Exchange we are currently handling as responder
80 * Message ID of the exchange
85 * packet for retransmission
92 * Exchange we are currently handling as initiator
96 * Message ID of the exchange
101 * how many times we have retransmitted so far
106 * packet for retransmission
111 * type of the initated exchange
113 exchange_type_t type
;
118 * List of queued tasks not yet in action
120 linked_list_t
*queued_tasks
;
123 * List of active tasks, initiated by ourselve
125 linked_list_t
*active_tasks
;
128 * List of tasks initiated by peer
130 linked_list_t
*passive_tasks
;
134 * flush all tasks in the task manager
136 static void flush(private_task_manager_t
*this)
140 this->queued_tasks
->destroy_offset(this->queued_tasks
,
141 offsetof(task_t
, destroy
));
142 this->passive_tasks
->destroy_offset(this->passive_tasks
,
143 offsetof(task_t
, destroy
));
145 /* emmit outstanding signals for tasks */
146 while (this->active_tasks
->remove_last(this->active_tasks
,
147 (void**)&task
) == SUCCESS
)
149 switch (task
->get_type(task
))
152 SIG(IKE_UP_FAILED
, "establishing IKE_SA failed");
155 SIG(IKE_DOWN_FAILED
, "IKE_SA deleted");
158 SIG(IKE_REKEY_FAILED
, "rekeying IKE_SA failed");
161 SIG(CHILD_UP_FAILED
, "establishing CHILD_SA failed");
164 SIG(CHILD_DOWN_FAILED
, "deleting CHILD_SA failed");
167 SIG(IKE_REKEY_FAILED
, "rekeying CHILD_SA failed");
174 this->queued_tasks
= linked_list_create();
175 this->passive_tasks
= linked_list_create();
179 * move a task of a specific type from the queue to the active list
181 static bool activate_task(private_task_manager_t
*this, task_type_t type
)
183 iterator_t
*iterator
;
187 iterator
= this->queued_tasks
->create_iterator(this->queued_tasks
, TRUE
);
188 while (iterator
->iterate(iterator
, (void**)&task
))
190 if (task
->get_type(task
) == type
)
192 DBG2(DBG_IKE
, " activating %N task", task_type_names
, type
);
193 iterator
->remove(iterator
);
194 this->active_tasks
->insert_last(this->active_tasks
, task
);
199 iterator
->destroy(iterator
);
204 * Implementation of task_manager_t.retransmit
206 static status_t
retransmit(private_task_manager_t
*this, u_int32_t message_id
)
208 if (message_id
== this->initiating
.mid
)
213 timeout
= charon
->configuration
->get_retransmit_timeout(
214 charon
->configuration
, this->initiating
.retransmitted
);
217 DBG1(DBG_IKE
, "giving up after %d retransmits",
218 this->initiating
.retransmitted
- 1);
222 if (this->initiating
.retransmitted
)
224 DBG1(DBG_IKE
, "retransmit %d of request with message ID %d",
225 this->initiating
.retransmitted
, message_id
);
227 this->initiating
.retransmitted
++;
229 charon
->sender
->send(charon
->sender
,
230 this->initiating
.packet
->clone(this->initiating
.packet
));
231 job
= (job_t
*)retransmit_job_create(this->initiating
.mid
,
232 this->ike_sa
->get_id(this->ike_sa
));
233 charon
->event_queue
->add_relative(charon
->event_queue
, job
, timeout
);
239 * build a request using the active task list
240 * Implementation of task_manager_t.initiate
242 static status_t
build_request(private_task_manager_t
*this)
244 iterator_t
*iterator
;
248 exchange_type_t exchange
= 0;
250 if (this->initiating
.type
!= EXCHANGE_TYPE_UNDEFINED
)
252 DBG2(DBG_IKE
, "delaying task initiation, exchange in progress");
253 /* do not initiate if we already have a message in the air */
257 if (this->active_tasks
->get_count(this->active_tasks
) == 0)
259 DBG2(DBG_IKE
, "activating new tasks");
260 switch (this->ike_sa
->get_state(this->ike_sa
))
263 if (activate_task(this, IKE_INIT
))
265 exchange
= IKE_SA_INIT
;
266 activate_task(this, IKE_NATD
);
267 activate_task(this, IKE_CERT
);
268 activate_task(this, IKE_AUTHENTICATE
);
269 activate_task(this, IKE_CONFIG
);
270 activate_task(this, CHILD_CREATE
);
273 case IKE_ESTABLISHED
:
274 if (activate_task(this, CHILD_CREATE
))
276 exchange
= CREATE_CHILD_SA
;
277 activate_task(this, IKE_CONFIG
);
280 if (activate_task(this, CHILD_DELETE
))
282 exchange
= INFORMATIONAL
;
285 if (activate_task(this, CHILD_REKEY
))
287 exchange
= CREATE_CHILD_SA
;
290 if (activate_task(this, IKE_DELETE
))
292 exchange
= INFORMATIONAL
;
295 if (activate_task(this, IKE_REKEY
))
297 exchange
= CREATE_CHILD_SA
;
300 if (activate_task(this, IKE_DEADPEER
))
302 exchange
= INFORMATIONAL
;
306 if (activate_task(this, IKE_DELETE
))
308 exchange
= INFORMATIONAL
;
318 DBG2(DBG_IKE
, "reinitiating already active tasks");
319 iterator
= this->active_tasks
->create_iterator(this->active_tasks
, TRUE
);
320 while (iterator
->iterate(iterator
, (void**)&task
))
322 DBG2(DBG_IKE
, " %N task", task_type_names
, task
->get_type(task
));
323 switch (task
->get_type(task
))
326 exchange
= IKE_SA_INIT
;
328 case IKE_AUTHENTICATE
:
336 iterator
->destroy(iterator
);
341 DBG2(DBG_IKE
, "nothing to initiate");
342 /* nothing to do yet... */
346 message
= message_create();
347 message
->set_message_id(message
, this->initiating
.mid
);
348 message
->set_exchange_type(message
, exchange
);
349 this->initiating
.type
= exchange
;
350 this->initiating
.retransmitted
= 0;
352 iterator
= this->active_tasks
->create_iterator(this->active_tasks
, TRUE
);
353 while (iterator
->iterate(iterator
, (void*)&task
))
355 switch (task
->build(task
, message
))
358 /* task completed, remove it */
359 iterator
->remove(iterator
);
363 /* processed, but task needs another exchange */
367 /* critical failure, destroy IKE_SA */
368 iterator
->destroy(iterator
);
369 message
->destroy(message
);
374 iterator
->destroy(iterator
);
376 DESTROY_IF(this->initiating
.packet
);
377 status
= this->ike_sa
->generate_message(this->ike_sa
, message
,
378 &this->initiating
.packet
);
379 message
->destroy(message
);
380 if (status
!= SUCCESS
)
382 /* message generation failed. There is nothing more to do than to
388 return retransmit(this, this->initiating
.mid
);
392 * handle an incoming response message
394 static status_t
process_response(private_task_manager_t
*this,
397 iterator_t
*iterator
;
400 if (message
->get_exchange_type(message
) != this->initiating
.type
)
402 DBG1(DBG_IKE
, "received %N response, but expected %N",
403 exchange_type_names
, message
->get_exchange_type(message
),
404 exchange_type_names
, this->initiating
.type
);
408 iterator
= this->active_tasks
->create_iterator(this->active_tasks
, TRUE
);
409 while (iterator
->iterate(iterator
, (void*)&task
))
411 switch (task
->process(task
, message
))
414 /* task completed, remove it */
415 iterator
->remove(iterator
);
419 /* processed, but task needs another exchange */
423 /* critical failure, destroy IKE_SA */
424 iterator
->destroy(iterator
);
428 iterator
->destroy(iterator
);
430 this->initiating
.mid
++;
431 this->initiating
.type
= EXCHANGE_TYPE_UNDEFINED
;
433 return build_request(this);
437 * handle exchange collisions
439 static void handle_collisions(private_task_manager_t
*this, task_t
*task
)
441 iterator_t
*iterator
;
445 type
= task
->get_type(task
);
447 /* do we have to check */
448 if (type
== IKE_REKEY
|| type
== CHILD_REKEY
||
449 type
== CHILD_DELETE
|| type
== IKE_DELETE
)
451 /* find an exchange collision, and notify these tasks */
452 iterator
= this->active_tasks
->create_iterator(this->active_tasks
, TRUE
);
453 while (iterator
->iterate(iterator
, (void**)&active
))
455 switch (active
->get_type(active
))
458 if (type
== IKE_REKEY
|| type
== IKE_DELETE
)
460 ike_rekey_t
*rekey
= (ike_rekey_t
*)active
;
461 rekey
->collide(rekey
, task
);
466 if (type
== CHILD_REKEY
|| type
== CHILD_DELETE
)
468 child_rekey_t
*rekey
= (child_rekey_t
*)active
;
469 rekey
->collide(rekey
, task
);
476 iterator
->destroy(iterator
);
479 iterator
->destroy(iterator
);
481 /* destroy task if not registered in any active task */
486 * build a response depending on the "passive" task list
488 static status_t
build_response(private_task_manager_t
*this,
489 exchange_type_t exchange
)
491 iterator_t
*iterator
;
497 message
= message_create();
498 message
->set_exchange_type(message
, exchange
);
499 message
->set_message_id(message
, this->responding
.mid
);
500 message
->set_request(message
, FALSE
);
502 iterator
= this->passive_tasks
->create_iterator(this->passive_tasks
, TRUE
);
503 while (iterator
->iterate(iterator
, (void*)&task
))
505 switch (task
->build(task
, message
))
508 /* task completed, remove it */
509 iterator
->remove(iterator
);
510 handle_collisions(this, task
);
512 /* processed, but task needs another exchange */
516 /* destroy IKE_SA, but SEND response first */
525 iterator
->destroy(iterator
);
527 /* remove resonder SPI if IKE_SA_INIT failed */
528 if (delete && exchange
== IKE_SA_INIT
)
530 ike_sa_id_t
*id
= this->ike_sa
->get_id(this->ike_sa
);
531 id
->set_responder_spi(id
, 0);
534 /* message complete, send it */
535 DESTROY_IF(this->responding
.packet
);
536 status
= this->ike_sa
->generate_message(this->ike_sa
, message
,
537 &this->responding
.packet
);
538 message
->destroy(message
);
539 if (status
!= SUCCESS
)
544 charon
->sender
->send(charon
->sender
,
545 this->responding
.packet
->clone(this->responding
.packet
));
554 * handle an incoming request message
556 static status_t
process_request(private_task_manager_t
*this,
559 iterator_t
*iterator
;
561 exchange_type_t exchange
;
563 notify_payload_t
*notify
;
565 exchange
= message
->get_exchange_type(message
);
567 /* create tasks depending on request type */
572 task
= (task_t
*)ike_init_create(this->ike_sa
, FALSE
, NULL
);
573 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
574 task
= (task_t
*)ike_natd_create(this->ike_sa
, FALSE
);
575 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
576 task
= (task_t
*)ike_cert_create(this->ike_sa
, FALSE
);
577 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
578 task
= (task_t
*)ike_auth_create(this->ike_sa
, FALSE
);
579 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
580 task
= (task_t
*)ike_config_create(this->ike_sa
, FALSE
);
581 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
582 task
= (task_t
*)child_create_create(this->ike_sa
, NULL
);
583 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
586 case CREATE_CHILD_SA
:
588 bool notify_found
= FALSE
, ts_found
= FALSE
;
589 iterator
= message
->get_payload_iterator(message
);
590 while (iterator
->iterate(iterator
, (void**)&payload
))
592 switch (payload
->get_type(payload
))
596 /* if we find a rekey notify, its CHILD_SA rekeying */
597 notify
= (notify_payload_t
*)payload
;
598 if (notify
->get_notify_type(notify
) == REKEY_SA
&&
599 (notify
->get_protocol_id(notify
) == PROTO_AH
||
600 notify
->get_protocol_id(notify
) == PROTO_ESP
))
606 case TRAFFIC_SELECTOR_INITIATOR
:
607 case TRAFFIC_SELECTOR_RESPONDER
:
609 /* if we don't find a TS, its IKE rekeying */
617 iterator
->destroy(iterator
);
623 task
= (task_t
*)child_rekey_create(this->ike_sa
, NULL
);
627 task
= (task_t
*)child_create_create(this->ike_sa
, NULL
);
632 task
= (task_t
*)ike_rekey_create(this->ike_sa
, FALSE
);
634 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
639 delete_payload_t
*delete;
641 delete = (delete_payload_t
*)message
->get_payload(message
, DELETE
);
644 if (delete->get_protocol_id(delete) == PROTO_IKE
)
646 task
= (task_t
*)ike_delete_create(this->ike_sa
, FALSE
);
647 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
651 task
= (task_t
*)child_delete_create(this->ike_sa
, NULL
);
652 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
657 task
= (task_t
*)ike_dpd_create(FALSE
);
658 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
666 /* let the tasks process the message */
667 iterator
= this->passive_tasks
->create_iterator(this->passive_tasks
, TRUE
);
668 while (iterator
->iterate(iterator
, (void*)&task
))
670 switch (task
->process(task
, message
))
673 /* task completed, remove it */
674 iterator
->remove(iterator
);
678 /* processed, but task needs at least another call to build() */
682 /* critical failure, destroy IKE_SA */
683 iterator
->destroy(iterator
);
687 iterator
->destroy(iterator
);
689 return build_response(this, exchange
);
693 * Implementation of task_manager_t.process_message
695 static status_t
process_message(private_task_manager_t
*this, message_t
*msg
)
697 u_int32_t mid
= msg
->get_message_id(msg
);
699 if (msg
->get_request(msg
))
701 if (mid
== this->responding
.mid
)
703 if (process_request(this, msg
) != SUCCESS
)
708 this->responding
.mid
++;
710 else if ((mid
== this->responding
.mid
- 1) && this->responding
.packet
)
712 DBG1(DBG_IKE
, "received retransmit of request with ID %d, "
713 "retransmitting response", mid
);
714 charon
->sender
->send(charon
->sender
,
715 this->responding
.packet
->clone(this->responding
.packet
));
719 DBG1(DBG_IKE
, "received message ID %d, excepted %d. Ignored",
720 mid
, this->responding
.mid
);
725 if (mid
== this->initiating
.mid
)
727 if (process_response(this, msg
) != SUCCESS
)
735 DBG1(DBG_IKE
, "received message ID %d, excepted %d. Ignored",
736 mid
, this->initiating
.mid
);
744 * Implementation of task_manager_t.queue_task
746 static void queue_task(private_task_manager_t
*this, task_t
*task
)
748 DBG2(DBG_IKE
, "queueing %N task", task_type_names
, task
->get_type(task
));
749 this->queued_tasks
->insert_last(this->queued_tasks
, task
);
753 * Implementation of task_manager_t.adopt_tasks
755 static void adopt_tasks(private_task_manager_t
*this, private_task_manager_t
*other
)
759 /* move queued tasks from other to this */
760 while (other
->queued_tasks
->remove_last(other
->queued_tasks
,
761 (void**)&task
) == SUCCESS
)
763 DBG2(DBG_IKE
, "migrating %N task", task_type_names
, task
->get_type(task
));
764 task
->migrate(task
, this->ike_sa
);
765 this->queued_tasks
->insert_first(this->queued_tasks
, task
);
768 /* reset active tasks and move them to others queued tasks */
769 while (other
->active_tasks
->remove_last(other
->active_tasks
,
770 (void**)&task
) == SUCCESS
)
772 DBG2(DBG_IKE
, "migrating %N task", task_type_names
, task
->get_type(task
));
773 task
->migrate(task
, this->ike_sa
);
774 this->queued_tasks
->insert_first(this->queued_tasks
, task
);
779 * Implementation of task_manager_t.busy
781 static bool busy(private_task_manager_t
*this)
783 return (this->active_tasks
->get_count(this->active_tasks
) > 0);
787 * Implementation of task_manager_t.reset
789 static void reset(private_task_manager_t
*this)
793 /* reset message counters and retransmit packets */
794 DESTROY_IF(this->responding
.packet
);
795 DESTROY_IF(this->initiating
.packet
);
796 this->responding
.packet
= NULL
;
797 this->initiating
.packet
= NULL
;
798 this->responding
.mid
= 0;
799 this->initiating
.mid
= -1;
800 this->initiating
.type
= EXCHANGE_TYPE_UNDEFINED
;
802 /* reset active tasks */
803 while (this->active_tasks
->remove_last(this->active_tasks
,
804 (void**)&task
) == SUCCESS
)
806 task
->migrate(task
, this->ike_sa
);
807 this->queued_tasks
->insert_first(this->queued_tasks
, task
);
812 * Implementation of task_manager_t.destroy
814 static void destroy(private_task_manager_t
*this)
818 this->active_tasks
->destroy(this->active_tasks
);
819 this->queued_tasks
->destroy(this->queued_tasks
);
820 this->passive_tasks
->destroy(this->passive_tasks
);
822 DESTROY_IF(this->responding
.packet
);
823 DESTROY_IF(this->initiating
.packet
);
830 task_manager_t
*task_manager_create(ike_sa_t
*ike_sa
)
832 private_task_manager_t
*this = malloc_thing(private_task_manager_t
);
834 this->public.process_message
= (status_t(*)(task_manager_t
*,message_t
*))process_message
;
835 this->public.queue_task
= (void(*)(task_manager_t
*,task_t
*))queue_task
;
836 this->public.initiate
= (status_t(*)(task_manager_t
*))build_request
;
837 this->public.retransmit
= (status_t(*)(task_manager_t
*,u_int32_t
))retransmit
;
838 this->public.reset
= (void(*)(task_manager_t
*))reset
;
839 this->public.adopt_tasks
= (void(*)(task_manager_t
*,task_manager_t
*))adopt_tasks
;
840 this->public.busy
= (bool(*)(task_manager_t
*))busy
;
841 this->public.destroy
= (void(*)(task_manager_t
*))destroy
;
843 this->ike_sa
= ike_sa
;
844 this->responding
.packet
= NULL
;
845 this->initiating
.packet
= NULL
;
846 this->responding
.mid
= 0;
847 this->initiating
.mid
= 0;
848 this->initiating
.type
= EXCHANGE_TYPE_UNDEFINED
;
849 this->queued_tasks
= linked_list_create();
850 this->active_tasks
= linked_list_create();
851 this->passive_tasks
= linked_list_create();
853 return &this->public;