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 <queues/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
;
133 * ike_sa_init message we sent, stored here for later authentication
135 packet_t
*ike_sa_init
;
139 * move a task of a specific type from the queue to the active list
141 static bool activate_task(private_task_manager_t
*this, task_type_t type
)
143 iterator_t
*iterator
;
147 iterator
= this->queued_tasks
->create_iterator(this->queued_tasks
, TRUE
);
148 while (iterator
->iterate(iterator
, (void**)&task
))
150 if (task
->get_type(task
) == type
)
152 DBG2(DBG_IKE
, " activating %N task", task_type_names
, type
);
153 iterator
->remove(iterator
);
154 this->active_tasks
->insert_last(this->active_tasks
, task
);
159 iterator
->destroy(iterator
);
164 * Implementation of task_manager_t.retransmit
166 static status_t
retransmit(private_task_manager_t
*this, u_int32_t message_id
)
168 if (message_id
== this->initiating
.mid
)
173 timeout
= charon
->configuration
->get_retransmit_timeout(
174 charon
->configuration
, this->initiating
.retransmitted
);
177 DBG1(DBG_IKE
, "giving up after %d retransmits",
178 this->initiating
.retransmitted
- 1);
182 if (this->initiating
.retransmitted
)
184 DBG1(DBG_IKE
, "retransmit %d of request with message ID %d",
185 this->initiating
.retransmitted
, message_id
);
187 this->initiating
.retransmitted
++;
189 charon
->send_queue
->add(charon
->send_queue
,
190 this->initiating
.packet
->clone(this->initiating
.packet
));
191 job
= (job_t
*)retransmit_job_create(this->initiating
.mid
,
192 this->ike_sa
->get_id(this->ike_sa
));
193 charon
->event_queue
->add_relative(charon
->event_queue
, job
, timeout
);
199 * build a request using the active task list
200 * Implementation of task_manager_t.initiate
202 static status_t
build_request(private_task_manager_t
*this)
204 iterator_t
*iterator
;
208 exchange_type_t exchange
= 0;
210 if (this->active_tasks
->get_count(this->active_tasks
) == 0)
212 DBG2(DBG_IKE
, "activating new tasks");
213 switch (this->ike_sa
->get_state(this->ike_sa
))
216 if (activate_task(this, IKE_INIT
))
218 exchange
= IKE_SA_INIT
;
219 activate_task(this, IKE_NATD
);
220 activate_task(this, IKE_CERT
);
221 activate_task(this, IKE_AUTHENTICATE
);
222 activate_task(this, IKE_CONFIG
);
223 activate_task(this, CHILD_CREATE
);
226 case IKE_ESTABLISHED
:
227 if (activate_task(this, CHILD_CREATE
))
229 exchange
= CREATE_CHILD_SA
;
230 activate_task(this, IKE_CONFIG
);
233 if (activate_task(this, CHILD_DELETE
))
235 exchange
= INFORMATIONAL
;
238 if (activate_task(this, CHILD_REKEY
))
240 exchange
= CREATE_CHILD_SA
;
243 if (activate_task(this, IKE_DELETE
))
245 exchange
= INFORMATIONAL
;
248 if (activate_task(this, IKE_REKEY
))
250 exchange
= CREATE_CHILD_SA
;
253 if (activate_task(this, IKE_DEADPEER
))
255 exchange
= INFORMATIONAL
;
259 if (activate_task(this, IKE_DELETE
))
261 exchange
= INFORMATIONAL
;
271 DBG2(DBG_IKE
, "reinitiating already active tasks");
272 iterator
= this->active_tasks
->create_iterator(this->active_tasks
, TRUE
);
273 while (iterator
->iterate(iterator
, (void**)&task
))
275 DBG2(DBG_IKE
, " %N task", task_type_names
, task
->get_type(task
));
276 switch (task
->get_type(task
))
279 exchange
= IKE_SA_INIT
;
281 case IKE_AUTHENTICATE
:
289 iterator
->destroy(iterator
);
294 DBG2(DBG_IKE
, "nothing to initiate");
295 /* nothing to do yet... */
299 message
= message_create();
300 message
->set_message_id(message
, this->initiating
.mid
);
301 message
->set_exchange_type(message
, exchange
);
302 this->initiating
.type
= exchange
;
303 this->initiating
.retransmitted
= 0;
305 iterator
= this->active_tasks
->create_iterator(this->active_tasks
, TRUE
);
306 while (iterator
->iterate(iterator
, (void*)&task
))
308 switch (task
->build(task
, message
))
311 /* task completed, remove it */
312 iterator
->remove(iterator
);
316 /* processed, but task needs another exchange */
320 /* critical failure, destroy IKE_SA */
321 iterator
->destroy(iterator
);
322 message
->destroy(message
);
326 iterator
->destroy(iterator
);
328 DESTROY_IF(this->initiating
.packet
);
329 status
= this->ike_sa
->generate_message(this->ike_sa
, message
,
330 &this->initiating
.packet
);
331 message
->destroy(message
);
332 if (status
!= SUCCESS
)
334 /* message generation failed. There is nothing more to do than to
339 return retransmit(this, this->initiating
.mid
);
343 * handle an incoming response message
345 static status_t
process_response(private_task_manager_t
*this,
348 iterator_t
*iterator
;
351 if (message
->get_exchange_type(message
) != this->initiating
.type
)
353 DBG1(DBG_IKE
, "received %N response, but expected %N",
354 exchange_type_names
, message
->get_exchange_type(message
),
355 exchange_type_names
, this->initiating
.type
);
359 iterator
= this->active_tasks
->create_iterator(this->active_tasks
, TRUE
);
360 while (iterator
->iterate(iterator
, (void*)&task
))
362 switch (task
->process(task
, message
))
365 /* task completed, remove it */
366 iterator
->remove(iterator
);
370 /* processed, but task needs another exchange */
374 /* critical failure, destroy IKE_SA */
375 iterator
->destroy(iterator
);
379 iterator
->destroy(iterator
);
381 this->initiating
.mid
++;
383 return build_request(this);
387 * build a response depending on the "passive" task list
389 static status_t
build_response(private_task_manager_t
*this,
390 exchange_type_t exchange
)
392 iterator_t
*iterator
;
398 message
= message_create();
399 message
->set_exchange_type(message
, exchange
);
400 message
->set_message_id(message
, this->responding
.mid
);
401 message
->set_request(message
, FALSE
);
403 iterator
= this->passive_tasks
->create_iterator(this->passive_tasks
, TRUE
);
404 while (iterator
->iterate(iterator
, (void*)&task
))
406 switch (task
->build(task
, message
))
409 /* task completed, remove it */
410 iterator
->remove(iterator
);
414 /* processed, but task needs another exchange */
418 /* destroy IKE_SA, but SEND response first */
427 iterator
->destroy(iterator
);
429 /* remove resonder SPI if IKE_SA_INIT failed */
430 if (delete && exchange
== IKE_SA_INIT
)
432 ike_sa_id_t
*id
= this->ike_sa
->get_id(this->ike_sa
);
433 id
->set_responder_spi(id
, 0);
436 /* message complete, send it */
437 DESTROY_IF(this->responding
.packet
);
438 status
= this->ike_sa
->generate_message(this->ike_sa
, message
,
439 &this->responding
.packet
);
440 message
->destroy(message
);
441 if (status
!= SUCCESS
)
446 charon
->send_queue
->add(charon
->send_queue
,
447 this->responding
.packet
->clone(this->responding
.packet
));
456 * handle an incoming request message
458 static status_t
process_request(private_task_manager_t
*this,
461 iterator_t
*iterator
;
463 exchange_type_t exchange
;
465 notify_payload_t
*notify
;
467 exchange
= message
->get_exchange_type(message
);
469 /* create tasks depending on request type */
474 task
= (task_t
*)ike_init_create(this->ike_sa
, FALSE
, NULL
);
475 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
476 task
= (task_t
*)ike_natd_create(this->ike_sa
, FALSE
);
477 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
478 task
= (task_t
*)ike_cert_create(this->ike_sa
, FALSE
);
479 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
480 task
= (task_t
*)ike_config_create(this->ike_sa
, NULL
);
481 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
482 task
= (task_t
*)ike_auth_create(this->ike_sa
, FALSE
);
483 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
484 task
= (task_t
*)child_create_create(this->ike_sa
, NULL
);
485 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
488 case CREATE_CHILD_SA
:
490 bool notify_found
= FALSE
, ts_found
= FALSE
;
491 iterator
= message
->get_payload_iterator(message
);
492 while (iterator
->iterate(iterator
, (void**)&payload
))
494 switch (payload
->get_type(payload
))
498 /* if we find a rekey notify, its CHILD_SA rekeying */
499 notify
= (notify_payload_t
*)payload
;
500 if (notify
->get_notify_type(notify
) == REKEY_SA
&&
501 (notify
->get_protocol_id(notify
) == PROTO_AH
||
502 notify
->get_protocol_id(notify
) == PROTO_ESP
))
508 case TRAFFIC_SELECTOR_INITIATOR
:
509 case TRAFFIC_SELECTOR_RESPONDER
:
511 /* if we don't find a TS, its IKE rekeying */
519 iterator
->destroy(iterator
);
525 task
= (task_t
*)child_rekey_create(this->ike_sa
, NULL
);
529 task
= (task_t
*)child_create_create(this->ike_sa
, NULL
);
534 task
= (task_t
*)ike_rekey_create(this->ike_sa
, FALSE
);
536 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
542 delete_payload_t
*delete;
544 delete = (delete_payload_t
*)message
->get_payload(message
, DELETE
);
547 if (delete->get_protocol_id(delete) == PROTO_IKE
)
549 task
= (task_t
*)ike_delete_create(this->ike_sa
, FALSE
);
550 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
554 task
= (task_t
*)child_delete_create(this->ike_sa
, NULL
);
555 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
560 task
= (task_t
*)ike_dpd_create(FALSE
);
561 this->passive_tasks
->insert_last(this->passive_tasks
, task
);
569 /* let the tasks process the message */
570 iterator
= this->passive_tasks
->create_iterator(this->passive_tasks
, TRUE
);
571 while (iterator
->iterate(iterator
, (void*)&task
))
573 switch (task
->process(task
, message
))
576 /* task completed, remove it */
577 iterator
->remove(iterator
);
581 /* processed, but task needs at least another call to build() */
585 /* critical failure, destroy IKE_SA */
586 iterator
->destroy(iterator
);
590 iterator
->destroy(iterator
);
592 return build_response(this, exchange
);
596 * Implementation of task_manager_t.process_message
598 static status_t
process_message(private_task_manager_t
*this, message_t
*msg
)
600 u_int32_t mid
= msg
->get_message_id(msg
);
602 if (msg
->get_request(msg
))
604 if (mid
== this->responding
.mid
)
606 if (process_request(this, msg
) != SUCCESS
)
610 this->responding
.mid
++;
612 else if ((mid
== this->responding
.mid
- 1) && this->responding
.packet
)
614 DBG1(DBG_IKE
, "received retransmit of request with ID %d, "
615 "retransmitting response", mid
);
616 charon
->send_queue
->add(charon
->send_queue
,
617 this->responding
.packet
->clone(
618 this->responding
.packet
));
622 DBG1(DBG_IKE
, "received message ID %d, excepted %d. Ignored",
623 mid
, this->responding
.mid
);
628 if (mid
== this->initiating
.mid
)
630 if (process_response(this, msg
) != SUCCESS
)
637 DBG1(DBG_IKE
, "received message ID %d, excepted %d. Ignored",
638 mid
, this->initiating
.mid
);
646 * Implementation of task_manager_t.queue_task
648 static void queue_task(private_task_manager_t
*this, task_t
*task
)
650 DBG2(DBG_IKE
, "queueing %N task", task_type_names
, task
->get_type(task
));
651 this->queued_tasks
->insert_last(this->queued_tasks
, task
);
655 * Implementation of task_manager_t.adopt_tasks
657 static void adopt_tasks(private_task_manager_t
*this, private_task_manager_t
*other
)
661 /* move queued tasks from other to this */
662 while (other
->queued_tasks
->remove_last(other
->queued_tasks
,
663 (void**)&task
) == SUCCESS
)
665 task
->migrate(task
, this->ike_sa
);
666 this->queued_tasks
->insert_first(this->queued_tasks
, task
);
669 /* reset active tasks and move them to others queued tasks */
670 while (other
->active_tasks
->remove_last(other
->active_tasks
,
671 (void**)&task
) == SUCCESS
)
673 task
->migrate(task
, this->ike_sa
);
674 this->queued_tasks
->insert_first(this->queued_tasks
, task
);
679 * Implementation of task_manager_t.busy
681 static bool busy(private_task_manager_t
*this)
683 return (this->active_tasks
->get_count(this->active_tasks
) > 0);
687 * Implementation of task_manager_t.reset
689 static void reset(private_task_manager_t
*this)
693 /* reset message counters and retransmit packets */
694 DESTROY_IF(this->responding
.packet
);
695 DESTROY_IF(this->initiating
.packet
);
696 DESTROY_IF(this->ike_sa_init
);
697 this->responding
.packet
= NULL
;
698 this->initiating
.packet
= NULL
;
699 this->ike_sa_init
= NULL
;
700 this->responding
.mid
= 0;
701 this->initiating
.mid
= -1;
703 /* reset active tasks */
704 while (this->active_tasks
->remove_last(this->active_tasks
,
705 (void**)&task
) == SUCCESS
)
707 task
->migrate(task
, this->ike_sa
);
708 this->queued_tasks
->insert_first(this->queued_tasks
, task
);
713 * Implementation of task_manager_t.destroy
715 static void destroy(private_task_manager_t
*this)
719 this->queued_tasks
->destroy_offset(this->queued_tasks
,
720 offsetof(task_t
, destroy
));
721 this->passive_tasks
->destroy_offset(this->passive_tasks
,
722 offsetof(task_t
, destroy
));
724 /* emmit outstanding signals for tasks */
725 while (this->active_tasks
->remove_last(this->active_tasks
,
726 (void**)&task
) == SUCCESS
)
728 switch (task
->get_type(task
))
731 SIG(IKE_UP_FAILED
, "establishing IKE_SA failed");
734 SIG(IKE_DOWN_FAILED
, "deleting IKE_SA properly failed");
737 SIG(IKE_REKEY_FAILED
, "rekeying IKE_SA failed");
740 SIG(CHILD_UP_FAILED
, "establishing CHILD_SA failed");
743 SIG(CHILD_DOWN_FAILED
, "deleting CHILD_SA failed");
746 SIG(IKE_REKEY_FAILED
, "rekeying CHILD_SA failed");
753 this->active_tasks
->destroy(this->active_tasks
);
754 DESTROY_IF(this->responding
.packet
);
755 DESTROY_IF(this->initiating
.packet
);
756 DESTROY_IF(this->ike_sa_init
);
763 task_manager_t
*task_manager_create(ike_sa_t
*ike_sa
)
765 private_task_manager_t
*this = malloc_thing(private_task_manager_t
);
767 this->public.process_message
= (status_t(*)(task_manager_t
*,message_t
*))process_message
;
768 this->public.queue_task
= (void(*)(task_manager_t
*,task_t
*))queue_task
;
769 this->public.initiate
= (status_t(*)(task_manager_t
*))build_request
;
770 this->public.retransmit
= (status_t(*)(task_manager_t
*,u_int32_t
))retransmit
;
771 this->public.reset
= (void(*)(task_manager_t
*))reset
;
772 this->public.adopt_tasks
= (void(*)(task_manager_t
*,task_manager_t
*))adopt_tasks
;
773 this->public.busy
= (bool(*)(task_manager_t
*))busy
;
774 this->public.destroy
= (void(*)(task_manager_t
*))destroy
;
776 this->ike_sa
= ike_sa
;
777 this->responding
.packet
= NULL
;
778 this->initiating
.packet
= NULL
;
779 this->responding
.mid
= 0;
780 this->initiating
.mid
= 0;
781 this->queued_tasks
= linked_list_create();
782 this->active_tasks
= linked_list_create();
783 this->passive_tasks
= linked_list_create();
784 this->ike_sa_init
= NULL
;
786 return &this->public;