]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/charon/sa/task_manager.c
proper cleanup on error
[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
3b138b84
MW
25#include <math.h>
26
c60c7694
MW
27#include <daemon.h>
28#include <sa/tasks/ike_init.h>
29#include <sa/tasks/ike_natd.h>
17d92e97 30#include <sa/tasks/ike_mobike.h>
c60c7694
MW
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>
e0fe7651 41#include <processing/jobs/retransmit_job.h>
c60c7694
MW
42
43typedef struct exchange_t exchange_t;
44
45/**
46 * An exchange in the air, used do detect and handle retransmission
47 */
48struct 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
61typedef struct private_task_manager_t private_task_manager_t;
62
63/**
64 * private data of the task manager
65 */
66struct 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;
17d92e97
MW
134
135 /**
136 * the task manager has been reset
137 */
138 bool reset;
c60c7694
MW
139};
140
0f33e826
MW
141/**
142 * flush all tasks in the task manager
143 */
144static void flush(private_task_manager_t *this)
145{
146 task_t *task;
147
148 this->queued_tasks->destroy_offset(this->queued_tasks,
17d92e97 149 offsetof(task_t, destroy));
0f33e826
MW
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
c60c7694
MW
186/**
187 * move a task of a specific type from the queue to the active list
188 */
189static 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 */
214static 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;
5474dc65
MW
220 iterator_t *iterator;
221 packet_t *packet;
222 task_t *task;
f215e919 223 ike_mobike_t *mobike = NULL;
c60c7694 224
f215e919 225 /* check if we are retransmitting a MOBIKE routability check */
5474dc65
MW
226 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
227 while (iterator->iterate(iterator, (void*)&task))
228 {
229 if (task->get_type(task) == IKE_MOBIKE)
230 {
f215e919
MW
231 mobike = (ike_mobike_t*)task;
232 if (!mobike->is_probing(mobike))
233 {
234 mobike = NULL;
235 }
5474dc65
MW
236 break;
237 }
238 }
239 iterator->destroy(iterator);
f215e919
MW
240
241 if (mobike == NULL)
242 {
243 if (this->initiating.retransmitted <= RETRANSMIT_TRIES)
244 {
245 timeout = (u_int32_t)(RETRANSMIT_TIMEOUT *
246 pow(RETRANSMIT_BASE, this->initiating.retransmitted));
247 }
248 else
249 {
250 DBG1(DBG_IKE, "giving up after %d retransmits",
251 this->initiating.retransmitted - 1);
252 return DESTROY_ME;
253 }
254
255 if (this->initiating.retransmitted)
256 {
257 DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
258 this->initiating.retransmitted, message_id);
259 }
260 packet = this->initiating.packet->clone(this->initiating.packet);
261 }
262 else
263 { /* for routeability checks, we use a more aggressive behavior */
264 if (this->initiating.retransmitted <= ROUTEABILITY_CHECK_TRIES)
265 {
266 timeout = ROUTEABILITY_CHECK_INTERVAL;
267 }
268 else
269 {
270 DBG1(DBG_IKE, "giving up after %d path probings",
271 this->initiating.retransmitted - 1);
272 return DESTROY_ME;
273 }
274
275 if (this->initiating.retransmitted)
276 {
277 DBG1(DBG_IKE, "path probing attempt %d",
278 this->initiating.retransmitted);
279 }
280 packet = this->initiating.packet->clone(this->initiating.packet);
281 mobike->transmit(mobike, packet);
282 }
5474dc65
MW
283
284 charon->sender->send(charon->sender, packet);
f215e919
MW
285
286 this->initiating.retransmitted++;
c60c7694
MW
287 job = (job_t*)retransmit_job_create(this->initiating.mid,
288 this->ike_sa->get_id(this->ike_sa));
9fe1a1ca 289 charon->scheduler->schedule_job(charon->scheduler, job, timeout);
c60c7694
MW
290 }
291 return SUCCESS;
292}
293
294/**
295 * build a request using the active task list
296 * Implementation of task_manager_t.initiate
297 */
298static status_t build_request(private_task_manager_t *this)
299{
300 iterator_t *iterator;
301 task_t *task;
302 message_t *message;
5474dc65 303 host_t *me, *other;
c60c7694
MW
304 status_t status;
305 exchange_type_t exchange = 0;
306
2540992a
MW
307 if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
308 {
309 DBG2(DBG_IKE, "delaying task initiation, exchange in progress");
310 /* do not initiate if we already have a message in the air */
311 return SUCCESS;
312 }
313
c60c7694
MW
314 if (this->active_tasks->get_count(this->active_tasks) == 0)
315 {
316 DBG2(DBG_IKE, "activating new tasks");
317 switch (this->ike_sa->get_state(this->ike_sa))
318 {
319 case IKE_CREATED:
320 if (activate_task(this, IKE_INIT))
321 {
63c47724 322 this->initiating.mid = 0;
c60c7694
MW
323 exchange = IKE_SA_INIT;
324 activate_task(this, IKE_NATD);
325 activate_task(this, IKE_CERT);
326 activate_task(this, IKE_AUTHENTICATE);
327 activate_task(this, IKE_CONFIG);
328 activate_task(this, CHILD_CREATE);
17d92e97 329 activate_task(this, IKE_MOBIKE);
c60c7694
MW
330 }
331 break;
332 case IKE_ESTABLISHED:
333 if (activate_task(this, CHILD_CREATE))
334 {
335 exchange = CREATE_CHILD_SA;
c60c7694
MW
336 break;
337 }
338 if (activate_task(this, CHILD_DELETE))
339 {
340 exchange = INFORMATIONAL;
341 break;
342 }
343 if (activate_task(this, CHILD_REKEY))
344 {
345 exchange = CREATE_CHILD_SA;
346 break;
347 }
348 if (activate_task(this, IKE_DELETE))
349 {
350 exchange = INFORMATIONAL;
351 break;
352 }
353 if (activate_task(this, IKE_REKEY))
354 {
355 exchange = CREATE_CHILD_SA;
356 break;
357 }
26424f03
MW
358 if (activate_task(this, IKE_REAUTH))
359 {
360 exchange = INFORMATIONAL;
361 break;
362 }
4cb9d7a7
MW
363 if (activate_task(this, IKE_MOBIKE))
364 {
365 exchange = INFORMATIONAL;
366 break;
367 }
17d92e97 368 if (activate_task(this, IKE_DPD))
c60c7694
MW
369 {
370 exchange = INFORMATIONAL;
371 break;
372 }
373 case IKE_REKEYING:
374 if (activate_task(this, IKE_DELETE))
375 {
376 exchange = INFORMATIONAL;
377 break;
378 }
379 case IKE_DELETING:
380 default:
381 break;
382 }
383 }
384 else
385 {
386 DBG2(DBG_IKE, "reinitiating already active tasks");
387 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
388 while (iterator->iterate(iterator, (void**)&task))
389 {
390 DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
391 switch (task->get_type(task))
392 {
393 case IKE_INIT:
394 exchange = IKE_SA_INIT;
395 break;
396 case IKE_AUTHENTICATE:
397 exchange = IKE_AUTH;
398 break;
1fd5383e
MW
399 case CHILD_CREATE:
400 case CHILD_REKEY:
401 case IKE_REKEY:
402 exchange = CREATE_CHILD_SA;
403 break;
2b3100b5
MW
404 case IKE_MOBIKE:
405 exchange = INFORMATIONAL;
c60c7694
MW
406 default:
407 continue;
408 }
409 break;
410 }
411 iterator->destroy(iterator);
412 }
413
414 if (exchange == 0)
415 {
416 DBG2(DBG_IKE, "nothing to initiate");
417 /* nothing to do yet... */
418 return SUCCESS;
419 }
420
5474dc65
MW
421 me = this->ike_sa->get_my_host(this->ike_sa);
422 other = this->ike_sa->get_other_host(this->ike_sa);
423
c60c7694
MW
424 message = message_create();
425 message->set_message_id(message, this->initiating.mid);
5474dc65
MW
426 message->set_source(message, me->clone(me));
427 message->set_destination(message, other->clone(other));
c60c7694
MW
428 message->set_exchange_type(message, exchange);
429 this->initiating.type = exchange;
430 this->initiating.retransmitted = 0;
431
432 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
433 while (iterator->iterate(iterator, (void*)&task))
434 {
435 switch (task->build(task, message))
436 {
437 case SUCCESS:
438 /* task completed, remove it */
439 iterator->remove(iterator);
440 task->destroy(task);
441 break;
442 case NEED_MORE:
443 /* processed, but task needs another exchange */
444 break;
445 case FAILED:
446 default:
447 /* critical failure, destroy IKE_SA */
448 iterator->destroy(iterator);
449 message->destroy(message);
0f33e826 450 flush(this);
c60c7694
MW
451 return DESTROY_ME;
452 }
453 }
454 iterator->destroy(iterator);
455
456 DESTROY_IF(this->initiating.packet);
457 status = this->ike_sa->generate_message(this->ike_sa, message,
458 &this->initiating.packet);
459 message->destroy(message);
460 if (status != SUCCESS)
461 {
462 /* message generation failed. There is nothing more to do than to
463 * close the SA */
0f33e826 464 flush(this);
c60c7694 465 return DESTROY_ME;
5474dc65 466 }
c60c7694
MW
467
468 return retransmit(this, this->initiating.mid);
469}
470
471/**
472 * handle an incoming response message
473 */
474static status_t process_response(private_task_manager_t *this,
475 message_t *message)
476{
477 iterator_t *iterator;
478 task_t *task;
479
480 if (message->get_exchange_type(message) != this->initiating.type)
481 {
482 DBG1(DBG_IKE, "received %N response, but expected %N",
483 exchange_type_names, message->get_exchange_type(message),
484 exchange_type_names, this->initiating.type);
485 return DESTROY_ME;
486 }
487
17d92e97
MW
488 /* catch if we get resetted while processing */
489 this->reset = FALSE;
c60c7694
MW
490 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
491 while (iterator->iterate(iterator, (void*)&task))
492 {
493 switch (task->process(task, message))
494 {
495 case SUCCESS:
496 /* task completed, remove it */
497 iterator->remove(iterator);
498 task->destroy(task);
499 break;
500 case NEED_MORE:
501 /* processed, but task needs another exchange */
502 break;
503 case FAILED:
504 default:
505 /* critical failure, destroy IKE_SA */
506 iterator->destroy(iterator);
507 return DESTROY_ME;
508 }
17d92e97
MW
509 if (this->reset)
510 { /* start all over again if we were reset */
511 this->reset = FALSE;
512 iterator->destroy(iterator);
513 return build_request(this);
514 }
c60c7694
MW
515 }
516 iterator->destroy(iterator);
517
518 this->initiating.mid++;
2540992a 519 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
c60c7694
MW
520
521 return build_request(this);
522}
523
195ada0b
MW
524/**
525 * handle exchange collisions
526 */
527static void handle_collisions(private_task_manager_t *this, task_t *task)
528{
529 iterator_t *iterator;
530 task_t *active;
531 task_type_t type;
532
533 type = task->get_type(task);
534
4315f5c8
MW
535 /* do we have to check */
536 if (type == IKE_REKEY || type == CHILD_REKEY ||
26424f03 537 type == CHILD_DELETE || type == IKE_DELETE || type == IKE_REAUTH)
4315f5c8
MW
538 {
539 /* find an exchange collision, and notify these tasks */
540 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
541 while (iterator->iterate(iterator, (void**)&active))
542 {
543 switch (active->get_type(active))
544 {
545 case IKE_REKEY:
26424f03
MW
546 if (type == IKE_REKEY || type == IKE_DELETE ||
547 type == IKE_REAUTH)
4315f5c8
MW
548 {
549 ike_rekey_t *rekey = (ike_rekey_t*)active;
550 rekey->collide(rekey, task);
551 break;
552 }
553 continue;
554 case CHILD_REKEY:
4315f5c8
MW
555 if (type == CHILD_REKEY || type == CHILD_DELETE)
556 {
557 child_rekey_t *rekey = (child_rekey_t*)active;
558 rekey->collide(rekey, task);
559 break;
560 }
561 continue;
562 default:
563 continue;
564 }
565 iterator->destroy(iterator);
566 return;
567 }
568 iterator->destroy(iterator);
195ada0b 569 }
4315f5c8
MW
570 /* destroy task if not registered in any active task */
571 task->destroy(task);
195ada0b
MW
572}
573
c60c7694
MW
574/**
575 * build a response depending on the "passive" task list
576 */
5474dc65 577static status_t build_response(private_task_manager_t *this, message_t *request)
c60c7694
MW
578{
579 iterator_t *iterator;
580 task_t *task;
581 message_t *message;
5474dc65 582 host_t *me, *other;
c60c7694
MW
583 bool delete = FALSE;
584 status_t status;
585
5474dc65
MW
586 me = request->get_destination(request);
587 other = request->get_source(request);
588
c60c7694 589 message = message_create();
5474dc65
MW
590 message->set_exchange_type(message, request->get_exchange_type(request));
591 /* send response along the path the request came in */
592 message->set_source(message, me->clone(me));
593 message->set_destination(message, other->clone(other));
c60c7694
MW
594 message->set_message_id(message, this->responding.mid);
595 message->set_request(message, FALSE);
596
597 iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
598 while (iterator->iterate(iterator, (void*)&task))
599 {
600 switch (task->build(task, message))
601 {
602 case SUCCESS:
603 /* task completed, remove it */
604 iterator->remove(iterator);
195ada0b 605 handle_collisions(this, task);
c60c7694
MW
606 case NEED_MORE:
607 /* processed, but task needs another exchange */
608 break;
609 case FAILED:
610 default:
611 /* destroy IKE_SA, but SEND response first */
612 delete = TRUE;
613 break;
614 }
615 if (delete)
616 {
617 break;
618 }
619 }
620 iterator->destroy(iterator);
ddae0f96
MW
621
622 /* remove resonder SPI if IKE_SA_INIT failed */
5474dc65 623 if (delete && request->get_exchange_type(request) == IKE_SA_INIT)
ddae0f96
MW
624 {
625 ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa);
626 id->set_responder_spi(id, 0);
627 }
c60c7694
MW
628
629 /* message complete, send it */
630 DESTROY_IF(this->responding.packet);
631 status = this->ike_sa->generate_message(this->ike_sa, message,
632 &this->responding.packet);
633 message->destroy(message);
634 if (status != SUCCESS)
635 {
636 return DESTROY_ME;
637 }
638
4deb8948
MW
639 charon->sender->send(charon->sender,
640 this->responding.packet->clone(this->responding.packet));
c60c7694
MW
641 if (delete)
642 {
643 return DESTROY_ME;
644 }
645 return SUCCESS;
646}
647
648/**
649 * handle an incoming request message
650 */
651static status_t process_request(private_task_manager_t *this,
652 message_t *message)
653{
654 iterator_t *iterator;
655 task_t *task = NULL;
c60c7694
MW
656 payload_t *payload;
657 notify_payload_t *notify;
4cb9d7a7 658 delete_payload_t *delete;
c60c7694 659
c60c7694 660 /* create tasks depending on request type */
5474dc65 661 switch (message->get_exchange_type(message))
c60c7694
MW
662 {
663 case IKE_SA_INIT:
664 {
665 task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
666 this->passive_tasks->insert_last(this->passive_tasks, task);
667 task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
668 this->passive_tasks->insert_last(this->passive_tasks, task);
669 task = (task_t*)ike_cert_create(this->ike_sa, FALSE);
670 this->passive_tasks->insert_last(this->passive_tasks, task);
c60c7694
MW
671 task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
672 this->passive_tasks->insert_last(this->passive_tasks, task);
e0fe7651 673 task = (task_t*)ike_config_create(this->ike_sa, FALSE);
5744d3e7 674 this->passive_tasks->insert_last(this->passive_tasks, task);
c60c7694
MW
675 task = (task_t*)child_create_create(this->ike_sa, NULL);
676 this->passive_tasks->insert_last(this->passive_tasks, task);
17d92e97
MW
677 task = (task_t*)ike_mobike_create(this->ike_sa, FALSE);
678 this->passive_tasks->insert_last(this->passive_tasks, task);
c60c7694
MW
679 break;
680 }
681 case CREATE_CHILD_SA:
682 {
683 bool notify_found = FALSE, ts_found = FALSE;
684 iterator = message->get_payload_iterator(message);
685 while (iterator->iterate(iterator, (void**)&payload))
686 {
687 switch (payload->get_type(payload))
688 {
689 case NOTIFY:
690 {
691 /* if we find a rekey notify, its CHILD_SA rekeying */
692 notify = (notify_payload_t*)payload;
693 if (notify->get_notify_type(notify) == REKEY_SA &&
694 (notify->get_protocol_id(notify) == PROTO_AH ||
695 notify->get_protocol_id(notify) == PROTO_ESP))
696 {
697 notify_found = TRUE;
698 }
699 break;
700 }
701 case TRAFFIC_SELECTOR_INITIATOR:
702 case TRAFFIC_SELECTOR_RESPONDER:
703 {
704 /* if we don't find a TS, its IKE rekeying */
705 ts_found = TRUE;
706 break;
707 }
708 default:
709 break;
710 }
711 }
712 iterator->destroy(iterator);
713
714 if (ts_found)
715 {
716 if (notify_found)
717 {
718 task = (task_t*)child_rekey_create(this->ike_sa, NULL);
719 }
720 else
721 {
722 task = (task_t*)child_create_create(this->ike_sa, NULL);
723 }
724 }
725 else
726 {
727 task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
728 }
729 this->passive_tasks->insert_last(this->passive_tasks, task);
c60c7694
MW
730 break;
731 }
732 case INFORMATIONAL:
733 {
4cb9d7a7
MW
734 iterator = message->get_payload_iterator(message);
735 while (iterator->iterate(iterator, (void**)&payload))
c60c7694 736 {
4cb9d7a7 737 switch (payload->get_type(payload))
c60c7694 738 {
4cb9d7a7
MW
739 case NOTIFY:
740 {
741 notify = (notify_payload_t*)payload;
742 switch (notify->get_notify_type(notify))
743 {
744 case ADDITIONAL_IP4_ADDRESS:
745 case ADDITIONAL_IP6_ADDRESS:
746 case NO_ADDITIONAL_ADDRESSES:
747 case UPDATE_SA_ADDRESSES:
748 case NO_NATS_ALLOWED:
749 case UNACCEPTABLE_ADDRESSES:
750 case UNEXPECTED_NAT_DETECTED:
751 case COOKIE2:
752 task = (task_t*)ike_mobike_create(this->ike_sa,
753 FALSE);
754 break;
755 default:
756 break;
757 }
758 break;
759 }
760 case DELETE:
761 {
762 delete = (delete_payload_t*)payload;
763 if (delete->get_protocol_id(delete) == PROTO_IKE)
764 {
765 task = (task_t*)ike_delete_create(this->ike_sa, FALSE);
766 }
767 else
768 {
769 task = (task_t*)child_delete_create(this->ike_sa, NULL);
770 }
771 break;
772 }
773 default:
774 break;
c60c7694 775 }
3bc62fe7
MW
776 if (task)
777 {
778 break;
779 }
c60c7694 780 }
4cb9d7a7
MW
781 iterator->destroy(iterator);
782
783 if (task == NULL)
c60c7694
MW
784 {
785 task = (task_t*)ike_dpd_create(FALSE);
c60c7694 786 }
4cb9d7a7 787 this->passive_tasks->insert_last(this->passive_tasks, task);
c60c7694
MW
788 break;
789 }
790 default:
791 break;
792 }
793
794 /* let the tasks process the message */
795 iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
796 while (iterator->iterate(iterator, (void*)&task))
797 {
798 switch (task->process(task, message))
799 {
800 case SUCCESS:
801 /* task completed, remove it */
802 iterator->remove(iterator);
803 task->destroy(task);
804 break;
805 case NEED_MORE:
806 /* processed, but task needs at least another call to build() */
807 break;
808 case FAILED:
809 default:
810 /* critical failure, destroy IKE_SA */
811 iterator->destroy(iterator);
812 return DESTROY_ME;
813 }
814 }
815 iterator->destroy(iterator);
816
5474dc65 817 return build_response(this, message);
c60c7694
MW
818}
819
820/**
821 * Implementation of task_manager_t.process_message
822 */
823static status_t process_message(private_task_manager_t *this, message_t *msg)
824{
825 u_int32_t mid = msg->get_message_id(msg);
826
827 if (msg->get_request(msg))
828 {
829 if (mid == this->responding.mid)
830 {
831 if (process_request(this, msg) != SUCCESS)
832 {
0f33e826 833 flush(this);
c60c7694
MW
834 return DESTROY_ME;
835 }
836 this->responding.mid++;
837 }
838 else if ((mid == this->responding.mid - 1) && this->responding.packet)
839 {
d9d69536
MW
840 packet_t *clone;
841 host_t *me, *other;
842
c60c7694
MW
843 DBG1(DBG_IKE, "received retransmit of request with ID %d, "
844 "retransmitting response", mid);
d9d69536
MW
845 clone = this->responding.packet->clone(this->responding.packet);
846 me = msg->get_destination(msg);
847 other = msg->get_source(msg);
848 clone->set_source(clone, me->clone(me));
849 clone->set_destination(clone, other->clone(other));
850 charon->sender->send(charon->sender, clone);
c60c7694
MW
851 }
852 else
853 {
278396b6 854 DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
c60c7694
MW
855 mid, this->responding.mid);
856 }
857 }
858 else
859 {
860 if (mid == this->initiating.mid)
861 {
862 if (process_response(this, msg) != SUCCESS)
863 {
0f33e826 864 flush(this);
c60c7694
MW
865 return DESTROY_ME;
866 }
867 }
868 else
869 {
278396b6 870 DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
c60c7694
MW
871 mid, this->initiating.mid);
872 return SUCCESS;
873 }
874 }
875 return SUCCESS;
876}
877
878/**
879 * Implementation of task_manager_t.queue_task
880 */
881static void queue_task(private_task_manager_t *this, task_t *task)
882{
f215e919
MW
883 if (task->get_type(task) == IKE_MOBIKE)
884 { /* there is no need to queue more than one mobike task */
885 iterator_t *iterator;
886 task_t *current;
887
888 iterator = this->queued_tasks->create_iterator(this->queued_tasks, TRUE);
889 while (iterator->iterate(iterator, (void**)&current))
890 {
891 if (current->get_type(current) == IKE_MOBIKE)
892 {
893 iterator->destroy(iterator);
894 task->destroy(task);
895 return;
896 }
897 }
898 iterator->destroy(iterator);
899 }
c60c7694
MW
900 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
901 this->queued_tasks->insert_last(this->queued_tasks, task);
902}
903
904/**
905 * Implementation of task_manager_t.adopt_tasks
906 */
907static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *other)
908{
909 task_t *task;
910
911 /* move queued tasks from other to this */
912 while (other->queued_tasks->remove_last(other->queued_tasks,
913 (void**)&task) == SUCCESS)
914 {
e23a59f6 915 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
c60c7694
MW
916 task->migrate(task, this->ike_sa);
917 this->queued_tasks->insert_first(this->queued_tasks, task);
918 }
919
920 /* reset active tasks and move them to others queued tasks */
921 while (other->active_tasks->remove_last(other->active_tasks,
922 (void**)&task) == SUCCESS)
923 {
e23a59f6 924 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
c60c7694
MW
925 task->migrate(task, this->ike_sa);
926 this->queued_tasks->insert_first(this->queued_tasks, task);
927 }
928}
929
930/**
931 * Implementation of task_manager_t.busy
932 */
933static bool busy(private_task_manager_t *this)
934{
935 return (this->active_tasks->get_count(this->active_tasks) > 0);
936}
937
938/**
939 * Implementation of task_manager_t.reset
940 */
941static void reset(private_task_manager_t *this)
942{
943 task_t *task;
944
945 /* reset message counters and retransmit packets */
946 DESTROY_IF(this->responding.packet);
947 DESTROY_IF(this->initiating.packet);
c60c7694
MW
948 this->responding.packet = NULL;
949 this->initiating.packet = NULL;
c60c7694 950 this->responding.mid = 0;
17d92e97 951 this->initiating.mid = 0;
1edf116c 952 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
c60c7694
MW
953
954 /* reset active tasks */
955 while (this->active_tasks->remove_last(this->active_tasks,
956 (void**)&task) == SUCCESS)
957 {
958 task->migrate(task, this->ike_sa);
959 this->queued_tasks->insert_first(this->queued_tasks, task);
960 }
17d92e97
MW
961
962 this->reset = TRUE;
c60c7694
MW
963}
964
965/**
966 * Implementation of task_manager_t.destroy
967 */
968static void destroy(private_task_manager_t *this)
969{
0f33e826 970 flush(this);
c60c7694 971
c60c7694 972 this->active_tasks->destroy(this->active_tasks);
0f33e826
MW
973 this->queued_tasks->destroy(this->queued_tasks);
974 this->passive_tasks->destroy(this->passive_tasks);
975
c60c7694
MW
976 DESTROY_IF(this->responding.packet);
977 DESTROY_IF(this->initiating.packet);
c60c7694
MW
978 free(this);
979}
980
981/*
982 * see header file
983 */
984task_manager_t *task_manager_create(ike_sa_t *ike_sa)
985{
986 private_task_manager_t *this = malloc_thing(private_task_manager_t);
987
988 this->public.process_message = (status_t(*)(task_manager_t*,message_t*))process_message;
989 this->public.queue_task = (void(*)(task_manager_t*,task_t*))queue_task;
990 this->public.initiate = (status_t(*)(task_manager_t*))build_request;
991 this->public.retransmit = (status_t(*)(task_manager_t*,u_int32_t))retransmit;
992 this->public.reset = (void(*)(task_manager_t*))reset;
993 this->public.adopt_tasks = (void(*)(task_manager_t*,task_manager_t*))adopt_tasks;
994 this->public.busy = (bool(*)(task_manager_t*))busy;
995 this->public.destroy = (void(*)(task_manager_t*))destroy;
996
997 this->ike_sa = ike_sa;
998 this->responding.packet = NULL;
999 this->initiating.packet = NULL;
1000 this->responding.mid = 0;
1001 this->initiating.mid = 0;
2540992a 1002 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
c60c7694
MW
1003 this->queued_tasks = linked_list_create();
1004 this->active_tasks = linked_list_create();
1005 this->passive_tasks = linked_list_create();
17d92e97 1006 this->reset = FALSE;
c60c7694
MW
1007
1008 return &this->public;
1009}