fixed keyingtries
[strongswan.git] / src / charon / sa / task_manager.c
1 /**
2 * @file task_manager.c
3 *
4 * @brief Implementation of task_manager_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2007 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
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>.
16 *
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
20 * for more details.
21 */
22
23 #include "task_manager.h"
24
25 #include <math.h>
26
27 #include <daemon.h>
28 #include <sa/tasks/ike_init.h>
29 #include <sa/tasks/ike_natd.h>
30 #include <sa/tasks/ike_auth.h>
31 #include <sa/tasks/ike_cert.h>
32 #include <sa/tasks/ike_rekey.h>
33 #include <sa/tasks/ike_delete.h>
34 #include <sa/tasks/ike_config.h>
35 #include <sa/tasks/ike_dpd.h>
36 #include <sa/tasks/child_create.h>
37 #include <sa/tasks/child_rekey.h>
38 #include <sa/tasks/child_delete.h>
39 #include <encoding/payloads/delete_payload.h>
40 #include <processing/jobs/retransmit_job.h>
41
42 typedef struct exchange_t exchange_t;
43
44 /**
45 * An exchange in the air, used do detect and handle retransmission
46 */
47 struct exchange_t {
48
49 /**
50 * Message ID used for this transaction
51 */
52 u_int32_t mid;
53
54 /**
55 * generated packet for retransmission
56 */
57 packet_t *packet;
58 };
59
60 typedef struct private_task_manager_t private_task_manager_t;
61
62 /**
63 * private data of the task manager
64 */
65 struct private_task_manager_t {
66
67 /**
68 * public functions
69 */
70 task_manager_t public;
71
72 /**
73 * associated IKE_SA we are serving
74 */
75 ike_sa_t *ike_sa;
76
77 /**
78 * Exchange we are currently handling as responder
79 */
80 struct {
81 /**
82 * Message ID of the exchange
83 */
84 u_int32_t mid;
85
86 /**
87 * packet for retransmission
88 */
89 packet_t *packet;
90
91 } responding;
92
93 /**
94 * Exchange we are currently handling as initiator
95 */
96 struct {
97 /**
98 * Message ID of the exchange
99 */
100 u_int32_t mid;
101
102 /**
103 * how many times we have retransmitted so far
104 */
105 u_int retransmitted;
106
107 /**
108 * packet for retransmission
109 */
110 packet_t *packet;
111
112 /**
113 * type of the initated exchange
114 */
115 exchange_type_t type;
116
117 } initiating;
118
119 /**
120 * List of queued tasks not yet in action
121 */
122 linked_list_t *queued_tasks;
123
124 /**
125 * List of active tasks, initiated by ourselve
126 */
127 linked_list_t *active_tasks;
128
129 /**
130 * List of tasks initiated by peer
131 */
132 linked_list_t *passive_tasks;
133 };
134
135 /**
136 * flush all tasks in the task manager
137 */
138 static void flush(private_task_manager_t *this)
139 {
140 task_t *task;
141
142 this->queued_tasks->destroy_offset(this->queued_tasks,
143 offsetof(task_t, destroy));
144 this->passive_tasks->destroy_offset(this->passive_tasks,
145 offsetof(task_t, destroy));
146
147 /* emmit outstanding signals for tasks */
148 while (this->active_tasks->remove_last(this->active_tasks,
149 (void**)&task) == SUCCESS)
150 {
151 switch (task->get_type(task))
152 {
153 case IKE_AUTH:
154 SIG(IKE_UP_FAILED, "establishing IKE_SA failed");
155 break;
156 case IKE_DELETE:
157 SIG(IKE_DOWN_FAILED, "IKE_SA deleted");
158 break;
159 case IKE_REKEY:
160 SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed");
161 break;
162 case CHILD_CREATE:
163 SIG(CHILD_UP_FAILED, "establishing CHILD_SA failed");
164 break;
165 case CHILD_DELETE:
166 SIG(CHILD_DOWN_FAILED, "deleting CHILD_SA failed");
167 break;
168 case CHILD_REKEY:
169 SIG(IKE_REKEY_FAILED, "rekeying CHILD_SA failed");
170 break;
171 default:
172 break;
173 }
174 task->destroy(task);
175 }
176 this->queued_tasks = linked_list_create();
177 this->passive_tasks = linked_list_create();
178 }
179
180 /**
181 * move a task of a specific type from the queue to the active list
182 */
183 static bool activate_task(private_task_manager_t *this, task_type_t type)
184 {
185 iterator_t *iterator;
186 task_t *task;
187 bool found = FALSE;
188
189 iterator = this->queued_tasks->create_iterator(this->queued_tasks, TRUE);
190 while (iterator->iterate(iterator, (void**)&task))
191 {
192 if (task->get_type(task) == type)
193 {
194 DBG2(DBG_IKE, " activating %N task", task_type_names, type);
195 iterator->remove(iterator);
196 this->active_tasks->insert_last(this->active_tasks, task);
197 found = TRUE;
198 break;
199 }
200 }
201 iterator->destroy(iterator);
202 return found;
203 }
204
205 /**
206 * Implementation of task_manager_t.retransmit
207 */
208 static status_t retransmit(private_task_manager_t *this, u_int32_t message_id)
209 {
210 if (message_id == this->initiating.mid)
211 {
212 u_int32_t timeout;
213 job_t *job;
214
215 if (this->initiating.retransmitted <= RETRANSMIT_TRIES)
216 {
217 timeout = (u_int32_t)(RETRANSMIT_TIMEOUT *
218 pow(RETRANSMIT_BASE, this->initiating.retransmitted));
219 }
220 else
221 {
222 DBG1(DBG_IKE, "giving up after %d retransmits",
223 this->initiating.retransmitted - 1);
224 return DESTROY_ME;
225 }
226
227 if (this->initiating.retransmitted)
228 {
229 DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
230 this->initiating.retransmitted, message_id);
231 }
232 this->initiating.retransmitted++;
233
234 charon->sender->send(charon->sender,
235 this->initiating.packet->clone(this->initiating.packet));
236 job = (job_t*)retransmit_job_create(this->initiating.mid,
237 this->ike_sa->get_id(this->ike_sa));
238 charon->event_queue->add_relative(charon->event_queue, job, timeout);
239 }
240 return SUCCESS;
241 }
242
243 /**
244 * build a request using the active task list
245 * Implementation of task_manager_t.initiate
246 */
247 static status_t build_request(private_task_manager_t *this)
248 {
249 iterator_t *iterator;
250 task_t *task;
251 message_t *message;
252 status_t status;
253 exchange_type_t exchange = 0;
254
255 if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
256 {
257 DBG2(DBG_IKE, "delaying task initiation, exchange in progress");
258 /* do not initiate if we already have a message in the air */
259 return SUCCESS;
260 }
261
262 if (this->active_tasks->get_count(this->active_tasks) == 0)
263 {
264 DBG2(DBG_IKE, "activating new tasks");
265 switch (this->ike_sa->get_state(this->ike_sa))
266 {
267 case IKE_CREATED:
268 if (activate_task(this, IKE_INIT))
269 {
270 this->initiating.mid = 0;
271 exchange = IKE_SA_INIT;
272 activate_task(this, IKE_NATD);
273 activate_task(this, IKE_CERT);
274 activate_task(this, IKE_AUTHENTICATE);
275 activate_task(this, IKE_CONFIG);
276 activate_task(this, CHILD_CREATE);
277 }
278 break;
279 case IKE_ESTABLISHED:
280 if (activate_task(this, CHILD_CREATE))
281 {
282 exchange = CREATE_CHILD_SA;
283 break;
284 }
285 if (activate_task(this, CHILD_DELETE))
286 {
287 exchange = INFORMATIONAL;
288 break;
289 }
290 if (activate_task(this, CHILD_REKEY))
291 {
292 exchange = CREATE_CHILD_SA;
293 break;
294 }
295 if (activate_task(this, IKE_DELETE))
296 {
297 exchange = INFORMATIONAL;
298 break;
299 }
300 if (activate_task(this, IKE_REKEY))
301 {
302 exchange = CREATE_CHILD_SA;
303 break;
304 }
305 if (activate_task(this, IKE_DEADPEER))
306 {
307 exchange = INFORMATIONAL;
308 break;
309 }
310 case IKE_REKEYING:
311 if (activate_task(this, IKE_DELETE))
312 {
313 exchange = INFORMATIONAL;
314 break;
315 }
316 case IKE_DELETING:
317 default:
318 break;
319 }
320 }
321 else
322 {
323 DBG2(DBG_IKE, "reinitiating already active tasks");
324 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
325 while (iterator->iterate(iterator, (void**)&task))
326 {
327 DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
328 switch (task->get_type(task))
329 {
330 case IKE_INIT:
331 exchange = IKE_SA_INIT;
332 break;
333 case IKE_AUTHENTICATE:
334 exchange = IKE_AUTH;
335 break;
336 case CHILD_CREATE:
337 case CHILD_REKEY:
338 case IKE_REKEY:
339 exchange = CREATE_CHILD_SA;
340 break;
341 default:
342 continue;
343 }
344 break;
345 }
346 iterator->destroy(iterator);
347 }
348
349 if (exchange == 0)
350 {
351 DBG2(DBG_IKE, "nothing to initiate");
352 /* nothing to do yet... */
353 return SUCCESS;
354 }
355
356 message = message_create();
357 message->set_message_id(message, this->initiating.mid);
358 message->set_exchange_type(message, exchange);
359 this->initiating.type = exchange;
360 this->initiating.retransmitted = 0;
361
362 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
363 while (iterator->iterate(iterator, (void*)&task))
364 {
365 switch (task->build(task, message))
366 {
367 case SUCCESS:
368 /* task completed, remove it */
369 iterator->remove(iterator);
370 task->destroy(task);
371 break;
372 case NEED_MORE:
373 /* processed, but task needs another exchange */
374 break;
375 case FAILED:
376 default:
377 /* critical failure, destroy IKE_SA */
378 iterator->destroy(iterator);
379 message->destroy(message);
380 flush(this);
381 return DESTROY_ME;
382 }
383 }
384 iterator->destroy(iterator);
385
386 DESTROY_IF(this->initiating.packet);
387 status = this->ike_sa->generate_message(this->ike_sa, message,
388 &this->initiating.packet);
389 message->destroy(message);
390 if (status != SUCCESS)
391 {
392 /* message generation failed. There is nothing more to do than to
393 * close the SA */
394 flush(this);
395 return DESTROY_ME;
396 }
397
398 return retransmit(this, this->initiating.mid);
399 }
400
401 /**
402 * handle an incoming response message
403 */
404 static status_t process_response(private_task_manager_t *this,
405 message_t *message)
406 {
407 iterator_t *iterator;
408 task_t *task;
409
410 if (message->get_exchange_type(message) != this->initiating.type)
411 {
412 DBG1(DBG_IKE, "received %N response, but expected %N",
413 exchange_type_names, message->get_exchange_type(message),
414 exchange_type_names, this->initiating.type);
415 return DESTROY_ME;
416 }
417
418 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
419 while (iterator->iterate(iterator, (void*)&task))
420 {
421 switch (task->process(task, message))
422 {
423 case SUCCESS:
424 /* task completed, remove it */
425 iterator->remove(iterator);
426 task->destroy(task);
427 break;
428 case NEED_MORE:
429 /* processed, but task needs another exchange */
430 break;
431 case FAILED:
432 default:
433 /* critical failure, destroy IKE_SA */
434 iterator->destroy(iterator);
435 return DESTROY_ME;
436 }
437 }
438 iterator->destroy(iterator);
439
440 this->initiating.mid++;
441 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
442
443 return build_request(this);
444 }
445
446 /**
447 * handle exchange collisions
448 */
449 static void handle_collisions(private_task_manager_t *this, task_t *task)
450 {
451 iterator_t *iterator;
452 task_t *active;
453 task_type_t type;
454
455 type = task->get_type(task);
456
457 /* do we have to check */
458 if (type == IKE_REKEY || type == CHILD_REKEY ||
459 type == CHILD_DELETE || type == IKE_DELETE)
460 {
461 /* find an exchange collision, and notify these tasks */
462 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
463 while (iterator->iterate(iterator, (void**)&active))
464 {
465 switch (active->get_type(active))
466 {
467 case IKE_REKEY:
468 if (type == IKE_REKEY || type == IKE_DELETE)
469 {
470 ike_rekey_t *rekey = (ike_rekey_t*)active;
471 rekey->collide(rekey, task);
472 break;
473 }
474 continue;
475 case CHILD_REKEY:
476 if (type == CHILD_REKEY || type == CHILD_DELETE)
477 {
478 child_rekey_t *rekey = (child_rekey_t*)active;
479 rekey->collide(rekey, task);
480 break;
481 }
482 continue;
483 default:
484 continue;
485 }
486 iterator->destroy(iterator);
487 return;
488 }
489 iterator->destroy(iterator);
490 }
491 /* destroy task if not registered in any active task */
492 task->destroy(task);
493 }
494
495 /**
496 * build a response depending on the "passive" task list
497 */
498 static status_t build_response(private_task_manager_t *this,
499 exchange_type_t exchange)
500 {
501 iterator_t *iterator;
502 task_t *task;
503 message_t *message;
504 bool delete = FALSE;
505 status_t status;
506
507 message = message_create();
508 message->set_exchange_type(message, exchange);
509 message->set_message_id(message, this->responding.mid);
510 message->set_request(message, FALSE);
511
512 iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
513 while (iterator->iterate(iterator, (void*)&task))
514 {
515 switch (task->build(task, message))
516 {
517 case SUCCESS:
518 /* task completed, remove it */
519 iterator->remove(iterator);
520 handle_collisions(this, task);
521 case NEED_MORE:
522 /* processed, but task needs another exchange */
523 break;
524 case FAILED:
525 default:
526 /* destroy IKE_SA, but SEND response first */
527 delete = TRUE;
528 break;
529 }
530 if (delete)
531 {
532 break;
533 }
534 }
535 iterator->destroy(iterator);
536
537 /* remove resonder SPI if IKE_SA_INIT failed */
538 if (delete && exchange == IKE_SA_INIT)
539 {
540 ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa);
541 id->set_responder_spi(id, 0);
542 }
543
544 /* message complete, send it */
545 DESTROY_IF(this->responding.packet);
546 status = this->ike_sa->generate_message(this->ike_sa, message,
547 &this->responding.packet);
548 message->destroy(message);
549 if (status != SUCCESS)
550 {
551 return DESTROY_ME;
552 }
553
554 charon->sender->send(charon->sender,
555 this->responding.packet->clone(this->responding.packet));
556 if (delete)
557 {
558 return DESTROY_ME;
559 }
560 return SUCCESS;
561 }
562
563 /**
564 * handle an incoming request message
565 */
566 static status_t process_request(private_task_manager_t *this,
567 message_t *message)
568 {
569 iterator_t *iterator;
570 task_t *task = NULL;
571 exchange_type_t exchange;
572 payload_t *payload;
573 notify_payload_t *notify;
574
575 exchange = message->get_exchange_type(message);
576
577 /* create tasks depending on request type */
578 switch (exchange)
579 {
580 case IKE_SA_INIT:
581 {
582 task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
583 this->passive_tasks->insert_last(this->passive_tasks, task);
584 task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
585 this->passive_tasks->insert_last(this->passive_tasks, task);
586 task = (task_t*)ike_cert_create(this->ike_sa, FALSE);
587 this->passive_tasks->insert_last(this->passive_tasks, task);
588 task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
589 this->passive_tasks->insert_last(this->passive_tasks, task);
590 task = (task_t*)ike_config_create(this->ike_sa, FALSE);
591 this->passive_tasks->insert_last(this->passive_tasks, task);
592 task = (task_t*)child_create_create(this->ike_sa, NULL);
593 this->passive_tasks->insert_last(this->passive_tasks, task);
594 break;
595 }
596 case CREATE_CHILD_SA:
597 {
598 bool notify_found = FALSE, ts_found = FALSE;
599 iterator = message->get_payload_iterator(message);
600 while (iterator->iterate(iterator, (void**)&payload))
601 {
602 switch (payload->get_type(payload))
603 {
604 case NOTIFY:
605 {
606 /* if we find a rekey notify, its CHILD_SA rekeying */
607 notify = (notify_payload_t*)payload;
608 if (notify->get_notify_type(notify) == REKEY_SA &&
609 (notify->get_protocol_id(notify) == PROTO_AH ||
610 notify->get_protocol_id(notify) == PROTO_ESP))
611 {
612 notify_found = TRUE;
613 }
614 break;
615 }
616 case TRAFFIC_SELECTOR_INITIATOR:
617 case TRAFFIC_SELECTOR_RESPONDER:
618 {
619 /* if we don't find a TS, its IKE rekeying */
620 ts_found = TRUE;
621 break;
622 }
623 default:
624 break;
625 }
626 }
627 iterator->destroy(iterator);
628
629 if (ts_found)
630 {
631 if (notify_found)
632 {
633 task = (task_t*)child_rekey_create(this->ike_sa, NULL);
634 }
635 else
636 {
637 task = (task_t*)child_create_create(this->ike_sa, NULL);
638 }
639 }
640 else
641 {
642 task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
643 }
644 this->passive_tasks->insert_last(this->passive_tasks, task);
645 break;
646 }
647 case INFORMATIONAL:
648 {
649 delete_payload_t *delete;
650
651 delete = (delete_payload_t*)message->get_payload(message, DELETE);
652 if (delete)
653 {
654 if (delete->get_protocol_id(delete) == PROTO_IKE)
655 {
656 task = (task_t*)ike_delete_create(this->ike_sa, FALSE);
657 this->passive_tasks->insert_last(this->passive_tasks, task);
658 }
659 else
660 {
661 task = (task_t*)child_delete_create(this->ike_sa, NULL);
662 this->passive_tasks->insert_last(this->passive_tasks, task);
663 }
664 }
665 else
666 {
667 task = (task_t*)ike_dpd_create(FALSE);
668 this->passive_tasks->insert_last(this->passive_tasks, task);
669 }
670 break;
671 }
672 default:
673 break;
674 }
675
676 /* let the tasks process the message */
677 iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
678 while (iterator->iterate(iterator, (void*)&task))
679 {
680 switch (task->process(task, message))
681 {
682 case SUCCESS:
683 /* task completed, remove it */
684 iterator->remove(iterator);
685 task->destroy(task);
686 break;
687 case NEED_MORE:
688 /* processed, but task needs at least another call to build() */
689 break;
690 case FAILED:
691 default:
692 /* critical failure, destroy IKE_SA */
693 iterator->destroy(iterator);
694 return DESTROY_ME;
695 }
696 }
697 iterator->destroy(iterator);
698
699 return build_response(this, exchange);
700 }
701
702 /**
703 * Implementation of task_manager_t.process_message
704 */
705 static status_t process_message(private_task_manager_t *this, message_t *msg)
706 {
707 u_int32_t mid = msg->get_message_id(msg);
708
709 if (msg->get_request(msg))
710 {
711 if (mid == this->responding.mid)
712 {
713 if (process_request(this, msg) != SUCCESS)
714 {
715 flush(this);
716 return DESTROY_ME;
717 }
718 this->responding.mid++;
719 }
720 else if ((mid == this->responding.mid - 1) && this->responding.packet)
721 {
722 DBG1(DBG_IKE, "received retransmit of request with ID %d, "
723 "retransmitting response", mid);
724 charon->sender->send(charon->sender,
725 this->responding.packet->clone(this->responding.packet));
726 }
727 else
728 {
729 DBG1(DBG_IKE, "received message ID %d, excepted %d. Ignored",
730 mid, this->responding.mid);
731 }
732 }
733 else
734 {
735 if (mid == this->initiating.mid)
736 {
737 if (process_response(this, msg) != SUCCESS)
738 {
739 flush(this);
740 return DESTROY_ME;
741 }
742 }
743 else
744 {
745 DBG1(DBG_IKE, "received message ID %d, excepted %d. Ignored",
746 mid, this->initiating.mid);
747 return SUCCESS;
748 }
749 }
750 return SUCCESS;
751 }
752
753 /**
754 * Implementation of task_manager_t.queue_task
755 */
756 static void queue_task(private_task_manager_t *this, task_t *task)
757 {
758 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
759 this->queued_tasks->insert_last(this->queued_tasks, task);
760 }
761
762 /**
763 * Implementation of task_manager_t.adopt_tasks
764 */
765 static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *other)
766 {
767 task_t *task;
768
769 /* move queued tasks from other to this */
770 while (other->queued_tasks->remove_last(other->queued_tasks,
771 (void**)&task) == SUCCESS)
772 {
773 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
774 task->migrate(task, this->ike_sa);
775 this->queued_tasks->insert_first(this->queued_tasks, task);
776 }
777
778 /* reset active tasks and move them to others queued tasks */
779 while (other->active_tasks->remove_last(other->active_tasks,
780 (void**)&task) == SUCCESS)
781 {
782 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
783 task->migrate(task, this->ike_sa);
784 this->queued_tasks->insert_first(this->queued_tasks, task);
785 }
786 }
787
788 /**
789 * Implementation of task_manager_t.busy
790 */
791 static bool busy(private_task_manager_t *this)
792 {
793 return (this->active_tasks->get_count(this->active_tasks) > 0);
794 }
795
796 /**
797 * Implementation of task_manager_t.reset
798 */
799 static void reset(private_task_manager_t *this)
800 {
801 task_t *task;
802
803 /* reset message counters and retransmit packets */
804 DESTROY_IF(this->responding.packet);
805 DESTROY_IF(this->initiating.packet);
806 this->responding.packet = NULL;
807 this->initiating.packet = NULL;
808 this->responding.mid = 0;
809 this->initiating.mid = -1;
810 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
811
812 /* reset active tasks */
813 while (this->active_tasks->remove_last(this->active_tasks,
814 (void**)&task) == SUCCESS)
815 {
816 task->migrate(task, this->ike_sa);
817 this->queued_tasks->insert_first(this->queued_tasks, task);
818 }
819 }
820
821 /**
822 * Implementation of task_manager_t.destroy
823 */
824 static void destroy(private_task_manager_t *this)
825 {
826 flush(this);
827
828 this->active_tasks->destroy(this->active_tasks);
829 this->queued_tasks->destroy(this->queued_tasks);
830 this->passive_tasks->destroy(this->passive_tasks);
831
832 DESTROY_IF(this->responding.packet);
833 DESTROY_IF(this->initiating.packet);
834 free(this);
835 }
836
837 /*
838 * see header file
839 */
840 task_manager_t *task_manager_create(ike_sa_t *ike_sa)
841 {
842 private_task_manager_t *this = malloc_thing(private_task_manager_t);
843
844 this->public.process_message = (status_t(*)(task_manager_t*,message_t*))process_message;
845 this->public.queue_task = (void(*)(task_manager_t*,task_t*))queue_task;
846 this->public.initiate = (status_t(*)(task_manager_t*))build_request;
847 this->public.retransmit = (status_t(*)(task_manager_t*,u_int32_t))retransmit;
848 this->public.reset = (void(*)(task_manager_t*))reset;
849 this->public.adopt_tasks = (void(*)(task_manager_t*,task_manager_t*))adopt_tasks;
850 this->public.busy = (bool(*)(task_manager_t*))busy;
851 this->public.destroy = (void(*)(task_manager_t*))destroy;
852
853 this->ike_sa = ike_sa;
854 this->responding.packet = NULL;
855 this->initiating.packet = NULL;
856 this->responding.mid = 0;
857 this->initiating.mid = 0;
858 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
859 this->queued_tasks = linked_list_create();
860 this->active_tasks = linked_list_create();
861 this->passive_tasks = linked_list_create();
862
863 return &this->public;
864 }