eb707c1f97b3c5dcd5ab6ff37305c1130e77ba89
[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 exchange = IKE_SA_INIT;
271 activate_task(this, IKE_NATD);
272 activate_task(this, IKE_CERT);
273 activate_task(this, IKE_AUTHENTICATE);
274 activate_task(this, IKE_CONFIG);
275 activate_task(this, CHILD_CREATE);
276 }
277 break;
278 case IKE_ESTABLISHED:
279 if (activate_task(this, CHILD_CREATE))
280 {
281 exchange = CREATE_CHILD_SA;
282 break;
283 }
284 if (activate_task(this, CHILD_DELETE))
285 {
286 exchange = INFORMATIONAL;
287 break;
288 }
289 if (activate_task(this, CHILD_REKEY))
290 {
291 exchange = CREATE_CHILD_SA;
292 break;
293 }
294 if (activate_task(this, IKE_DELETE))
295 {
296 exchange = INFORMATIONAL;
297 break;
298 }
299 if (activate_task(this, IKE_REKEY))
300 {
301 exchange = CREATE_CHILD_SA;
302 break;
303 }
304 if (activate_task(this, IKE_DEADPEER))
305 {
306 exchange = INFORMATIONAL;
307 break;
308 }
309 case IKE_REKEYING:
310 if (activate_task(this, IKE_DELETE))
311 {
312 exchange = INFORMATIONAL;
313 break;
314 }
315 case IKE_DELETING:
316 default:
317 break;
318 }
319 }
320 else
321 {
322 DBG2(DBG_IKE, "reinitiating already active tasks");
323 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
324 while (iterator->iterate(iterator, (void**)&task))
325 {
326 DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
327 switch (task->get_type(task))
328 {
329 case IKE_INIT:
330 exchange = IKE_SA_INIT;
331 break;
332 case IKE_AUTHENTICATE:
333 exchange = IKE_AUTH;
334 break;
335 case CHILD_CREATE:
336 case CHILD_REKEY:
337 case IKE_REKEY:
338 exchange = CREATE_CHILD_SA;
339 break;
340 default:
341 continue;
342 }
343 break;
344 }
345 iterator->destroy(iterator);
346 }
347
348 if (exchange == 0)
349 {
350 DBG2(DBG_IKE, "nothing to initiate");
351 /* nothing to do yet... */
352 return SUCCESS;
353 }
354
355 message = message_create();
356 message->set_message_id(message, this->initiating.mid);
357 message->set_exchange_type(message, exchange);
358 this->initiating.type = exchange;
359 this->initiating.retransmitted = 0;
360
361 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
362 while (iterator->iterate(iterator, (void*)&task))
363 {
364 switch (task->build(task, message))
365 {
366 case SUCCESS:
367 /* task completed, remove it */
368 iterator->remove(iterator);
369 task->destroy(task);
370 break;
371 case NEED_MORE:
372 /* processed, but task needs another exchange */
373 break;
374 case FAILED:
375 default:
376 /* critical failure, destroy IKE_SA */
377 iterator->destroy(iterator);
378 message->destroy(message);
379 flush(this);
380 return DESTROY_ME;
381 }
382 }
383 iterator->destroy(iterator);
384
385 DESTROY_IF(this->initiating.packet);
386 status = this->ike_sa->generate_message(this->ike_sa, message,
387 &this->initiating.packet);
388 message->destroy(message);
389 if (status != SUCCESS)
390 {
391 /* message generation failed. There is nothing more to do than to
392 * close the SA */
393 flush(this);
394 return DESTROY_ME;
395 }
396
397 return retransmit(this, this->initiating.mid);
398 }
399
400 /**
401 * handle an incoming response message
402 */
403 static status_t process_response(private_task_manager_t *this,
404 message_t *message)
405 {
406 iterator_t *iterator;
407 task_t *task;
408
409 if (message->get_exchange_type(message) != this->initiating.type)
410 {
411 DBG1(DBG_IKE, "received %N response, but expected %N",
412 exchange_type_names, message->get_exchange_type(message),
413 exchange_type_names, this->initiating.type);
414 return DESTROY_ME;
415 }
416
417 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
418 while (iterator->iterate(iterator, (void*)&task))
419 {
420 switch (task->process(task, message))
421 {
422 case SUCCESS:
423 /* task completed, remove it */
424 iterator->remove(iterator);
425 task->destroy(task);
426 break;
427 case NEED_MORE:
428 /* processed, but task needs another exchange */
429 break;
430 case FAILED:
431 default:
432 /* critical failure, destroy IKE_SA */
433 iterator->destroy(iterator);
434 return DESTROY_ME;
435 }
436 }
437 iterator->destroy(iterator);
438
439 this->initiating.mid++;
440 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
441
442 return build_request(this);
443 }
444
445 /**
446 * handle exchange collisions
447 */
448 static void handle_collisions(private_task_manager_t *this, task_t *task)
449 {
450 iterator_t *iterator;
451 task_t *active;
452 task_type_t type;
453
454 type = task->get_type(task);
455
456 /* do we have to check */
457 if (type == IKE_REKEY || type == CHILD_REKEY ||
458 type == CHILD_DELETE || type == IKE_DELETE)
459 {
460 /* find an exchange collision, and notify these tasks */
461 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
462 while (iterator->iterate(iterator, (void**)&active))
463 {
464 switch (active->get_type(active))
465 {
466 case IKE_REKEY:
467 if (type == IKE_REKEY || type == IKE_DELETE)
468 {
469 ike_rekey_t *rekey = (ike_rekey_t*)active;
470 rekey->collide(rekey, task);
471 break;
472 }
473 continue;
474 case CHILD_REKEY:
475 if (type == CHILD_REKEY || type == CHILD_DELETE)
476 {
477 child_rekey_t *rekey = (child_rekey_t*)active;
478 rekey->collide(rekey, task);
479 break;
480 }
481 continue;
482 default:
483 continue;
484 }
485 iterator->destroy(iterator);
486 return;
487 }
488 iterator->destroy(iterator);
489 }
490 /* destroy task if not registered in any active task */
491 task->destroy(task);
492 }
493
494 /**
495 * build a response depending on the "passive" task list
496 */
497 static status_t build_response(private_task_manager_t *this,
498 exchange_type_t exchange)
499 {
500 iterator_t *iterator;
501 task_t *task;
502 message_t *message;
503 bool delete = FALSE;
504 status_t status;
505
506 message = message_create();
507 message->set_exchange_type(message, exchange);
508 message->set_message_id(message, this->responding.mid);
509 message->set_request(message, FALSE);
510
511 iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
512 while (iterator->iterate(iterator, (void*)&task))
513 {
514 switch (task->build(task, message))
515 {
516 case SUCCESS:
517 /* task completed, remove it */
518 iterator->remove(iterator);
519 handle_collisions(this, task);
520 case NEED_MORE:
521 /* processed, but task needs another exchange */
522 break;
523 case FAILED:
524 default:
525 /* destroy IKE_SA, but SEND response first */
526 delete = TRUE;
527 break;
528 }
529 if (delete)
530 {
531 break;
532 }
533 }
534 iterator->destroy(iterator);
535
536 /* remove resonder SPI if IKE_SA_INIT failed */
537 if (delete && exchange == IKE_SA_INIT)
538 {
539 ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa);
540 id->set_responder_spi(id, 0);
541 }
542
543 /* message complete, send it */
544 DESTROY_IF(this->responding.packet);
545 status = this->ike_sa->generate_message(this->ike_sa, message,
546 &this->responding.packet);
547 message->destroy(message);
548 if (status != SUCCESS)
549 {
550 return DESTROY_ME;
551 }
552
553 charon->sender->send(charon->sender,
554 this->responding.packet->clone(this->responding.packet));
555 if (delete)
556 {
557 return DESTROY_ME;
558 }
559 return SUCCESS;
560 }
561
562 /**
563 * handle an incoming request message
564 */
565 static status_t process_request(private_task_manager_t *this,
566 message_t *message)
567 {
568 iterator_t *iterator;
569 task_t *task = NULL;
570 exchange_type_t exchange;
571 payload_t *payload;
572 notify_payload_t *notify;
573
574 exchange = message->get_exchange_type(message);
575
576 /* create tasks depending on request type */
577 switch (exchange)
578 {
579 case IKE_SA_INIT:
580 {
581 task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
582 this->passive_tasks->insert_last(this->passive_tasks, task);
583 task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
584 this->passive_tasks->insert_last(this->passive_tasks, task);
585 task = (task_t*)ike_cert_create(this->ike_sa, FALSE);
586 this->passive_tasks->insert_last(this->passive_tasks, task);
587 task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
588 this->passive_tasks->insert_last(this->passive_tasks, task);
589 task = (task_t*)ike_config_create(this->ike_sa, FALSE);
590 this->passive_tasks->insert_last(this->passive_tasks, task);
591 task = (task_t*)child_create_create(this->ike_sa, NULL);
592 this->passive_tasks->insert_last(this->passive_tasks, task);
593 break;
594 }
595 case CREATE_CHILD_SA:
596 {
597 bool notify_found = FALSE, ts_found = FALSE;
598 iterator = message->get_payload_iterator(message);
599 while (iterator->iterate(iterator, (void**)&payload))
600 {
601 switch (payload->get_type(payload))
602 {
603 case NOTIFY:
604 {
605 /* if we find a rekey notify, its CHILD_SA rekeying */
606 notify = (notify_payload_t*)payload;
607 if (notify->get_notify_type(notify) == REKEY_SA &&
608 (notify->get_protocol_id(notify) == PROTO_AH ||
609 notify->get_protocol_id(notify) == PROTO_ESP))
610 {
611 notify_found = TRUE;
612 }
613 break;
614 }
615 case TRAFFIC_SELECTOR_INITIATOR:
616 case TRAFFIC_SELECTOR_RESPONDER:
617 {
618 /* if we don't find a TS, its IKE rekeying */
619 ts_found = TRUE;
620 break;
621 }
622 default:
623 break;
624 }
625 }
626 iterator->destroy(iterator);
627
628 if (ts_found)
629 {
630 if (notify_found)
631 {
632 task = (task_t*)child_rekey_create(this->ike_sa, NULL);
633 }
634 else
635 {
636 task = (task_t*)child_create_create(this->ike_sa, NULL);
637 }
638 }
639 else
640 {
641 task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
642 }
643 this->passive_tasks->insert_last(this->passive_tasks, task);
644 break;
645 }
646 case INFORMATIONAL:
647 {
648 delete_payload_t *delete;
649
650 delete = (delete_payload_t*)message->get_payload(message, DELETE);
651 if (delete)
652 {
653 if (delete->get_protocol_id(delete) == PROTO_IKE)
654 {
655 task = (task_t*)ike_delete_create(this->ike_sa, FALSE);
656 this->passive_tasks->insert_last(this->passive_tasks, task);
657 }
658 else
659 {
660 task = (task_t*)child_delete_create(this->ike_sa, NULL);
661 this->passive_tasks->insert_last(this->passive_tasks, task);
662 }
663 }
664 else
665 {
666 task = (task_t*)ike_dpd_create(FALSE);
667 this->passive_tasks->insert_last(this->passive_tasks, task);
668 }
669 break;
670 }
671 default:
672 break;
673 }
674
675 /* let the tasks process the message */
676 iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
677 while (iterator->iterate(iterator, (void*)&task))
678 {
679 switch (task->process(task, message))
680 {
681 case SUCCESS:
682 /* task completed, remove it */
683 iterator->remove(iterator);
684 task->destroy(task);
685 break;
686 case NEED_MORE:
687 /* processed, but task needs at least another call to build() */
688 break;
689 case FAILED:
690 default:
691 /* critical failure, destroy IKE_SA */
692 iterator->destroy(iterator);
693 return DESTROY_ME;
694 }
695 }
696 iterator->destroy(iterator);
697
698 return build_response(this, exchange);
699 }
700
701 /**
702 * Implementation of task_manager_t.process_message
703 */
704 static status_t process_message(private_task_manager_t *this, message_t *msg)
705 {
706 u_int32_t mid = msg->get_message_id(msg);
707
708 if (msg->get_request(msg))
709 {
710 if (mid == this->responding.mid)
711 {
712 if (process_request(this, msg) != SUCCESS)
713 {
714 flush(this);
715 return DESTROY_ME;
716 }
717 this->responding.mid++;
718 }
719 else if ((mid == this->responding.mid - 1) && this->responding.packet)
720 {
721 DBG1(DBG_IKE, "received retransmit of request with ID %d, "
722 "retransmitting response", mid);
723 charon->sender->send(charon->sender,
724 this->responding.packet->clone(this->responding.packet));
725 }
726 else
727 {
728 DBG1(DBG_IKE, "received message ID %d, excepted %d. Ignored",
729 mid, this->responding.mid);
730 }
731 }
732 else
733 {
734 if (mid == this->initiating.mid)
735 {
736 if (process_response(this, msg) != SUCCESS)
737 {
738 flush(this);
739 return DESTROY_ME;
740 }
741 }
742 else
743 {
744 DBG1(DBG_IKE, "received message ID %d, excepted %d. Ignored",
745 mid, this->initiating.mid);
746 return SUCCESS;
747 }
748 }
749 return SUCCESS;
750 }
751
752 /**
753 * Implementation of task_manager_t.queue_task
754 */
755 static void queue_task(private_task_manager_t *this, task_t *task)
756 {
757 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
758 this->queued_tasks->insert_last(this->queued_tasks, task);
759 }
760
761 /**
762 * Implementation of task_manager_t.adopt_tasks
763 */
764 static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *other)
765 {
766 task_t *task;
767
768 /* move queued tasks from other to this */
769 while (other->queued_tasks->remove_last(other->queued_tasks,
770 (void**)&task) == SUCCESS)
771 {
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);
775 }
776
777 /* reset active tasks and move them to others queued tasks */
778 while (other->active_tasks->remove_last(other->active_tasks,
779 (void**)&task) == SUCCESS)
780 {
781 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
782 task->migrate(task, this->ike_sa);
783 this->queued_tasks->insert_first(this->queued_tasks, task);
784 }
785 }
786
787 /**
788 * Implementation of task_manager_t.busy
789 */
790 static bool busy(private_task_manager_t *this)
791 {
792 return (this->active_tasks->get_count(this->active_tasks) > 0);
793 }
794
795 /**
796 * Implementation of task_manager_t.reset
797 */
798 static void reset(private_task_manager_t *this)
799 {
800 task_t *task;
801
802 /* reset message counters and retransmit packets */
803 DESTROY_IF(this->responding.packet);
804 DESTROY_IF(this->initiating.packet);
805 this->responding.packet = NULL;
806 this->initiating.packet = NULL;
807 this->responding.mid = 0;
808 this->initiating.mid = -1;
809 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
810
811 /* reset active tasks */
812 while (this->active_tasks->remove_last(this->active_tasks,
813 (void**)&task) == SUCCESS)
814 {
815 task->migrate(task, this->ike_sa);
816 this->queued_tasks->insert_first(this->queued_tasks, task);
817 }
818 }
819
820 /**
821 * Implementation of task_manager_t.destroy
822 */
823 static void destroy(private_task_manager_t *this)
824 {
825 flush(this);
826
827 this->active_tasks->destroy(this->active_tasks);
828 this->queued_tasks->destroy(this->queued_tasks);
829 this->passive_tasks->destroy(this->passive_tasks);
830
831 DESTROY_IF(this->responding.packet);
832 DESTROY_IF(this->initiating.packet);
833 free(this);
834 }
835
836 /*
837 * see header file
838 */
839 task_manager_t *task_manager_create(ike_sa_t *ike_sa)
840 {
841 private_task_manager_t *this = malloc_thing(private_task_manager_t);
842
843 this->public.process_message = (status_t(*)(task_manager_t*,message_t*))process_message;
844 this->public.queue_task = (void(*)(task_manager_t*,task_t*))queue_task;
845 this->public.initiate = (status_t(*)(task_manager_t*))build_request;
846 this->public.retransmit = (status_t(*)(task_manager_t*,u_int32_t))retransmit;
847 this->public.reset = (void(*)(task_manager_t*))reset;
848 this->public.adopt_tasks = (void(*)(task_manager_t*,task_manager_t*))adopt_tasks;
849 this->public.busy = (bool(*)(task_manager_t*))busy;
850 this->public.destroy = (void(*)(task_manager_t*))destroy;
851
852 this->ike_sa = ike_sa;
853 this->responding.packet = NULL;
854 this->initiating.packet = NULL;
855 this->responding.mid = 0;
856 this->initiating.mid = 0;
857 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
858 this->queued_tasks = linked_list_create();
859 this->active_tasks = linked_list_create();
860 this->passive_tasks = linked_list_create();
861
862 return &this->public;
863 }