]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/sa/ikev2/task_manager_v2.c
ike-rekey: Ignore colliding rekey tasks that did not create an IKE_SA
[thirdparty/strongswan.git] / src / libcharon / sa / ikev2 / task_manager_v2.c
CommitLineData
c60c7694 1/*
1cca2070 2 * Copyright (C) 2007-2016 Tobias Brunner
9560a316 3 * Copyright (C) 2007-2010 Martin Willi
c60c7694
MW
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
e69f7dcd 17#include "task_manager_v2.h"
c60c7694 18
3b138b84
MW
19#include <math.h>
20
6207fadb 21#include <collections/array.h>
c60c7694 22#include <daemon.h>
15a682f4
MW
23#include <sa/ikev2/tasks/ike_init.h>
24#include <sa/ikev2/tasks/ike_natd.h>
25#include <sa/ikev2/tasks/ike_mobike.h>
26#include <sa/ikev2/tasks/ike_auth.h>
27#include <sa/ikev2/tasks/ike_auth_lifetime.h>
28#include <sa/ikev2/tasks/ike_cert_pre.h>
29#include <sa/ikev2/tasks/ike_cert_post.h>
30#include <sa/ikev2/tasks/ike_rekey.h>
cedb412e 31#include <sa/ikev2/tasks/ike_reauth.h>
3676023e 32#include <sa/ikev2/tasks/ike_reauth_complete.h>
0840385b 33#include <sa/ikev2/tasks/ike_redirect.h>
15a682f4
MW
34#include <sa/ikev2/tasks/ike_delete.h>
35#include <sa/ikev2/tasks/ike_config.h>
36#include <sa/ikev2/tasks/ike_dpd.h>
37#include <sa/ikev2/tasks/ike_vendor.h>
f1cbacc5 38#include <sa/ikev2/tasks/ike_verify_peer_cert.h>
15a682f4
MW
39#include <sa/ikev2/tasks/child_create.h>
40#include <sa/ikev2/tasks/child_rekey.h>
41#include <sa/ikev2/tasks/child_delete.h>
c60c7694 42#include <encoding/payloads/delete_payload.h>
68c6863b 43#include <encoding/payloads/unknown_payload.h>
e0fe7651 44#include <processing/jobs/retransmit_job.h>
68c6863b 45#include <processing/jobs/delete_ike_sa_job.h>
c60c7694 46
dc04b7c7 47#ifdef ME
15a682f4 48#include <sa/ikev2/tasks/ike_me.h>
d5cc1758
TB
49#endif
50
c60c7694
MW
51typedef struct exchange_t exchange_t;
52
53/**
54 * An exchange in the air, used do detect and handle retransmission
55 */
56struct exchange_t {
7daf5226 57
c60c7694
MW
58 /**
59 * Message ID used for this transaction
60 */
b12c53ce 61 uint32_t mid;
7daf5226 62
c60c7694
MW
63 /**
64 * generated packet for retransmission
65 */
66 packet_t *packet;
67};
68
69typedef struct private_task_manager_t private_task_manager_t;
70
71/**
72 * private data of the task manager
73 */
74struct private_task_manager_t {
7daf5226 75
c60c7694
MW
76 /**
77 * public functions
78 */
e69f7dcd 79 task_manager_v2_t public;
7daf5226 80
c60c7694
MW
81 /**
82 * associated IKE_SA we are serving
83 */
84 ike_sa_t *ike_sa;
7daf5226 85
c60c7694
MW
86 /**
87 * Exchange we are currently handling as responder
88 */
89 struct {
90 /**
91 * Message ID of the exchange
92 */
b12c53ce 93 uint32_t mid;
7daf5226 94
c60c7694 95 /**
b678d9e1 96 * packet(s) for retransmission
c60c7694 97 */
b678d9e1
TB
98 array_t *packets;
99
100 /**
101 * Helper to defragment the request
102 */
103 message_t *defrag;
7daf5226 104
c60c7694 105 } responding;
7daf5226 106
c60c7694
MW
107 /**
108 * Exchange we are currently handling as initiator
109 */
110 struct {
111 /**
112 * Message ID of the exchange
113 */
b12c53ce 114 uint32_t mid;
7daf5226 115
c60c7694
MW
116 /**
117 * how many times we have retransmitted so far
118 */
119 u_int retransmitted;
120
121 /**
b678d9e1 122 * packet(s) for retransmission
c60c7694 123 */
b678d9e1 124 array_t *packets;
7daf5226 125
c60c7694
MW
126 /**
127 * type of the initated exchange
128 */
129 exchange_type_t type;
7daf5226 130
10bad0fc
TB
131 /**
132 * TRUE if exchange was deferred because no path was available
133 */
134 bool deferred;
135
b678d9e1
TB
136 /**
137 * Helper to defragment the response
138 */
139 message_t *defrag;
140
c60c7694 141 } initiating;
7daf5226 142
c60c7694 143 /**
6207fadb 144 * Array of queued tasks not yet in action
c60c7694 145 */
6207fadb 146 array_t *queued_tasks;
7daf5226 147
c60c7694 148 /**
6207fadb 149 * Array of active tasks, initiated by ourselve
c60c7694 150 */
6207fadb 151 array_t *active_tasks;
7daf5226 152
c60c7694 153 /**
6207fadb 154 * Array of tasks initiated by peer
c60c7694 155 */
6207fadb 156 array_t *passive_tasks;
7daf5226 157
17d92e97 158 /**
484a06bc 159 * the task manager has been reset
17d92e97
MW
160 */
161 bool reset;
bc6ff2fc
MW
162
163 /**
164 * Number of times we retransmit messages before giving up
165 */
166 u_int retransmit_tries;
167
168 /**
169 * Retransmission timeout
170 */
171 double retransmit_timeout;
172
173 /**
174 * Base to calculate retransmission timeout
175 */
176 double retransmit_base;
349f7f24
MW
177
178 /**
179 * Use make-before-break instead of break-before-make reauth?
180 */
181 bool make_before_break;
c60c7694
MW
182};
183
b678d9e1
TB
184/**
185 * Reset retransmission packet list
186 */
187static void clear_packets(array_t *array)
188{
189 packet_t *packet;
190
191 while (array_remove(array, ARRAY_TAIL, &packet))
192 {
193 packet->destroy(packet);
194 }
195}
196
a5c79960
MW
197METHOD(task_manager_t, flush_queue, void,
198 private_task_manager_t *this, task_queue_t queue)
199{
6207fadb 200 array_t *array;
a5c79960
MW
201 task_t *task;
202
203 switch (queue)
204 {
205 case TASK_QUEUE_ACTIVE:
6207fadb 206 array = this->active_tasks;
a5c79960
MW
207 break;
208 case TASK_QUEUE_PASSIVE:
6207fadb 209 array = this->passive_tasks;
a5c79960
MW
210 break;
211 case TASK_QUEUE_QUEUED:
6207fadb 212 array = this->queued_tasks;
a5c79960
MW
213 break;
214 default:
215 return;
216 }
6207fadb 217 while (array_remove(array, ARRAY_TAIL, &task))
a5c79960
MW
218 {
219 task->destroy(task);
220 }
221}
222
b1908994
TE
223METHOD(task_manager_t, flush, void,
224 private_task_manager_t *this)
0f33e826 225{
a5c79960
MW
226 flush_queue(this, TASK_QUEUE_QUEUED);
227 flush_queue(this, TASK_QUEUE_PASSIVE);
228 flush_queue(this, TASK_QUEUE_ACTIVE);
0f33e826
MW
229}
230
c60c7694
MW
231/**
232 * move a task of a specific type from the queue to the active list
233 */
234static bool activate_task(private_task_manager_t *this, task_type_t type)
235{
e2630434 236 enumerator_t *enumerator;
c60c7694
MW
237 task_t *task;
238 bool found = FALSE;
7daf5226 239
6207fadb 240 enumerator = array_create_enumerator(this->queued_tasks);
e2630434 241 while (enumerator->enumerate(enumerator, (void**)&task))
c60c7694
MW
242 {
243 if (task->get_type(task) == type)
244 {
245 DBG2(DBG_IKE, " activating %N task", task_type_names, type);
6207fadb
MW
246 array_remove_at(this->queued_tasks, enumerator);
247 array_insert(this->active_tasks, ARRAY_TAIL, task);
c60c7694
MW
248 found = TRUE;
249 break;
250 }
251 }
e2630434 252 enumerator->destroy(enumerator);
c60c7694
MW
253 return found;
254}
255
b678d9e1
TB
256/**
257 * Send packets in the given array (they get cloned). Optionally, the
258 * source and destination addresses are changed before sending it.
259 */
260static void send_packets(private_task_manager_t *this, array_t *packets,
261 host_t *src, host_t *dst)
262{
263 packet_t *packet, *clone;
264 int i;
265
266 for (i = 0; i < array_count(packets); i++)
267 {
268 array_get(packets, i, &packet);
269 clone = packet->clone(packet);
270 if (src)
271 {
272 clone->set_source(clone, src->clone(src));
273 }
274 if (dst)
275 {
276 clone->set_destination(clone, dst->clone(dst));
277 }
278 charon->sender->send(charon->sender, clone);
279 }
280}
281
282/**
283 * Generates the given message and stores packet(s) in the given array
284 */
285static bool generate_message(private_task_manager_t *this, message_t *message,
286 array_t **packets)
287{
288 enumerator_t *fragments;
289 packet_t *fragment;
290
291 if (this->ike_sa->generate_message_fragmented(this->ike_sa, message,
292 &fragments) != SUCCESS)
293 {
294 return FALSE;
295 }
296 while (fragments->enumerate(fragments, &fragment))
297 {
298 array_insert_create(packets, ARRAY_TAIL, fragment);
299 }
300 fragments->destroy(fragments);
301 array_compress(*packets);
302 return TRUE;
303}
304
9560a316 305METHOD(task_manager_t, retransmit, status_t,
b12c53ce 306 private_task_manager_t *this, uint32_t message_id)
c60c7694 307{
b678d9e1
TB
308 if (message_id == this->initiating.mid &&
309 array_count(this->initiating.packets))
c60c7694 310 {
b12c53ce 311 uint32_t timeout;
c60c7694 312 job_t *job;
e2630434 313 enumerator_t *enumerator;
5474dc65
MW
314 packet_t *packet;
315 task_t *task;
f215e919 316 ike_mobike_t *mobike = NULL;
7daf5226 317
b678d9e1
TB
318 array_get(this->initiating.packets, 0, &packet);
319
f215e919 320 /* check if we are retransmitting a MOBIKE routability check */
22949c59 321 if (this->initiating.type == INFORMATIONAL)
5474dc65 322 {
22949c59
TB
323 enumerator = array_create_enumerator(this->active_tasks);
324 while (enumerator->enumerate(enumerator, (void*)&task))
5474dc65 325 {
22949c59
TB
326 if (task->get_type(task) == TASK_IKE_MOBIKE)
327 {
328 mobike = (ike_mobike_t*)task;
329 break;
330 }
5474dc65 331 }
22949c59 332 enumerator->destroy(enumerator);
5474dc65 333 }
f215e919 334
de6ab8e8 335 if (!mobike || !mobike->is_probing(mobike))
f215e919 336 {
bc6ff2fc 337 if (this->initiating.retransmitted <= this->retransmit_tries)
f215e919 338 {
b12c53ce 339 timeout = (uint32_t)(this->retransmit_timeout * 1000.0 *
bc6ff2fc 340 pow(this->retransmit_base, this->initiating.retransmitted));
f215e919
MW
341 }
342 else
343 {
344 DBG1(DBG_IKE, "giving up after %d retransmits",
345 this->initiating.retransmitted - 1);
3c79b7b7 346 charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_TIMEOUT,
b678d9e1 347 packet);
f215e919
MW
348 return DESTROY_ME;
349 }
7daf5226 350
f215e919
MW
351 if (this->initiating.retransmitted)
352 {
353 DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
354 this->initiating.retransmitted, message_id);
9da65eae
TE
355 charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet,
356 this->initiating.retransmitted);
f215e919 357 }
de6ab8e8
TB
358 if (!mobike)
359 {
f1aa18b2
TB
360 send_packets(this, this->initiating.packets,
361 this->ike_sa->get_my_host(this->ike_sa),
362 this->ike_sa->get_other_host(this->ike_sa));
de6ab8e8 363 }
acd69fc2 364 else
de6ab8e8 365 {
b678d9e1 366 if (!mobike->transmit(mobike, packet))
acd69fc2
TB
367 {
368 DBG1(DBG_IKE, "no route found to reach peer, MOBIKE update "
369 "deferred");
370 this->ike_sa->set_condition(this->ike_sa, COND_STALE, TRUE);
371 this->initiating.deferred = TRUE;
372 return SUCCESS;
373 }
374 else if (mobike->is_probing(mobike))
375 {
376 timeout = ROUTEABILITY_CHECK_INTERVAL;
377 }
de6ab8e8 378 }
f215e919
MW
379 }
380 else
381 { /* for routeability checks, we use a more aggressive behavior */
382 if (this->initiating.retransmitted <= ROUTEABILITY_CHECK_TRIES)
383 {
384 timeout = ROUTEABILITY_CHECK_INTERVAL;
385 }
386 else
387 {
388 DBG1(DBG_IKE, "giving up after %d path probings",
389 this->initiating.retransmitted - 1);
390 return DESTROY_ME;
391 }
7daf5226 392
f215e919
MW
393 if (this->initiating.retransmitted)
394 {
395 DBG1(DBG_IKE, "path probing attempt %d",
396 this->initiating.retransmitted);
397 }
b678d9e1
TB
398 /* TODO-FRAG: presumably these small packets are not fragmented,
399 * we should maybe ensure this is the case when generating them */
400 if (!mobike->transmit(mobike, packet))
10bad0fc
TB
401 {
402 DBG1(DBG_IKE, "no route found to reach peer, path probing "
403 "deferred");
404 this->ike_sa->set_condition(this->ike_sa, COND_STALE, TRUE);
405 this->initiating.deferred = TRUE;
406 return SUCCESS;
407 }
f215e919 408 }
7daf5226 409
f215e919 410 this->initiating.retransmitted++;
c60c7694
MW
411 job = (job_t*)retransmit_job_create(this->initiating.mid,
412 this->ike_sa->get_id(this->ike_sa));
bb381e26 413 lib->scheduler->schedule_job_ms(lib->scheduler, job, timeout);
c60c7694
MW
414 }
415 return SUCCESS;
416}
417
9560a316
MW
418METHOD(task_manager_t, initiate, status_t,
419 private_task_manager_t *this)
c60c7694 420{
e2630434 421 enumerator_t *enumerator;
c60c7694
MW
422 task_t *task;
423 message_t *message;
5474dc65 424 host_t *me, *other;
c60c7694 425 exchange_type_t exchange = 0;
7daf5226 426
2540992a
MW
427 if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
428 {
03ffa885
TE
429 DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
430 exchange_type_names, this->initiating.type);
2540992a 431 /* do not initiate if we already have a message in the air */
10bad0fc
TB
432 if (this->initiating.deferred)
433 { /* re-initiate deferred exchange */
434 this->initiating.deferred = FALSE;
435 this->initiating.retransmitted = 0;
436 return retransmit(this, this->initiating.mid);
437 }
2540992a
MW
438 return SUCCESS;
439 }
7daf5226 440
6207fadb 441 if (array_count(this->active_tasks) == 0)
c60c7694
MW
442 {
443 DBG2(DBG_IKE, "activating new tasks");
444 switch (this->ike_sa->get_state(this->ike_sa))
445 {
446 case IKE_CREATED:
a09972df
MW
447 activate_task(this, TASK_IKE_VENDOR);
448 if (activate_task(this, TASK_IKE_INIT))
c60c7694 449 {
63c47724 450 this->initiating.mid = 0;
c60c7694 451 exchange = IKE_SA_INIT;
a09972df
MW
452 activate_task(this, TASK_IKE_NATD);
453 activate_task(this, TASK_IKE_CERT_PRE);
dc04b7c7 454#ifdef ME
a09972df 455 /* this task has to be activated before the TASK_IKE_AUTH
d5cc1758
TB
456 * task, because that task pregenerates the packet after
457 * which no payloads can be added to the message anymore.
458 */
a09972df 459 activate_task(this, TASK_IKE_ME);
dc04b7c7 460#endif /* ME */
a09972df
MW
461 activate_task(this, TASK_IKE_AUTH);
462 activate_task(this, TASK_IKE_CERT_POST);
463 activate_task(this, TASK_IKE_CONFIG);
464 activate_task(this, TASK_CHILD_CREATE);
465 activate_task(this, TASK_IKE_AUTH_LIFETIME);
466 activate_task(this, TASK_IKE_MOBIKE);
c60c7694
MW
467 }
468 break;
469 case IKE_ESTABLISHED:
9e3ab0d1 470 if (activate_task(this, TASK_IKE_MOBIKE))
c60c7694 471 {
9e3ab0d1 472 exchange = INFORMATIONAL;
c60c7694
MW
473 break;
474 }
9e3ab0d1 475 if (activate_task(this, TASK_IKE_DELETE))
c60c7694
MW
476 {
477 exchange = INFORMATIONAL;
478 break;
479 }
0840385b
TB
480 if (activate_task(this, TASK_IKE_REDIRECT))
481 {
482 exchange = INFORMATIONAL;
483 break;
484 }
9e3ab0d1 485 if (activate_task(this, TASK_CHILD_DELETE))
c60c7694 486 {
9e3ab0d1 487 exchange = INFORMATIONAL;
c60c7694
MW
488 break;
489 }
9e3ab0d1 490 if (activate_task(this, TASK_IKE_REAUTH))
c60c7694
MW
491 {
492 exchange = INFORMATIONAL;
493 break;
494 }
9e3ab0d1 495 if (activate_task(this, TASK_CHILD_CREATE))
c60c7694
MW
496 {
497 exchange = CREATE_CHILD_SA;
498 break;
499 }
9e3ab0d1 500 if (activate_task(this, TASK_CHILD_REKEY))
26424f03 501 {
9e3ab0d1 502 exchange = CREATE_CHILD_SA;
26424f03
MW
503 break;
504 }
9e3ab0d1 505 if (activate_task(this, TASK_IKE_REKEY))
4cb9d7a7 506 {
9e3ab0d1 507 exchange = CREATE_CHILD_SA;
4cb9d7a7
MW
508 break;
509 }
a09972df 510 if (activate_task(this, TASK_IKE_DPD))
c60c7694
MW
511 {
512 exchange = INFORMATIONAL;
513 break;
514 }
b1f2f05c
MW
515 if (activate_task(this, TASK_IKE_AUTH_LIFETIME))
516 {
517 exchange = INFORMATIONAL;
518 break;
519 }
dc04b7c7 520#ifdef ME
a09972df 521 if (activate_task(this, TASK_IKE_ME))
d5cc1758 522 {
dc04b7c7 523 exchange = ME_CONNECT;
d5cc1758
TB
524 break;
525 }
dc04b7c7 526#endif /* ME */
3676023e
MW
527 if (activate_task(this, TASK_IKE_REAUTH_COMPLETE))
528 {
529 exchange = INFORMATIONAL;
530 break;
531 }
8ce78e43
TB
532 if (activate_task(this, TASK_IKE_VERIFY_PEER_CERT))
533 {
534 exchange = INFORMATIONAL;
535 break;
536 }
c60c7694 537 case IKE_REKEYING:
bb389973 538 case IKE_REKEYED:
a09972df 539 if (activate_task(this, TASK_IKE_DELETE))
c60c7694
MW
540 {
541 exchange = INFORMATIONAL;
542 break;
543 }
544 case IKE_DELETING:
545 default:
546 break;
547 }
548 }
549 else
550 {
551 DBG2(DBG_IKE, "reinitiating already active tasks");
6207fadb
MW
552 enumerator = array_create_enumerator(this->active_tasks);
553 while (enumerator->enumerate(enumerator, &task))
c60c7694
MW
554 {
555 DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
556 switch (task->get_type(task))
557 {
a09972df 558 case TASK_IKE_INIT:
c60c7694
MW
559 exchange = IKE_SA_INIT;
560 break;
a09972df 561 case TASK_IKE_AUTH:
c60c7694
MW
562 exchange = IKE_AUTH;
563 break;
a09972df
MW
564 case TASK_CHILD_CREATE:
565 case TASK_CHILD_REKEY:
566 case TASK_IKE_REKEY:
1fd5383e
MW
567 exchange = CREATE_CHILD_SA;
568 break;
a09972df 569 case TASK_IKE_MOBIKE:
2b3100b5 570 exchange = INFORMATIONAL;
d46f8575 571 break;
c60c7694
MW
572 default:
573 continue;
574 }
575 break;
576 }
e2630434 577 enumerator->destroy(enumerator);
c60c7694 578 }
7daf5226 579
c60c7694
MW
580 if (exchange == 0)
581 {
582 DBG2(DBG_IKE, "nothing to initiate");
583 /* nothing to do yet... */
584 return SUCCESS;
585 }
7daf5226 586
5474dc65
MW
587 me = this->ike_sa->get_my_host(this->ike_sa);
588 other = this->ike_sa->get_other_host(this->ike_sa);
7daf5226 589
4ed52db2 590 message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
c60c7694 591 message->set_message_id(message, this->initiating.mid);
5474dc65
MW
592 message->set_source(message, me->clone(me));
593 message->set_destination(message, other->clone(other));
c60c7694
MW
594 message->set_exchange_type(message, exchange);
595 this->initiating.type = exchange;
596 this->initiating.retransmitted = 0;
10bad0fc 597 this->initiating.deferred = FALSE;
7daf5226 598
6207fadb
MW
599 enumerator = array_create_enumerator(this->active_tasks);
600 while (enumerator->enumerate(enumerator, &task))
c60c7694 601 {
f1f09810
MW
602 switch (task->build(task, message))
603 {
604 case SUCCESS:
605 /* task completed, remove it */
6207fadb 606 array_remove_at(this->active_tasks, enumerator);
f1f09810
MW
607 task->destroy(task);
608 break;
609 case NEED_MORE:
610 /* processed, but task needs another exchange */
611 break;
612 case FAILED:
613 default:
bee6515a 614 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
bb389973
TB
615 if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING &&
616 this->ike_sa->get_state(this->ike_sa) != IKE_REKEYED)
977ec0c3
MW
617 {
618 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
619 }
620 /* FALL */
621 case DESTROY_ME:
f1f09810 622 /* critical failure, destroy IKE_SA */
e2630434 623 enumerator->destroy(enumerator);
c60c7694 624 message->destroy(message);
0f33e826 625 flush(this);
f1f09810
MW
626 return DESTROY_ME;
627 }
c60c7694 628 }
e2630434 629 enumerator->destroy(enumerator);
7daf5226 630
394eb35b
MW
631 /* update exchange type if a task changed it */
632 this->initiating.type = message->get_exchange_type(message);
52bd3b8e
MW
633 if (this->initiating.type == EXCHANGE_TYPE_UNDEFINED)
634 {
635 message->destroy(message);
034a4629 636 return initiate(this);
52bd3b8e 637 }
7daf5226 638
b678d9e1 639 if (!generate_message(this, message, &this->initiating.packets))
c60c7694 640 {
f1f09810 641 /* message generation failed. There is nothing more to do than to
c60c7694 642 * close the SA */
f1f09810 643 message->destroy(message);
0f33e826 644 flush(this);
977ec0c3 645 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
f1f09810 646 return DESTROY_ME;
5474dc65 647 }
f1f09810 648 message->destroy(message);
7daf5226 649
6207fadb
MW
650 array_compress(this->active_tasks);
651 array_compress(this->queued_tasks);
652
c60c7694
MW
653 return retransmit(this, this->initiating.mid);
654}
655
656/**
657 * handle an incoming response message
658 */
659static status_t process_response(private_task_manager_t *this,
660 message_t *message)
661{
e2630434 662 enumerator_t *enumerator;
c60c7694 663 task_t *task;
7daf5226 664
c60c7694
MW
665 if (message->get_exchange_type(message) != this->initiating.type)
666 {
667 DBG1(DBG_IKE, "received %N response, but expected %N",
668 exchange_type_names, message->get_exchange_type(message),
669 exchange_type_names, this->initiating.type);
977ec0c3 670 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
c60c7694
MW
671 return DESTROY_ME;
672 }
7daf5226 673
4b836193
TB
674 enumerator = array_create_enumerator(this->active_tasks);
675 while (enumerator->enumerate(enumerator, &task))
676 {
677 if (!task->pre_process)
678 {
679 continue;
680 }
681 switch (task->pre_process(task, message))
682 {
683 case SUCCESS:
684 break;
685 case FAILED:
686 default:
687 /* just ignore the message */
688 DBG1(DBG_IKE, "ignore invalid %N response",
689 exchange_type_names, message->get_exchange_type(message));
690 enumerator->destroy(enumerator);
691 return SUCCESS;
692 case DESTROY_ME:
693 /* critical failure, destroy IKE_SA */
694 enumerator->destroy(enumerator);
695 return DESTROY_ME;
696 }
697 }
698 enumerator->destroy(enumerator);
699
bd71ba0f
TB
700 if (this->initiating.retransmitted)
701 {
702 packet_t *packet = NULL;
703 array_get(this->initiating.packets, 0, &packet);
704 charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_CLEARED, packet);
705 }
706
17d92e97
MW
707 /* catch if we get resetted while processing */
708 this->reset = FALSE;
6207fadb
MW
709 enumerator = array_create_enumerator(this->active_tasks);
710 while (enumerator->enumerate(enumerator, &task))
c60c7694 711 {
f1f09810
MW
712 switch (task->process(task, message))
713 {
714 case SUCCESS:
715 /* task completed, remove it */
6207fadb 716 array_remove_at(this->active_tasks, enumerator);
f1f09810
MW
717 task->destroy(task);
718 break;
719 case NEED_MORE:
720 /* processed, but task needs another exchange */
721 break;
722 case FAILED:
723 default:
977ec0c3
MW
724 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
725 /* FALL */
726 case DESTROY_ME:
f1f09810 727 /* critical failure, destroy IKE_SA */
6207fadb 728 array_remove_at(this->active_tasks, enumerator);
e2630434 729 enumerator->destroy(enumerator);
394eb35b 730 task->destroy(task);
f1f09810
MW
731 return DESTROY_ME;
732 }
733 if (this->reset)
734 { /* start all over again if we were reset */
735 this->reset = FALSE;
e2630434 736 enumerator->destroy(enumerator);
9560a316 737 return initiate(this);
484a06bc 738 }
c60c7694 739 }
e2630434 740 enumerator->destroy(enumerator);
7daf5226 741
c60c7694 742 this->initiating.mid++;
2540992a 743 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
b678d9e1 744 clear_packets(this->initiating.packets);
7daf5226 745
6207fadb
MW
746 array_compress(this->active_tasks);
747
9560a316 748 return initiate(this);
c60c7694
MW
749}
750
195ada0b
MW
751/**
752 * handle exchange collisions
753 */
3ced6b51 754static bool handle_collisions(private_task_manager_t *this, task_t *task)
195ada0b 755{
e2630434 756 enumerator_t *enumerator;
195ada0b
MW
757 task_t *active;
758 task_type_t type;
7daf5226 759
195ada0b 760 type = task->get_type(task);
7daf5226 761
4315f5c8 762 /* do we have to check */
a09972df
MW
763 if (type == TASK_IKE_REKEY || type == TASK_CHILD_REKEY ||
764 type == TASK_CHILD_DELETE || type == TASK_IKE_DELETE ||
765 type == TASK_IKE_REAUTH)
4315f5c8 766 {
f1f09810 767 /* find an exchange collision, and notify these tasks */
6207fadb
MW
768 enumerator = array_create_enumerator(this->active_tasks);
769 while (enumerator->enumerate(enumerator, &active))
f1f09810
MW
770 {
771 switch (active->get_type(active))
772 {
a09972df
MW
773 case TASK_IKE_REKEY:
774 if (type == TASK_IKE_REKEY || type == TASK_IKE_DELETE ||
775 type == TASK_IKE_REAUTH)
f1f09810
MW
776 {
777 ike_rekey_t *rekey = (ike_rekey_t*)active;
778 rekey->collide(rekey, task);
779 break;
780 }
781 continue;
a09972df
MW
782 case TASK_CHILD_REKEY:
783 if (type == TASK_CHILD_REKEY || type == TASK_CHILD_DELETE)
f1f09810
MW
784 {
785 child_rekey_t *rekey = (child_rekey_t*)active;
786 rekey->collide(rekey, task);
787 break;
788 }
789 continue;
790 default:
791 continue;
792 }
e2630434 793 enumerator->destroy(enumerator);
3ced6b51 794 return TRUE;
4315f5c8 795 }
e2630434 796 enumerator->destroy(enumerator);
195ada0b 797 }
3ced6b51 798 return FALSE;
195ada0b
MW
799}
800
c60c7694
MW
801/**
802 * build a response depending on the "passive" task list
803 */
5474dc65 804static status_t build_response(private_task_manager_t *this, message_t *request)
c60c7694 805{
e2630434 806 enumerator_t *enumerator;
c60c7694
MW
807 task_t *task;
808 message_t *message;
5474dc65 809 host_t *me, *other;
b24be296 810 bool delete = FALSE, hook = FALSE;
2ec3552f 811 ike_sa_id_t *id = NULL;
b12c53ce 812 uint64_t responder_spi = 0;
b678d9e1 813 bool result;
7daf5226 814
5474dc65
MW
815 me = request->get_destination(request);
816 other = request->get_source(request);
7daf5226 817
4ed52db2 818 message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
5474dc65
MW
819 message->set_exchange_type(message, request->get_exchange_type(request));
820 /* send response along the path the request came in */
821 message->set_source(message, me->clone(me));
822 message->set_destination(message, other->clone(other));
c60c7694
MW
823 message->set_message_id(message, this->responding.mid);
824 message->set_request(message, FALSE);
7daf5226 825
6207fadb 826 enumerator = array_create_enumerator(this->passive_tasks);
e2630434 827 while (enumerator->enumerate(enumerator, (void*)&task))
c60c7694 828 {
f1f09810
MW
829 switch (task->build(task, message))
830 {
831 case SUCCESS:
832 /* task completed, remove it */
6207fadb 833 array_remove_at(this->passive_tasks, enumerator);
3ced6b51
MW
834 if (!handle_collisions(this, task))
835 {
836 task->destroy(task);
837 }
838 break;
f1f09810
MW
839 case NEED_MORE:
840 /* processed, but task needs another exchange */
3ced6b51
MW
841 if (handle_collisions(this, task))
842 {
6207fadb 843 array_remove_at(this->passive_tasks, enumerator);
3ced6b51 844 }
f1f09810
MW
845 break;
846 case FAILED:
847 default:
b24be296
MW
848 hook = TRUE;
849 /* FALL */
850 case DESTROY_ME:
f1f09810 851 /* destroy IKE_SA, but SEND response first */
1cca2070
TB
852 if (handle_collisions(this, task))
853 {
854 array_remove_at(this->passive_tasks, enumerator);
855 }
f1f09810
MW
856 delete = TRUE;
857 break;
858 }
859 if (delete)
860 {
861 break;
862 }
c60c7694 863 }
e2630434 864 enumerator->destroy(enumerator);
7daf5226 865
2ec3552f
TB
866 /* RFC 5996, section 2.6 mentions that in the event of a failure during
867 * IKE_SA_INIT the responder's SPI will be 0 in the response, while it
868 * actually explicitly allows it to be non-zero. Since we use the responder
869 * SPI to create hashes in the IKE_SA manager we can only set the SPI to
870 * zero temporarily, otherwise checking the SA in would fail. */
5474dc65 871 if (delete && request->get_exchange_type(request) == IKE_SA_INIT)
ddae0f96 872 {
2ec3552f
TB
873 id = this->ike_sa->get_id(this->ike_sa);
874 responder_spi = id->get_responder_spi(id);
ddae0f96
MW
875 id->set_responder_spi(id, 0);
876 }
7daf5226 877
c60c7694 878 /* message complete, send it */
b678d9e1
TB
879 clear_packets(this->responding.packets);
880 result = generate_message(this, message, &this->responding.packets);
c60c7694 881 message->destroy(message);
2ec3552f
TB
882 if (id)
883 {
884 id->set_responder_spi(id, responder_spi);
885 }
b678d9e1 886 if (!result)
c60c7694 887 {
977ec0c3 888 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
f1f09810 889 return DESTROY_ME;
c60c7694 890 }
7daf5226 891
b678d9e1 892 send_packets(this, this->responding.packets, NULL, NULL);
c60c7694
MW
893 if (delete)
894 {
b24be296
MW
895 if (hook)
896 {
897 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
898 }
c60c7694
MW
899 return DESTROY_ME;
900 }
6207fadb
MW
901
902 array_compress(this->passive_tasks);
903
c60c7694
MW
904 return SUCCESS;
905}
906
907/**
908 * handle an incoming request message
909 */
910static status_t process_request(private_task_manager_t *this,
911 message_t *message)
912{
a44bb934 913 enumerator_t *enumerator;
c60c7694 914 task_t *task = NULL;
c60c7694
MW
915 payload_t *payload;
916 notify_payload_t *notify;
4cb9d7a7 917 delete_payload_t *delete;
bb389973 918 ike_sa_state_t state;
7daf5226 919
6207fadb 920 if (array_count(this->passive_tasks) == 0)
0ce19b27 921 { /* create tasks depending on request type, if not already some queued */
bb389973 922 state = this->ike_sa->get_state(this->ike_sa);
0ce19b27 923 switch (message->get_exchange_type(message))
c60c7694 924 {
0ce19b27
MW
925 case IKE_SA_INIT:
926 {
a5a0bcaa 927 task = (task_t*)ike_vendor_create(this->ike_sa, FALSE);
6207fadb 928 array_insert(this->passive_tasks, ARRAY_TAIL, task);
347488bd 929 task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
6207fadb 930 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 931 task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
6207fadb 932 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 933 task = (task_t*)ike_cert_pre_create(this->ike_sa, FALSE);
6207fadb 934 array_insert(this->passive_tasks, ARRAY_TAIL, task);
484a06bc 935#ifdef ME
0ce19b27 936 task = (task_t*)ike_me_create(this->ike_sa, FALSE);
6207fadb 937 array_insert(this->passive_tasks, ARRAY_TAIL, task);
dc04b7c7 938#endif /* ME */
0ce19b27 939 task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
6207fadb 940 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 941 task = (task_t*)ike_cert_post_create(this->ike_sa, FALSE);
6207fadb 942 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 943 task = (task_t*)ike_config_create(this->ike_sa, FALSE);
6207fadb 944 array_insert(this->passive_tasks, ARRAY_TAIL, task);
f669f453
MW
945 task = (task_t*)child_create_create(this->ike_sa, NULL, FALSE,
946 NULL, NULL);
6207fadb 947 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 948 task = (task_t*)ike_auth_lifetime_create(this->ike_sa, FALSE);
6207fadb 949 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 950 task = (task_t*)ike_mobike_create(this->ike_sa, FALSE);
6207fadb 951 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27
MW
952 break;
953 }
954 case CREATE_CHILD_SA:
955 { /* FIXME: we should prevent this on mediation connections */
956 bool notify_found = FALSE, ts_found = FALSE;
85030771 957
bb389973
TB
958 if (state == IKE_CREATED ||
959 state == IKE_CONNECTING)
85030771
MW
960 {
961 DBG1(DBG_IKE, "received CREATE_CHILD_SA request for "
962 "unestablished IKE_SA, rejected");
963 return FAILED;
964 }
965
0ce19b27
MW
966 enumerator = message->create_payload_enumerator(message);
967 while (enumerator->enumerate(enumerator, &payload))
c60c7694 968 {
0ce19b27 969 switch (payload->get_type(payload))
c60c7694 970 {
3ecfc83c 971 case PLV2_NOTIFY:
0ce19b27
MW
972 { /* if we find a rekey notify, its CHILD_SA rekeying */
973 notify = (notify_payload_t*)payload;
974 if (notify->get_notify_type(notify) == REKEY_SA &&
975 (notify->get_protocol_id(notify) == PROTO_AH ||
976 notify->get_protocol_id(notify) == PROTO_ESP))
977 {
978 notify_found = TRUE;
979 }
980 break;
c60c7694 981 }
3ecfc83c
MW
982 case PLV2_TS_INITIATOR:
983 case PLV2_TS_RESPONDER:
0ce19b27
MW
984 { /* if we don't find a TS, its IKE rekeying */
985 ts_found = TRUE;
986 break;
987 }
988 default:
989 break;
c60c7694 990 }
c60c7694 991 }
0ce19b27 992 enumerator->destroy(enumerator);
7daf5226 993
0ce19b27 994 if (ts_found)
c60c7694 995 {
0ce19b27
MW
996 if (notify_found)
997 {
998 task = (task_t*)child_rekey_create(this->ike_sa,
999 PROTO_NONE, 0);
1000 }
1001 else
1002 {
f669f453
MW
1003 task = (task_t*)child_create_create(this->ike_sa, NULL,
1004 FALSE, NULL, NULL);
0ce19b27 1005 }
c60c7694
MW
1006 }
1007 else
1008 {
0ce19b27 1009 task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
c60c7694 1010 }
6207fadb 1011 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 1012 break;
c60c7694 1013 }
0ce19b27 1014 case INFORMATIONAL:
c60c7694 1015 {
0ce19b27
MW
1016 enumerator = message->create_payload_enumerator(message);
1017 while (enumerator->enumerate(enumerator, &payload))
c60c7694 1018 {
0ce19b27 1019 switch (payload->get_type(payload))
4cb9d7a7 1020 {
3ecfc83c 1021 case PLV2_NOTIFY:
4cb9d7a7 1022 {
0ce19b27 1023 notify = (notify_payload_t*)payload;
bb389973
TB
1024 if (state == IKE_REKEYED)
1025 {
1026 DBG1(DBG_IKE, "received unexpected notify %N "
1027 "for rekeyed IKE_SA, ignored",
1028 notify_type_names,
1029 notify->get_notify_type(notify));
1030 break;
1031 }
0ce19b27
MW
1032 switch (notify->get_notify_type(notify))
1033 {
1034 case ADDITIONAL_IP4_ADDRESS:
1035 case ADDITIONAL_IP6_ADDRESS:
1036 case NO_ADDITIONAL_ADDRESSES:
1037 case UPDATE_SA_ADDRESSES:
1038 case NO_NATS_ALLOWED:
1039 case UNACCEPTABLE_ADDRESSES:
1040 case UNEXPECTED_NAT_DETECTED:
1041 case COOKIE2:
1042 case NAT_DETECTION_SOURCE_IP:
1043 case NAT_DETECTION_DESTINATION_IP:
1044 task = (task_t*)ike_mobike_create(
1045 this->ike_sa, FALSE);
1046 break;
1047 case AUTH_LIFETIME:
1048 task = (task_t*)ike_auth_lifetime_create(
1049 this->ike_sa, FALSE);
1050 break;
ca74bf7a
MW
1051 case AUTHENTICATION_FAILED:
1052 /* initiator failed to authenticate us.
1053 * We use ike_delete to handle this, which
1054 * invokes all the required hooks. */
1055 task = (task_t*)ike_delete_create(
1056 this->ike_sa, FALSE);
0840385b
TB
1057 break;
1058 case REDIRECT:
1059 task = (task_t*)ike_redirect_create(
1060 this->ike_sa, NULL);
1061 break;
0ce19b27
MW
1062 default:
1063 break;
1064 }
1065 break;
4cb9d7a7 1066 }
3ecfc83c 1067 case PLV2_DELETE:
4cb9d7a7 1068 {
0ce19b27
MW
1069 delete = (delete_payload_t*)payload;
1070 if (delete->get_protocol_id(delete) == PROTO_IKE)
1071 {
1072 task = (task_t*)ike_delete_create(this->ike_sa,
1073 FALSE);
1074 }
1075 else
1076 {
1077 task = (task_t*)child_delete_create(this->ike_sa,
3a925f74 1078 PROTO_NONE, 0, FALSE);
0ce19b27
MW
1079 }
1080 break;
4cb9d7a7 1081 }
0ce19b27
MW
1082 default:
1083 break;
4cb9d7a7 1084 }
0ce19b27
MW
1085 if (task)
1086 {
4cb9d7a7 1087 break;
0ce19b27 1088 }
c60c7694 1089 }
0ce19b27 1090 enumerator->destroy(enumerator);
7daf5226 1091
0ce19b27 1092 if (task == NULL)
3bc62fe7 1093 {
0ce19b27 1094 task = (task_t*)ike_dpd_create(FALSE);
3bc62fe7 1095 }
6207fadb 1096 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 1097 break;
c60c7694 1098 }
0ce19b27
MW
1099#ifdef ME
1100 case ME_CONNECT:
c60c7694 1101 {
0ce19b27 1102 task = (task_t*)ike_me_create(this->ike_sa, FALSE);
6207fadb 1103 array_insert(this->passive_tasks, ARRAY_TAIL, task);
c60c7694 1104 }
dc04b7c7 1105#endif /* ME */
0ce19b27
MW
1106 default:
1107 break;
1108 }
c60c7694 1109 }
7daf5226 1110
fb7cc16d
TB
1111 enumerator = array_create_enumerator(this->passive_tasks);
1112 while (enumerator->enumerate(enumerator, &task))
1113 {
1114 if (!task->pre_process)
1115 {
1116 continue;
1117 }
1118 switch (task->pre_process(task, message))
1119 {
1120 case SUCCESS:
1121 break;
1122 case FAILED:
1123 default:
1124 /* just ignore the message */
1125 DBG1(DBG_IKE, "ignore invalid %N request",
1126 exchange_type_names, message->get_exchange_type(message));
1127 enumerator->destroy(enumerator);
1128 switch (message->get_exchange_type(message))
1129 {
1130 case IKE_SA_INIT:
1131 /* no point in keeping the SA when it was created with
1132 * an invalid IKE_SA_INIT message */
1133 return DESTROY_ME;
1134 default:
1135 /* remove tasks we queued for this request */
1136 flush_queue(this, TASK_QUEUE_PASSIVE);
1137 /* fall-through */
1138 case IKE_AUTH:
1139 return NEED_MORE;
1140 }
1141 case DESTROY_ME:
1142 /* critical failure, destroy IKE_SA */
1143 enumerator->destroy(enumerator);
1144 return DESTROY_ME;
1145 }
1146 }
1147 enumerator->destroy(enumerator);
1148
c60c7694 1149 /* let the tasks process the message */
6207fadb 1150 enumerator = array_create_enumerator(this->passive_tasks);
e2630434 1151 while (enumerator->enumerate(enumerator, (void*)&task))
c60c7694 1152 {
f1f09810
MW
1153 switch (task->process(task, message))
1154 {
1155 case SUCCESS:
1156 /* task completed, remove it */
6207fadb 1157 array_remove_at(this->passive_tasks, enumerator);
f1f09810
MW
1158 task->destroy(task);
1159 break;
1160 case NEED_MORE:
1161 /* processed, but task needs at least another call to build() */
1162 break;
1163 case FAILED:
1164 default:
977ec0c3
MW
1165 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
1166 /* FALL */
1167 case DESTROY_ME:
f1f09810 1168 /* critical failure, destroy IKE_SA */
6207fadb 1169 array_remove_at(this->passive_tasks, enumerator);
e2630434 1170 enumerator->destroy(enumerator);
394eb35b 1171 task->destroy(task);
f1f09810
MW
1172 return DESTROY_ME;
1173 }
c60c7694 1174 }
e2630434 1175 enumerator->destroy(enumerator);
7daf5226 1176
5474dc65 1177 return build_response(this, message);
c60c7694
MW
1178}
1179
68c6863b
TB
1180METHOD(task_manager_t, incr_mid, void,
1181 private_task_manager_t *this, bool initiate)
1182{
1183 if (initiate)
1184 {
1185 this->initiating.mid++;
1186 }
1187 else
1188 {
1189 this->responding.mid++;
1190 }
1191}
1192
b678d9e1
TB
1193/**
1194 * Handle the given IKE fragment, if it is one.
1195 *
1196 * Returns SUCCESS if the message is not a fragment, and NEED_MORE if it was
1197 * handled properly. Error states are returned if the fragment was invalid or
1198 * the reassembled message could not have been processed properly.
1199 */
1200static status_t handle_fragment(private_task_manager_t *this,
1201 message_t **defrag, message_t *msg)
1202{
1203 message_t *reassembled;
1204 status_t status;
1205
1206 if (!msg->get_payload(msg, PLV2_FRAGMENT))
1207 {
1208 return SUCCESS;
1209 }
1210 if (!*defrag)
1211 {
1212 *defrag = message_create_defrag(msg);
1213 if (!*defrag)
1214 {
1215 return FAILED;
1216 }
1217 }
1218 status = (*defrag)->add_fragment(*defrag, msg);
1219 if (status == SUCCESS)
1220 {
1221 /* reinject the reassembled message */
1222 reassembled = *defrag;
1223 *defrag = NULL;
1224 status = this->ike_sa->process_message(this->ike_sa, reassembled);
1225 if (status == SUCCESS)
1226 {
1227 /* avoid processing the last fragment */
1228 status = NEED_MORE;
1229 }
1230 reassembled->destroy(reassembled);
1231 }
1232 return status;
1233}
1234
68c6863b
TB
1235/**
1236 * Send a notify back to the sender
1237 */
1238static void send_notify_response(private_task_manager_t *this,
1239 message_t *request, notify_type_t type,
1240 chunk_t data)
1241{
1242 message_t *response;
1243 packet_t *packet;
1244 host_t *me, *other;
1245
1246 response = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
1247 response->set_exchange_type(response, request->get_exchange_type(request));
1248 response->set_request(response, FALSE);
1249 response->set_message_id(response, request->get_message_id(request));
1250 response->add_notify(response, FALSE, type, data);
1251 me = this->ike_sa->get_my_host(this->ike_sa);
1252 if (me->is_anyaddr(me))
1253 {
1254 me = request->get_destination(request);
1255 this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
1256 }
1257 other = this->ike_sa->get_other_host(this->ike_sa);
1258 if (other->is_anyaddr(other))
1259 {
1260 other = request->get_source(request);
1261 this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
1262 }
1263 response->set_source(response, me->clone(me));
1264 response->set_destination(response, other->clone(other));
1265 if (this->ike_sa->generate_message(this->ike_sa, response,
1266 &packet) == SUCCESS)
1267 {
1268 charon->sender->send(charon->sender, packet);
1269 }
1270 response->destroy(response);
1271}
1272
1273/**
1274 * Parse the given message and verify that it is valid.
1275 */
1276static status_t parse_message(private_task_manager_t *this, message_t *msg)
1277{
1278 status_t status;
b12c53ce 1279 uint8_t type = 0;
68c6863b 1280
68c6863b
TB
1281 status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
1282
1283 if (status == SUCCESS)
1284 { /* check for unsupported critical payloads */
1285 enumerator_t *enumerator;
1286 unknown_payload_t *unknown;
1287 payload_t *payload;
1288
1289 enumerator = msg->create_payload_enumerator(msg);
1290 while (enumerator->enumerate(enumerator, &payload))
1291 {
15076474 1292 if (payload->get_type(payload) == PL_UNKNOWN)
68c6863b 1293 {
15076474
TB
1294 unknown = (unknown_payload_t*)payload;
1295 if (unknown->is_critical(unknown))
1296 {
1297 type = unknown->get_type(unknown);
1298 DBG1(DBG_ENC, "payload type %N is not supported, "
1299 "but its critical!", payload_type_names, type);
1300 status = NOT_SUPPORTED;
1301 break;
1302 }
68c6863b
TB
1303 }
1304 }
1305 enumerator->destroy(enumerator);
1306 }
1307
1308 if (status != SUCCESS)
1309 {
e6732003
TB
1310 bool is_request = msg->get_request(msg);
1311
1312 switch (status)
68c6863b 1313 {
e6732003
TB
1314 case NOT_SUPPORTED:
1315 DBG1(DBG_IKE, "critical unknown payloads found");
1316 if (is_request)
1317 {
1318 send_notify_response(this, msg,
1319 UNSUPPORTED_CRITICAL_PAYLOAD,
1320 chunk_from_thing(type));
1321 incr_mid(this, FALSE);
1322 }
1323 break;
1324 case PARSE_ERROR:
1325 DBG1(DBG_IKE, "message parsing failed");
1326 if (is_request)
1327 {
1328 send_notify_response(this, msg,
1329 INVALID_SYNTAX, chunk_empty);
1330 incr_mid(this, FALSE);
1331 }
1332 break;
1333 case VERIFY_ERROR:
1334 DBG1(DBG_IKE, "message verification failed");
1335 if (is_request)
1336 {
1337 send_notify_response(this, msg,
1338 INVALID_SYNTAX, chunk_empty);
1339 incr_mid(this, FALSE);
1340 }
1341 break;
1342 case FAILED:
1343 DBG1(DBG_IKE, "integrity check failed");
1344 /* ignored */
1345 break;
1346 case INVALID_STATE:
1347 DBG1(DBG_IKE, "found encrypted message, but no keys available");
1348 default:
1349 break;
68c6863b
TB
1350 }
1351 DBG1(DBG_IKE, "%N %s with message ID %d processing failed",
1352 exchange_type_names, msg->get_exchange_type(msg),
1353 is_request ? "request" : "response",
1354 msg->get_message_id(msg));
1355
418f4bc7
MW
1356 charon->bus->alert(charon->bus, ALERT_PARSE_ERROR_BODY, msg, status);
1357
68c6863b
TB
1358 if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED)
1359 { /* invalid initiation attempt, close SA */
1360 return DESTROY_ME;
1361 }
1362 }
1363 return status;
1364}
1365
1366
9560a316
MW
1367METHOD(task_manager_t, process_message, status_t,
1368 private_task_manager_t *this, message_t *msg)
c60c7694 1369{
8ba805f4 1370 host_t *me, *other;
68c6863b 1371 status_t status;
b12c53ce 1372 uint32_t mid;
4dc89780 1373 bool schedule_delete_job = FALSE;
bb389973
TB
1374 ike_sa_state_t state;
1375 exchange_type_t type;
8ba805f4 1376
47b8f6ef 1377 charon->bus->message(charon->bus, msg, TRUE, FALSE);
68c6863b
TB
1378 status = parse_message(this, msg);
1379 if (status != SUCCESS)
1380 {
1381 return status;
1382 }
1383
8ba805f4
MW
1384 me = msg->get_destination(msg);
1385 other = msg->get_source(msg);
7daf5226 1386
68c6863b
TB
1387 /* if this IKE_SA is virgin, we check for a config */
1388 if (this->ike_sa->get_ike_cfg(this->ike_sa) == NULL)
1389 {
68c6863b 1390 ike_cfg_t *ike_cfg;
4dc89780 1391
79101163
MW
1392 ike_cfg = charon->backends->get_ike_cfg(charon->backends,
1393 me, other, IKEV2);
68c6863b
TB
1394 if (ike_cfg == NULL)
1395 {
1396 /* no config found for these hosts, destroy */
1397 DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
1398 me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
1399 send_notify_response(this, msg,
1400 NO_PROPOSAL_CHOSEN, chunk_empty);
1401 return DESTROY_ME;
1402 }
1403 this->ike_sa->set_ike_cfg(this->ike_sa, ike_cfg);
1404 ike_cfg->destroy(ike_cfg);
1405 /* add a timeout if peer does not establish it completely */
4dc89780 1406 schedule_delete_job = TRUE;
68c6863b
TB
1407 }
1408 this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
1409 time_monotonic(NULL));
1410
1411 mid = msg->get_message_id(msg);
c60c7694
MW
1412 if (msg->get_request(msg))
1413 {
1414 if (mid == this->responding.mid)
1415 {
bb389973
TB
1416 /* reject initial messages if not received in specific states,
1417 * after rekeying we only expect a DELETE in an INFORMATIONAL */
1418 type = msg->get_exchange_type(msg);
1419 state = this->ike_sa->get_state(this->ike_sa);
1420 if ((type == IKE_SA_INIT && state != IKE_CREATED) ||
1421 (type == IKE_AUTH && state != IKE_CONNECTING) ||
1422 (state == IKE_REKEYED && type != INFORMATIONAL))
cdf75a39 1423 {
dd0ebb54 1424 DBG1(DBG_IKE, "ignoring %N in IKE_SA state %N",
bb389973 1425 exchange_type_names, type, ike_sa_state_names, state);
dd0ebb54 1426 return FAILED;
cdf75a39 1427 }
561f94ae
TB
1428 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
1429 { /* with MOBIKE, we do no implicit updates */
1430 this->ike_sa->update_hosts(this->ike_sa, me, other, mid == 1);
cd26eedc 1431 }
b678d9e1
TB
1432 status = handle_fragment(this, &this->responding.defrag, msg);
1433 if (status != SUCCESS)
1434 {
1435 return status;
1436 }
47b8f6ef 1437 charon->bus->message(charon->bus, msg, TRUE, TRUE);
c146c3c4
MW
1438 if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
1439 { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
1440 return SUCCESS;
1441 }
fb7cc16d 1442 switch (process_request(this, msg))
c60c7694 1443 {
fb7cc16d
TB
1444 case SUCCESS:
1445 this->responding.mid++;
1446 break;
1447 case NEED_MORE:
1448 break;
1449 default:
1450 flush(this);
1451 return DESTROY_ME;
c60c7694 1452 }
c60c7694 1453 }
b678d9e1
TB
1454 else if ((mid == this->responding.mid - 1) &&
1455 array_count(this->responding.packets))
c60c7694 1456 {
b678d9e1
TB
1457 status = handle_fragment(this, &this->responding.defrag, msg);
1458 if (status != SUCCESS)
1459 {
1460 return status;
1461 }
c60c7694 1462 DBG1(DBG_IKE, "received retransmit of request with ID %d, "
b9b8a98f 1463 "retransmitting response", mid);
3c79b7b7 1464 charon->bus->alert(charon->bus, ALERT_RETRANSMIT_RECEIVE, msg);
b678d9e1
TB
1465 send_packets(this, this->responding.packets,
1466 msg->get_destination(msg), msg->get_source(msg));
c60c7694
MW
1467 }
1468 else
1469 {
278396b6 1470 DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
c60c7694
MW
1471 mid, this->responding.mid);
1472 }
1473 }
1474 else
1475 {
1476 if (mid == this->initiating.mid)
1477 {
cd26eedc
TB
1478 if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED ||
1479 this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING ||
1480 msg->get_exchange_type(msg) != IKE_SA_INIT)
1dd58b0e 1481 { /* only do updates based on verified messages (or initial ones) */
cd26eedc 1482 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
561f94ae
TB
1483 { /* with MOBIKE, we do no implicit updates. we force an
1484 * update of the local address on IKE_SA_INIT, but never
1485 * for the remote address */
1486 this->ike_sa->update_hosts(this->ike_sa, me, NULL, mid == 0);
1487 this->ike_sa->update_hosts(this->ike_sa, NULL, other, FALSE);
cd26eedc
TB
1488 }
1489 }
b678d9e1
TB
1490 status = handle_fragment(this, &this->initiating.defrag, msg);
1491 if (status != SUCCESS)
1492 {
1493 return status;
1494 }
47b8f6ef 1495 charon->bus->message(charon->bus, msg, TRUE, TRUE);
c146c3c4
MW
1496 if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
1497 { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
1498 return SUCCESS;
1499 }
c60c7694
MW
1500 if (process_response(this, msg) != SUCCESS)
1501 {
0f33e826 1502 flush(this);
c60c7694
MW
1503 return DESTROY_ME;
1504 }
1505 }
1506 else
1507 {
278396b6 1508 DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
c60c7694
MW
1509 mid, this->initiating.mid);
1510 return SUCCESS;
1511 }
1512 }
4dc89780
TB
1513
1514 if (schedule_delete_job)
1515 {
1516 ike_sa_id_t *ike_sa_id;
1517 job_t *job;
1518
1519 ike_sa_id = this->ike_sa->get_id(this->ike_sa);
1520 job = (job_t*)delete_ike_sa_job_create(ike_sa_id, FALSE);
1521 lib->scheduler->schedule_job(lib->scheduler, job,
1522 lib->settings->get_int(lib->settings,
1523 "%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
d223fe80 1524 lib->ns));
4dc89780 1525 }
c60c7694
MW
1526 return SUCCESS;
1527}
1528
9560a316
MW
1529METHOD(task_manager_t, queue_task, void,
1530 private_task_manager_t *this, task_t *task)
c60c7694 1531{
a09972df 1532 if (task->get_type(task) == TASK_IKE_MOBIKE)
f215e919 1533 { /* there is no need to queue more than one mobike task */
e2630434 1534 enumerator_t *enumerator;
f215e919 1535 task_t *current;
7daf5226 1536
6207fadb
MW
1537 enumerator = array_create_enumerator(this->queued_tasks);
1538 while (enumerator->enumerate(enumerator, &current))
f215e919 1539 {
a09972df 1540 if (current->get_type(current) == TASK_IKE_MOBIKE)
f215e919 1541 {
e2630434 1542 enumerator->destroy(enumerator);
f215e919
MW
1543 task->destroy(task);
1544 return;
1545 }
1546 }
e2630434 1547 enumerator->destroy(enumerator);
f215e919 1548 }
c60c7694 1549 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
b3a7ba14 1550 array_insert(this->queued_tasks, ARRAY_TAIL, task);
c60c7694
MW
1551}
1552
8573b18d
MW
1553/**
1554 * Check if a given task has been queued already
1555 */
1556static bool has_queued(private_task_manager_t *this, task_type_t type)
a60daa07 1557{
26eee421 1558 enumerator_t *enumerator;
8573b18d 1559 bool found = FALSE;
26eee421
MW
1560 task_t *task;
1561
6207fadb 1562 enumerator = array_create_enumerator(this->queued_tasks);
26eee421
MW
1563 while (enumerator->enumerate(enumerator, &task))
1564 {
8573b18d 1565 if (task->get_type(task) == type)
26eee421 1566 {
8573b18d
MW
1567 found = TRUE;
1568 break;
26eee421
MW
1569 }
1570 }
1571 enumerator->destroy(enumerator);
8573b18d
MW
1572 return found;
1573}
26eee421 1574
8573b18d
MW
1575METHOD(task_manager_t, queue_ike, void,
1576 private_task_manager_t *this)
1577{
1578 if (!has_queued(this, TASK_IKE_VENDOR))
a60daa07 1579 {
26eee421 1580 queue_task(this, (task_t*)ike_vendor_create(this->ike_sa, TRUE));
8573b18d
MW
1581 }
1582 if (!has_queued(this, TASK_IKE_INIT))
1583 {
26eee421 1584 queue_task(this, (task_t*)ike_init_create(this->ike_sa, TRUE, NULL));
8573b18d
MW
1585 }
1586 if (!has_queued(this, TASK_IKE_NATD))
1587 {
26eee421 1588 queue_task(this, (task_t*)ike_natd_create(this->ike_sa, TRUE));
a60daa07 1589 }
8573b18d 1590 if (!has_queued(this, TASK_IKE_CERT_PRE))
26eee421
MW
1591 {
1592 queue_task(this, (task_t*)ike_cert_pre_create(this->ike_sa, TRUE));
8573b18d
MW
1593 }
1594 if (!has_queued(this, TASK_IKE_AUTH))
1595 {
26eee421 1596 queue_task(this, (task_t*)ike_auth_create(this->ike_sa, TRUE));
8573b18d
MW
1597 }
1598 if (!has_queued(this, TASK_IKE_CERT_POST))
1599 {
26eee421 1600 queue_task(this, (task_t*)ike_cert_post_create(this->ike_sa, TRUE));
8573b18d
MW
1601 }
1602 if (!has_queued(this, TASK_IKE_CONFIG))
1603 {
26eee421 1604 queue_task(this, (task_t*)ike_config_create(this->ike_sa, TRUE));
8573b18d
MW
1605 }
1606 if (!has_queued(this, TASK_IKE_AUTH_LIFETIME))
1607 {
26eee421 1608 queue_task(this, (task_t*)ike_auth_lifetime_create(this->ike_sa, TRUE));
8573b18d
MW
1609 }
1610 if (!has_queued(this, TASK_IKE_MOBIKE))
1611 {
1612 peer_cfg_t *peer_cfg;
26eee421
MW
1613
1614 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
1615 if (peer_cfg->use_mobike(peer_cfg))
1616 {
1617 queue_task(this, (task_t*)ike_mobike_create(this->ike_sa, TRUE));
1618 }
8573b18d 1619 }
a60daa07 1620#ifdef ME
8573b18d
MW
1621 if (!has_queued(this, TASK_IKE_ME))
1622 {
26eee421 1623 queue_task(this, (task_t*)ike_me_create(this->ike_sa, TRUE));
26eee421 1624 }
8573b18d 1625#endif /* ME */
a60daa07
MW
1626}
1627
dab60d64
MW
1628METHOD(task_manager_t, queue_ike_rekey, void,
1629 private_task_manager_t *this)
1630{
1631 queue_task(this, (task_t*)ike_rekey_create(this->ike_sa, TRUE));
1632}
1633
349f7f24
MW
1634/**
1635 * Start reauthentication using make-before-break
1636 */
1637static void trigger_mbb_reauth(private_task_manager_t *this)
1638{
1639 enumerator_t *enumerator;
1640 child_sa_t *child_sa;
1641 child_cfg_t *cfg;
1642 ike_sa_t *new;
1643 host_t *host;
1644 task_t *task;
1645
1646 new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
1647 this->ike_sa->get_version(this->ike_sa), TRUE);
1648 if (!new)
1649 { /* shouldn't happen */
1650 return;
1651 }
1652
1653 new->set_peer_cfg(new, this->ike_sa->get_peer_cfg(this->ike_sa));
1654 host = this->ike_sa->get_other_host(this->ike_sa);
1655 new->set_other_host(new, host->clone(host));
1656 host = this->ike_sa->get_my_host(this->ike_sa);
1657 new->set_my_host(new, host->clone(host));
1658 enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
1659 while (enumerator->enumerate(enumerator, &host))
1660 {
1661 new->add_virtual_ip(new, TRUE, host);
1662 }
1663 enumerator->destroy(enumerator);
1664
1665 enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
1666 while (enumerator->enumerate(enumerator, &child_sa))
1667 {
1668 cfg = child_sa->get_config(child_sa);
1669 new->queue_task(new, &child_create_create(new, cfg->get_ref(cfg),
1670 FALSE, NULL, NULL)->task);
1671 }
1672 enumerator->destroy(enumerator);
1673
1674 enumerator = array_create_enumerator(this->queued_tasks);
1675 while (enumerator->enumerate(enumerator, &task))
1676 {
1677 if (task->get_type(task) == TASK_CHILD_CREATE)
1678 {
1679 task->migrate(task, new);
1680 new->queue_task(new, task);
1681 array_remove_at(this->queued_tasks, enumerator);
1682 }
1683 }
1684 enumerator->destroy(enumerator);
1685
f1cbacc5
TB
1686 /* suspend online revocation checking until the SA is established */
1687 new->set_condition(new, COND_ONLINE_VALIDATION_SUSPENDED, TRUE);
1688
349f7f24
MW
1689 if (new->initiate(new, NULL, 0, NULL, NULL) != DESTROY_ME)
1690 {
f1cbacc5 1691 new->queue_task(new, (task_t*)ike_verify_peer_cert_create(new));
3676023e
MW
1692 new->queue_task(new, (task_t*)ike_reauth_complete_create(new,
1693 this->ike_sa->get_id(this->ike_sa)));
349f7f24 1694 charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
349f7f24
MW
1695 }
1696 else
1697 {
1698 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
1699 DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
1700 }
1701 charon->bus->set_sa(charon->bus, this->ike_sa);
1702}
1703
cedb412e
MW
1704METHOD(task_manager_t, queue_ike_reauth, void,
1705 private_task_manager_t *this)
1706{
349f7f24
MW
1707 if (this->make_before_break)
1708 {
1709 return trigger_mbb_reauth(this);
1710 }
cedb412e
MW
1711 queue_task(this, (task_t*)ike_reauth_create(this->ike_sa));
1712}
1713
3ed148b3
MW
1714METHOD(task_manager_t, queue_ike_delete, void,
1715 private_task_manager_t *this)
1716{
1717 queue_task(this, (task_t*)ike_delete_create(this->ike_sa, TRUE));
1718}
1719
873df908
MW
1720METHOD(task_manager_t, queue_mobike, void,
1721 private_task_manager_t *this, bool roam, bool address)
1722{
1723 ike_mobike_t *mobike;
1724
1725 mobike = ike_mobike_create(this->ike_sa, TRUE);
1726 if (roam)
1727 {
1b17f647
TB
1728 enumerator_t *enumerator;
1729 task_t *current;
1730
873df908 1731 mobike->roam(mobike, address);
1b17f647
TB
1732
1733 /* enable path probing for a currently active MOBIKE task. This might
1734 * not be the case if an address appeared on a new interface while the
1735 * current address is not working but has not yet disappeared. */
1736 enumerator = array_create_enumerator(this->active_tasks);
1737 while (enumerator->enumerate(enumerator, &current))
1738 {
1739 if (current->get_type(current) == TASK_IKE_MOBIKE)
1740 {
1741 ike_mobike_t *active = (ike_mobike_t*)current;
1742 active->enable_probing(active);
1743 break;
1744 }
1745 }
1746 enumerator->destroy(enumerator);
873df908
MW
1747 }
1748 else
1749 {
1750 mobike->addresses(mobike);
1751 }
1752 queue_task(this, &mobike->task);
1753}
1754
fe43d9a2 1755METHOD(task_manager_t, queue_child, void,
b12c53ce 1756 private_task_manager_t *this, child_cfg_t *cfg, uint32_t reqid,
fe43d9a2
MW
1757 traffic_selector_t *tsi, traffic_selector_t *tsr)
1758{
1759 child_create_t *task;
1760
1761 task = child_create_create(this->ike_sa, cfg, FALSE, tsi, tsr);
1762 if (reqid)
1763 {
1764 task->use_reqid(task, reqid);
1765 }
1766 queue_task(this, &task->task);
1767}
1768
463a73cc 1769METHOD(task_manager_t, queue_child_rekey, void,
b12c53ce 1770 private_task_manager_t *this, protocol_id_t protocol, uint32_t spi)
463a73cc
MW
1771{
1772 queue_task(this, (task_t*)child_rekey_create(this->ike_sa, protocol, spi));
1773}
1774
83c5fda0 1775METHOD(task_manager_t, queue_child_delete, void,
b12c53ce 1776 private_task_manager_t *this, protocol_id_t protocol, uint32_t spi,
3a925f74 1777 bool expired)
83c5fda0 1778{
3a925f74
MW
1779 queue_task(this, (task_t*)child_delete_create(this->ike_sa,
1780 protocol, spi, expired));
83c5fda0
MW
1781}
1782
244d715d
MW
1783METHOD(task_manager_t, queue_dpd, void,
1784 private_task_manager_t *this)
1785{
1786 ike_mobike_t *mobike;
1787
1788 if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE) &&
1789 this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
1790 {
1791 /* use mobike enabled DPD to detect NAT mapping changes */
1792 mobike = ike_mobike_create(this->ike_sa, TRUE);
1793 mobike->dpd(mobike);
1794 queue_task(this, &mobike->task);
1795 }
1796 else
1797 {
1798 queue_task(this, (task_t*)ike_dpd_create(TRUE));
1799 }
1800}
1801
9560a316
MW
1802METHOD(task_manager_t, adopt_tasks, void,
1803 private_task_manager_t *this, task_manager_t *other_public)
c60c7694 1804{
9560a316 1805 private_task_manager_t *other = (private_task_manager_t*)other_public;
c60c7694 1806 task_t *task;
7daf5226 1807
c60c7694 1808 /* move queued tasks from other to this */
6207fadb 1809 while (array_remove(other->queued_tasks, ARRAY_TAIL, &task))
c60c7694 1810 {
e23a59f6 1811 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
c60c7694 1812 task->migrate(task, this->ike_sa);
6207fadb 1813 array_insert(this->queued_tasks, ARRAY_HEAD, task);
c60c7694 1814 }
c60c7694
MW
1815}
1816
68db844f
TB
1817/**
1818 * Migrates child-creating tasks from src to dst
1819 */
1820static void migrate_child_tasks(private_task_manager_t *this,
1821 array_t *src, array_t *dst)
1822{
1823 enumerator_t *enumerator;
1824 task_t *task;
1825
1826 enumerator = array_create_enumerator(src);
1827 while (enumerator->enumerate(enumerator, &task))
1828 {
1829 if (task->get_type(task) == TASK_CHILD_CREATE)
1830 {
1831 array_remove_at(src, enumerator);
1832 task->migrate(task, this->ike_sa);
1833 array_insert(dst, ARRAY_TAIL, task);
1834 }
1835 }
1836 enumerator->destroy(enumerator);
1837}
1838
1839METHOD(task_manager_t, adopt_child_tasks, void,
1840 private_task_manager_t *this, task_manager_t *other_public)
1841{
1842 private_task_manager_t *other = (private_task_manager_t*)other_public;
1843
1844 /* move active child tasks from other to this */
1845 migrate_child_tasks(this, other->active_tasks, this->queued_tasks);
1846 /* do the same for queued tasks */
1847 migrate_child_tasks(this, other->queued_tasks, this->queued_tasks);
1848}
1849
9560a316
MW
1850METHOD(task_manager_t, busy, bool,
1851 private_task_manager_t *this)
c60c7694 1852{
6207fadb 1853 return array_count(this->active_tasks) > 0;
c60c7694
MW
1854}
1855
9560a316 1856METHOD(task_manager_t, reset, void,
b12c53ce 1857 private_task_manager_t *this, uint32_t initiate, uint32_t respond)
c60c7694 1858{
31d0efd7 1859 enumerator_t *enumerator;
c60c7694 1860 task_t *task;
7daf5226 1861
c60c7694 1862 /* reset message counters and retransmit packets */
b678d9e1
TB
1863 clear_packets(this->responding.packets);
1864 clear_packets(this->initiating.packets);
1865 DESTROY_IF(this->responding.defrag);
1866 DESTROY_IF(this->initiating.defrag);
1867 this->responding.defrag = NULL;
1868 this->initiating.defrag = NULL;
b09ca747
MW
1869 if (initiate != UINT_MAX)
1870 {
1871 this->initiating.mid = initiate;
1872 }
1873 if (respond != UINT_MAX)
1874 {
1875 this->responding.mid = respond;
1876 }
1edf116c 1877 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
7daf5226 1878
7f1eb895 1879 /* reset queued tasks */
6207fadb 1880 enumerator = array_create_enumerator(this->queued_tasks);
31d0efd7 1881 while (enumerator->enumerate(enumerator, &task))
7f1eb895
TE
1882 {
1883 task->migrate(task, this->ike_sa);
7f1eb895 1884 }
31d0efd7
TE
1885 enumerator->destroy(enumerator);
1886
c60c7694 1887 /* reset active tasks */
6207fadb 1888 while (array_remove(this->active_tasks, ARRAY_TAIL, &task))
c60c7694
MW
1889 {
1890 task->migrate(task, this->ike_sa);
6207fadb 1891 array_insert(this->queued_tasks, ARRAY_HEAD, task);
c60c7694 1892 }
7daf5226 1893
17d92e97 1894 this->reset = TRUE;
c60c7694
MW
1895}
1896
665c18bd
MW
1897METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
1898 private_task_manager_t *this, task_queue_t queue)
1899{
1900 switch (queue)
1901 {
1902 case TASK_QUEUE_ACTIVE:
6207fadb 1903 return array_create_enumerator(this->active_tasks);
665c18bd 1904 case TASK_QUEUE_PASSIVE:
6207fadb 1905 return array_create_enumerator(this->passive_tasks);
665c18bd 1906 case TASK_QUEUE_QUEUED:
6207fadb 1907 return array_create_enumerator(this->queued_tasks);
665c18bd
MW
1908 default:
1909 return enumerator_create_empty();
1910 }
1911}
1912
9560a316
MW
1913METHOD(task_manager_t, destroy, void,
1914 private_task_manager_t *this)
c60c7694 1915{
0f33e826 1916 flush(this);
7daf5226 1917
6207fadb
MW
1918 array_destroy(this->active_tasks);
1919 array_destroy(this->queued_tasks);
1920 array_destroy(this->passive_tasks);
7daf5226 1921
b678d9e1
TB
1922 clear_packets(this->responding.packets);
1923 array_destroy(this->responding.packets);
1924 clear_packets(this->initiating.packets);
1925 array_destroy(this->initiating.packets);
1926 DESTROY_IF(this->responding.defrag);
1927 DESTROY_IF(this->initiating.defrag);
c60c7694
MW
1928 free(this);
1929}
1930
1931/*
1932 * see header file
1933 */
e69f7dcd 1934task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
c60c7694 1935{
9560a316
MW
1936 private_task_manager_t *this;
1937
1938 INIT(this,
1939 .public = {
e69f7dcd
MW
1940 .task_manager = {
1941 .process_message = _process_message,
1942 .queue_task = _queue_task,
a60daa07 1943 .queue_ike = _queue_ike,
dab60d64 1944 .queue_ike_rekey = _queue_ike_rekey,
cedb412e 1945 .queue_ike_reauth = _queue_ike_reauth,
3ed148b3 1946 .queue_ike_delete = _queue_ike_delete,
873df908 1947 .queue_mobike = _queue_mobike,
fe43d9a2 1948 .queue_child = _queue_child,
463a73cc 1949 .queue_child_rekey = _queue_child_rekey,
83c5fda0 1950 .queue_child_delete = _queue_child_delete,
244d715d 1951 .queue_dpd = _queue_dpd,
e69f7dcd
MW
1952 .initiate = _initiate,
1953 .retransmit = _retransmit,
1954 .incr_mid = _incr_mid,
1955 .reset = _reset,
1956 .adopt_tasks = _adopt_tasks,
68db844f 1957 .adopt_child_tasks = _adopt_child_tasks,
e69f7dcd
MW
1958 .busy = _busy,
1959 .create_task_enumerator = _create_task_enumerator,
b1908994 1960 .flush = _flush,
a5c79960 1961 .flush_queue = _flush_queue,
e69f7dcd
MW
1962 .destroy = _destroy,
1963 },
9560a316
MW
1964 },
1965 .ike_sa = ike_sa,
1966 .initiating.type = EXCHANGE_TYPE_UNDEFINED,
6207fadb
MW
1967 .queued_tasks = array_create(0, 0),
1968 .active_tasks = array_create(0, 0),
1969 .passive_tasks = array_create(0, 0),
9560a316 1970 .retransmit_tries = lib->settings->get_int(lib->settings,
d223fe80 1971 "%s.retransmit_tries", RETRANSMIT_TRIES, lib->ns),
9560a316 1972 .retransmit_timeout = lib->settings->get_double(lib->settings,
d223fe80 1973 "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, lib->ns),
9560a316 1974 .retransmit_base = lib->settings->get_double(lib->settings,
d223fe80 1975 "%s.retransmit_base", RETRANSMIT_BASE, lib->ns),
349f7f24
MW
1976 .make_before_break = lib->settings->get_bool(lib->settings,
1977 "%s.make_before_break", FALSE, lib->ns),
9560a316 1978 );
bc6ff2fc 1979
c60c7694
MW
1980 return &this->public;
1981}