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