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