]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/sa/ikev2/task_manager_v2.c
NEWS: mention xauth-radius backend in eap-radius plugin
[thirdparty/strongswan.git] / src / libcharon / sa / ikev2 / task_manager_v2.c
CommitLineData
c60c7694 1/*
68c6863b 2 * Copyright (C) 2007-2011 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>
15a682f4
MW
32#include <sa/ikev2/tasks/ike_delete.h>
33#include <sa/ikev2/tasks/ike_config.h>
34#include <sa/ikev2/tasks/ike_dpd.h>
35#include <sa/ikev2/tasks/ike_vendor.h>
36#include <sa/ikev2/tasks/child_create.h>
37#include <sa/ikev2/tasks/child_rekey.h>
38#include <sa/ikev2/tasks/child_delete.h>
c60c7694 39#include <encoding/payloads/delete_payload.h>
68c6863b 40#include <encoding/payloads/unknown_payload.h>
e0fe7651 41#include <processing/jobs/retransmit_job.h>
68c6863b 42#include <processing/jobs/delete_ike_sa_job.h>
c60c7694 43
dc04b7c7 44#ifdef ME
15a682f4 45#include <sa/ikev2/tasks/ike_me.h>
d5cc1758
TB
46#endif
47
c60c7694
MW
48typedef struct exchange_t exchange_t;
49
50/**
51 * An exchange in the air, used do detect and handle retransmission
52 */
53struct exchange_t {
7daf5226 54
c60c7694
MW
55 /**
56 * Message ID used for this transaction
57 */
58 u_int32_t mid;
7daf5226 59
c60c7694
MW
60 /**
61 * generated packet for retransmission
62 */
63 packet_t *packet;
64};
65
66typedef struct private_task_manager_t private_task_manager_t;
67
68/**
69 * private data of the task manager
70 */
71struct private_task_manager_t {
7daf5226 72
c60c7694
MW
73 /**
74 * public functions
75 */
e69f7dcd 76 task_manager_v2_t public;
7daf5226 77
c60c7694
MW
78 /**
79 * associated IKE_SA we are serving
80 */
81 ike_sa_t *ike_sa;
7daf5226 82
c60c7694
MW
83 /**
84 * Exchange we are currently handling as responder
85 */
86 struct {
87 /**
88 * Message ID of the exchange
89 */
90 u_int32_t mid;
7daf5226 91
c60c7694
MW
92 /**
93 * packet for retransmission
94 */
95 packet_t *packet;
7daf5226 96
c60c7694 97 } responding;
7daf5226 98
c60c7694
MW
99 /**
100 * Exchange we are currently handling as initiator
101 */
102 struct {
103 /**
104 * Message ID of the exchange
105 */
106 u_int32_t mid;
7daf5226 107
c60c7694
MW
108 /**
109 * how many times we have retransmitted so far
110 */
111 u_int retransmitted;
112
113 /**
114 * packet for retransmission
115 */
116 packet_t *packet;
7daf5226 117
c60c7694
MW
118 /**
119 * type of the initated exchange
120 */
121 exchange_type_t type;
7daf5226 122
c60c7694 123 } initiating;
7daf5226 124
c60c7694 125 /**
6207fadb 126 * Array of queued tasks not yet in action
c60c7694 127 */
6207fadb 128 array_t *queued_tasks;
7daf5226 129
c60c7694 130 /**
6207fadb 131 * Array of active tasks, initiated by ourselve
c60c7694 132 */
6207fadb 133 array_t *active_tasks;
7daf5226 134
c60c7694 135 /**
6207fadb 136 * Array of tasks initiated by peer
c60c7694 137 */
6207fadb 138 array_t *passive_tasks;
7daf5226 139
17d92e97 140 /**
484a06bc 141 * the task manager has been reset
17d92e97
MW
142 */
143 bool reset;
bc6ff2fc
MW
144
145 /**
146 * Number of times we retransmit messages before giving up
147 */
148 u_int retransmit_tries;
149
150 /**
151 * Retransmission timeout
152 */
153 double retransmit_timeout;
154
155 /**
156 * Base to calculate retransmission timeout
157 */
158 double retransmit_base;
c60c7694
MW
159};
160
a5c79960
MW
161METHOD(task_manager_t, flush_queue, void,
162 private_task_manager_t *this, task_queue_t queue)
163{
6207fadb 164 array_t *array;
a5c79960
MW
165 task_t *task;
166
167 switch (queue)
168 {
169 case TASK_QUEUE_ACTIVE:
6207fadb 170 array = this->active_tasks;
a5c79960
MW
171 break;
172 case TASK_QUEUE_PASSIVE:
6207fadb 173 array = this->passive_tasks;
a5c79960
MW
174 break;
175 case TASK_QUEUE_QUEUED:
6207fadb 176 array = this->queued_tasks;
a5c79960
MW
177 break;
178 default:
179 return;
180 }
6207fadb 181 while (array_remove(array, ARRAY_TAIL, &task))
a5c79960
MW
182 {
183 task->destroy(task);
184 }
185}
186
0f33e826
MW
187/**
188 * flush all tasks in the task manager
189 */
190static void flush(private_task_manager_t *this)
191{
a5c79960
MW
192 flush_queue(this, TASK_QUEUE_QUEUED);
193 flush_queue(this, TASK_QUEUE_PASSIVE);
194 flush_queue(this, TASK_QUEUE_ACTIVE);
0f33e826
MW
195}
196
c60c7694
MW
197/**
198 * move a task of a specific type from the queue to the active list
199 */
200static bool activate_task(private_task_manager_t *this, task_type_t type)
201{
e2630434 202 enumerator_t *enumerator;
c60c7694
MW
203 task_t *task;
204 bool found = FALSE;
7daf5226 205
6207fadb 206 enumerator = array_create_enumerator(this->queued_tasks);
e2630434 207 while (enumerator->enumerate(enumerator, (void**)&task))
c60c7694
MW
208 {
209 if (task->get_type(task) == type)
210 {
211 DBG2(DBG_IKE, " activating %N task", task_type_names, type);
6207fadb
MW
212 array_remove_at(this->queued_tasks, enumerator);
213 array_insert(this->active_tasks, ARRAY_TAIL, task);
c60c7694
MW
214 found = TRUE;
215 break;
216 }
217 }
e2630434 218 enumerator->destroy(enumerator);
c60c7694
MW
219 return found;
220}
221
9560a316
MW
222METHOD(task_manager_t, retransmit, status_t,
223 private_task_manager_t *this, u_int32_t message_id)
c60c7694 224{
a7d3b0e0 225 if (this->initiating.packet && message_id == this->initiating.mid)
c60c7694
MW
226 {
227 u_int32_t timeout;
228 job_t *job;
e2630434 229 enumerator_t *enumerator;
5474dc65
MW
230 packet_t *packet;
231 task_t *task;
f215e919 232 ike_mobike_t *mobike = NULL;
7daf5226 233
f215e919 234 /* check if we are retransmitting a MOBIKE routability check */
6207fadb 235 enumerator = array_create_enumerator(this->active_tasks);
e2630434 236 while (enumerator->enumerate(enumerator, (void*)&task))
5474dc65 237 {
a09972df 238 if (task->get_type(task) == TASK_IKE_MOBIKE)
5474dc65 239 {
f215e919
MW
240 mobike = (ike_mobike_t*)task;
241 if (!mobike->is_probing(mobike))
242 {
243 mobike = NULL;
244 }
5474dc65
MW
245 break;
246 }
247 }
e2630434 248 enumerator->destroy(enumerator);
f215e919
MW
249
250 if (mobike == NULL)
251 {
bc6ff2fc 252 if (this->initiating.retransmitted <= this->retransmit_tries)
f215e919 253 {
bc6ff2fc
MW
254 timeout = (u_int32_t)(this->retransmit_timeout * 1000.0 *
255 pow(this->retransmit_base, this->initiating.retransmitted));
f215e919
MW
256 }
257 else
258 {
259 DBG1(DBG_IKE, "giving up after %d retransmits",
260 this->initiating.retransmitted - 1);
3c79b7b7
MW
261 charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_TIMEOUT,
262 this->initiating.packet);
f215e919
MW
263 return DESTROY_ME;
264 }
7daf5226 265
f215e919
MW
266 if (this->initiating.retransmitted)
267 {
268 DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
269 this->initiating.retransmitted, message_id);
3c79b7b7
MW
270 charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND,
271 this->initiating.packet);
f215e919
MW
272 }
273 packet = this->initiating.packet->clone(this->initiating.packet);
387a6e6c 274 charon->sender->send(charon->sender, packet);
f215e919
MW
275 }
276 else
277 { /* for routeability checks, we use a more aggressive behavior */
278 if (this->initiating.retransmitted <= ROUTEABILITY_CHECK_TRIES)
279 {
280 timeout = ROUTEABILITY_CHECK_INTERVAL;
281 }
282 else
283 {
284 DBG1(DBG_IKE, "giving up after %d path probings",
285 this->initiating.retransmitted - 1);
286 return DESTROY_ME;
287 }
7daf5226 288
f215e919
MW
289 if (this->initiating.retransmitted)
290 {
291 DBG1(DBG_IKE, "path probing attempt %d",
292 this->initiating.retransmitted);
293 }
387a6e6c 294 mobike->transmit(mobike, this->initiating.packet);
f215e919 295 }
7daf5226 296
f215e919 297 this->initiating.retransmitted++;
c60c7694
MW
298 job = (job_t*)retransmit_job_create(this->initiating.mid,
299 this->ike_sa->get_id(this->ike_sa));
bb381e26 300 lib->scheduler->schedule_job_ms(lib->scheduler, job, timeout);
c60c7694
MW
301 }
302 return SUCCESS;
303}
304
9560a316
MW
305METHOD(task_manager_t, initiate, status_t,
306 private_task_manager_t *this)
c60c7694 307{
e2630434 308 enumerator_t *enumerator;
c60c7694
MW
309 task_t *task;
310 message_t *message;
5474dc65 311 host_t *me, *other;
c60c7694
MW
312 status_t status;
313 exchange_type_t exchange = 0;
7daf5226 314
2540992a
MW
315 if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
316 {
03ffa885
TE
317 DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
318 exchange_type_names, this->initiating.type);
2540992a
MW
319 /* do not initiate if we already have a message in the air */
320 return SUCCESS;
321 }
7daf5226 322
6207fadb 323 if (array_count(this->active_tasks) == 0)
c60c7694
MW
324 {
325 DBG2(DBG_IKE, "activating new tasks");
326 switch (this->ike_sa->get_state(this->ike_sa))
327 {
328 case IKE_CREATED:
a09972df
MW
329 activate_task(this, TASK_IKE_VENDOR);
330 if (activate_task(this, TASK_IKE_INIT))
c60c7694 331 {
63c47724 332 this->initiating.mid = 0;
c60c7694 333 exchange = IKE_SA_INIT;
a09972df
MW
334 activate_task(this, TASK_IKE_NATD);
335 activate_task(this, TASK_IKE_CERT_PRE);
dc04b7c7 336#ifdef ME
a09972df 337 /* this task has to be activated before the TASK_IKE_AUTH
d5cc1758
TB
338 * task, because that task pregenerates the packet after
339 * which no payloads can be added to the message anymore.
340 */
a09972df 341 activate_task(this, TASK_IKE_ME);
dc04b7c7 342#endif /* ME */
a09972df
MW
343 activate_task(this, TASK_IKE_AUTH);
344 activate_task(this, TASK_IKE_CERT_POST);
345 activate_task(this, TASK_IKE_CONFIG);
346 activate_task(this, TASK_CHILD_CREATE);
347 activate_task(this, TASK_IKE_AUTH_LIFETIME);
348 activate_task(this, TASK_IKE_MOBIKE);
c60c7694
MW
349 }
350 break;
351 case IKE_ESTABLISHED:
a09972df 352 if (activate_task(this, TASK_CHILD_CREATE))
c60c7694
MW
353 {
354 exchange = CREATE_CHILD_SA;
c60c7694
MW
355 break;
356 }
a09972df 357 if (activate_task(this, TASK_CHILD_DELETE))
c60c7694
MW
358 {
359 exchange = INFORMATIONAL;
360 break;
361 }
a09972df 362 if (activate_task(this, TASK_CHILD_REKEY))
c60c7694
MW
363 {
364 exchange = CREATE_CHILD_SA;
365 break;
366 }
a09972df 367 if (activate_task(this, TASK_IKE_DELETE))
c60c7694
MW
368 {
369 exchange = INFORMATIONAL;
370 break;
371 }
a09972df 372 if (activate_task(this, TASK_IKE_REKEY))
c60c7694
MW
373 {
374 exchange = CREATE_CHILD_SA;
375 break;
376 }
a09972df 377 if (activate_task(this, TASK_IKE_REAUTH))
26424f03
MW
378 {
379 exchange = INFORMATIONAL;
380 break;
381 }
a09972df 382 if (activate_task(this, TASK_IKE_MOBIKE))
4cb9d7a7
MW
383 {
384 exchange = INFORMATIONAL;
385 break;
386 }
a09972df 387 if (activate_task(this, TASK_IKE_DPD))
c60c7694
MW
388 {
389 exchange = INFORMATIONAL;
390 break;
391 }
b1f2f05c
MW
392 if (activate_task(this, TASK_IKE_AUTH_LIFETIME))
393 {
394 exchange = INFORMATIONAL;
395 break;
396 }
dc04b7c7 397#ifdef ME
a09972df 398 if (activate_task(this, TASK_IKE_ME))
d5cc1758 399 {
dc04b7c7 400 exchange = ME_CONNECT;
d5cc1758
TB
401 break;
402 }
dc04b7c7 403#endif /* ME */
c60c7694 404 case IKE_REKEYING:
a09972df 405 if (activate_task(this, TASK_IKE_DELETE))
c60c7694
MW
406 {
407 exchange = INFORMATIONAL;
408 break;
409 }
410 case IKE_DELETING:
411 default:
412 break;
413 }
414 }
415 else
416 {
417 DBG2(DBG_IKE, "reinitiating already active tasks");
6207fadb
MW
418 enumerator = array_create_enumerator(this->active_tasks);
419 while (enumerator->enumerate(enumerator, &task))
c60c7694
MW
420 {
421 DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
422 switch (task->get_type(task))
423 {
a09972df 424 case TASK_IKE_INIT:
c60c7694
MW
425 exchange = IKE_SA_INIT;
426 break;
a09972df 427 case TASK_IKE_AUTH:
c60c7694
MW
428 exchange = IKE_AUTH;
429 break;
a09972df
MW
430 case TASK_CHILD_CREATE:
431 case TASK_CHILD_REKEY:
432 case TASK_IKE_REKEY:
1fd5383e
MW
433 exchange = CREATE_CHILD_SA;
434 break;
a09972df 435 case TASK_IKE_MOBIKE:
2b3100b5 436 exchange = INFORMATIONAL;
d46f8575 437 break;
c60c7694
MW
438 default:
439 continue;
440 }
441 break;
442 }
e2630434 443 enumerator->destroy(enumerator);
c60c7694 444 }
7daf5226 445
c60c7694
MW
446 if (exchange == 0)
447 {
448 DBG2(DBG_IKE, "nothing to initiate");
449 /* nothing to do yet... */
450 return SUCCESS;
451 }
7daf5226 452
5474dc65
MW
453 me = this->ike_sa->get_my_host(this->ike_sa);
454 other = this->ike_sa->get_other_host(this->ike_sa);
7daf5226 455
4ed52db2 456 message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
c60c7694 457 message->set_message_id(message, this->initiating.mid);
5474dc65
MW
458 message->set_source(message, me->clone(me));
459 message->set_destination(message, other->clone(other));
c60c7694
MW
460 message->set_exchange_type(message, exchange);
461 this->initiating.type = exchange;
462 this->initiating.retransmitted = 0;
7daf5226 463
6207fadb
MW
464 enumerator = array_create_enumerator(this->active_tasks);
465 while (enumerator->enumerate(enumerator, &task))
c60c7694 466 {
f1f09810
MW
467 switch (task->build(task, message))
468 {
469 case SUCCESS:
470 /* task completed, remove it */
6207fadb 471 array_remove_at(this->active_tasks, enumerator);
f1f09810
MW
472 task->destroy(task);
473 break;
474 case NEED_MORE:
475 /* processed, but task needs another exchange */
476 break;
477 case FAILED:
478 default:
bee6515a 479 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
977ec0c3
MW
480 if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
481 {
482 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
483 }
484 /* FALL */
485 case DESTROY_ME:
f1f09810 486 /* critical failure, destroy IKE_SA */
e2630434 487 enumerator->destroy(enumerator);
c60c7694 488 message->destroy(message);
0f33e826 489 flush(this);
f1f09810
MW
490 return DESTROY_ME;
491 }
c60c7694 492 }
e2630434 493 enumerator->destroy(enumerator);
7daf5226 494
394eb35b
MW
495 /* update exchange type if a task changed it */
496 this->initiating.type = message->get_exchange_type(message);
7daf5226 497
c60c7694
MW
498 status = this->ike_sa->generate_message(this->ike_sa, message,
499 &this->initiating.packet);
c60c7694
MW
500 if (status != SUCCESS)
501 {
f1f09810 502 /* message generation failed. There is nothing more to do than to
c60c7694 503 * close the SA */
f1f09810 504 message->destroy(message);
0f33e826 505 flush(this);
977ec0c3 506 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
f1f09810 507 return DESTROY_ME;
5474dc65 508 }
f1f09810 509 message->destroy(message);
7daf5226 510
6207fadb
MW
511 array_compress(this->active_tasks);
512 array_compress(this->queued_tasks);
513
c60c7694
MW
514 return retransmit(this, this->initiating.mid);
515}
516
517/**
518 * handle an incoming response message
519 */
520static status_t process_response(private_task_manager_t *this,
521 message_t *message)
522{
e2630434 523 enumerator_t *enumerator;
c60c7694 524 task_t *task;
7daf5226 525
c60c7694
MW
526 if (message->get_exchange_type(message) != this->initiating.type)
527 {
528 DBG1(DBG_IKE, "received %N response, but expected %N",
529 exchange_type_names, message->get_exchange_type(message),
530 exchange_type_names, this->initiating.type);
977ec0c3 531 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
c60c7694
MW
532 return DESTROY_ME;
533 }
7daf5226 534
17d92e97
MW
535 /* catch if we get resetted while processing */
536 this->reset = FALSE;
6207fadb
MW
537 enumerator = array_create_enumerator(this->active_tasks);
538 while (enumerator->enumerate(enumerator, &task))
c60c7694 539 {
f1f09810
MW
540 switch (task->process(task, message))
541 {
542 case SUCCESS:
543 /* task completed, remove it */
6207fadb 544 array_remove_at(this->active_tasks, enumerator);
f1f09810
MW
545 task->destroy(task);
546 break;
547 case NEED_MORE:
548 /* processed, but task needs another exchange */
549 break;
550 case FAILED:
551 default:
977ec0c3
MW
552 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
553 /* FALL */
554 case DESTROY_ME:
f1f09810 555 /* critical failure, destroy IKE_SA */
6207fadb 556 array_remove_at(this->active_tasks, enumerator);
e2630434 557 enumerator->destroy(enumerator);
394eb35b 558 task->destroy(task);
f1f09810
MW
559 return DESTROY_ME;
560 }
561 if (this->reset)
562 { /* start all over again if we were reset */
563 this->reset = FALSE;
e2630434 564 enumerator->destroy(enumerator);
9560a316 565 return initiate(this);
484a06bc 566 }
c60c7694 567 }
e2630434 568 enumerator->destroy(enumerator);
7daf5226 569
c60c7694 570 this->initiating.mid++;
2540992a 571 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
04a7a1c3
MW
572 this->initiating.packet->destroy(this->initiating.packet);
573 this->initiating.packet = NULL;
7daf5226 574
6207fadb
MW
575 array_compress(this->active_tasks);
576
9560a316 577 return initiate(this);
c60c7694
MW
578}
579
195ada0b
MW
580/**
581 * handle exchange collisions
582 */
3ced6b51 583static bool handle_collisions(private_task_manager_t *this, task_t *task)
195ada0b 584{
e2630434 585 enumerator_t *enumerator;
195ada0b
MW
586 task_t *active;
587 task_type_t type;
7daf5226 588
195ada0b 589 type = task->get_type(task);
7daf5226 590
4315f5c8 591 /* do we have to check */
a09972df
MW
592 if (type == TASK_IKE_REKEY || type == TASK_CHILD_REKEY ||
593 type == TASK_CHILD_DELETE || type == TASK_IKE_DELETE ||
594 type == TASK_IKE_REAUTH)
4315f5c8 595 {
f1f09810 596 /* find an exchange collision, and notify these tasks */
6207fadb
MW
597 enumerator = array_create_enumerator(this->active_tasks);
598 while (enumerator->enumerate(enumerator, &active))
f1f09810
MW
599 {
600 switch (active->get_type(active))
601 {
a09972df
MW
602 case TASK_IKE_REKEY:
603 if (type == TASK_IKE_REKEY || type == TASK_IKE_DELETE ||
604 type == TASK_IKE_REAUTH)
f1f09810
MW
605 {
606 ike_rekey_t *rekey = (ike_rekey_t*)active;
607 rekey->collide(rekey, task);
608 break;
609 }
610 continue;
a09972df
MW
611 case TASK_CHILD_REKEY:
612 if (type == TASK_CHILD_REKEY || type == TASK_CHILD_DELETE)
f1f09810
MW
613 {
614 child_rekey_t *rekey = (child_rekey_t*)active;
615 rekey->collide(rekey, task);
616 break;
617 }
618 continue;
619 default:
620 continue;
621 }
e2630434 622 enumerator->destroy(enumerator);
3ced6b51 623 return TRUE;
4315f5c8 624 }
e2630434 625 enumerator->destroy(enumerator);
195ada0b 626 }
3ced6b51 627 return FALSE;
195ada0b
MW
628}
629
c60c7694
MW
630/**
631 * build a response depending on the "passive" task list
632 */
5474dc65 633static status_t build_response(private_task_manager_t *this, message_t *request)
c60c7694 634{
e2630434 635 enumerator_t *enumerator;
c60c7694
MW
636 task_t *task;
637 message_t *message;
5474dc65 638 host_t *me, *other;
b24be296 639 bool delete = FALSE, hook = FALSE;
2ec3552f
TB
640 ike_sa_id_t *id = NULL;
641 u_int64_t responder_spi;
c60c7694 642 status_t status;
7daf5226 643
5474dc65
MW
644 me = request->get_destination(request);
645 other = request->get_source(request);
7daf5226 646
4ed52db2 647 message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
5474dc65
MW
648 message->set_exchange_type(message, request->get_exchange_type(request));
649 /* send response along the path the request came in */
650 message->set_source(message, me->clone(me));
651 message->set_destination(message, other->clone(other));
c60c7694
MW
652 message->set_message_id(message, this->responding.mid);
653 message->set_request(message, FALSE);
7daf5226 654
6207fadb 655 enumerator = array_create_enumerator(this->passive_tasks);
e2630434 656 while (enumerator->enumerate(enumerator, (void*)&task))
c60c7694 657 {
f1f09810
MW
658 switch (task->build(task, message))
659 {
660 case SUCCESS:
661 /* task completed, remove it */
6207fadb 662 array_remove_at(this->passive_tasks, enumerator);
3ced6b51
MW
663 if (!handle_collisions(this, task))
664 {
665 task->destroy(task);
666 }
667 break;
f1f09810
MW
668 case NEED_MORE:
669 /* processed, but task needs another exchange */
3ced6b51
MW
670 if (handle_collisions(this, task))
671 {
6207fadb 672 array_remove_at(this->passive_tasks, enumerator);
3ced6b51 673 }
f1f09810
MW
674 break;
675 case FAILED:
676 default:
b24be296
MW
677 hook = TRUE;
678 /* FALL */
679 case DESTROY_ME:
f1f09810
MW
680 /* destroy IKE_SA, but SEND response first */
681 delete = TRUE;
682 break;
683 }
684 if (delete)
685 {
686 break;
687 }
c60c7694 688 }
e2630434 689 enumerator->destroy(enumerator);
7daf5226 690
2ec3552f
TB
691 /* RFC 5996, section 2.6 mentions that in the event of a failure during
692 * IKE_SA_INIT the responder's SPI will be 0 in the response, while it
693 * actually explicitly allows it to be non-zero. Since we use the responder
694 * SPI to create hashes in the IKE_SA manager we can only set the SPI to
695 * zero temporarily, otherwise checking the SA in would fail. */
5474dc65 696 if (delete && request->get_exchange_type(request) == IKE_SA_INIT)
ddae0f96 697 {
2ec3552f
TB
698 id = this->ike_sa->get_id(this->ike_sa);
699 responder_spi = id->get_responder_spi(id);
ddae0f96
MW
700 id->set_responder_spi(id, 0);
701 }
7daf5226 702
c60c7694
MW
703 /* message complete, send it */
704 DESTROY_IF(this->responding.packet);
8f0ab613 705 this->responding.packet = NULL;
c60c7694
MW
706 status = this->ike_sa->generate_message(this->ike_sa, message,
707 &this->responding.packet);
708 message->destroy(message);
2ec3552f
TB
709 if (id)
710 {
711 id->set_responder_spi(id, responder_spi);
712 }
c60c7694
MW
713 if (status != SUCCESS)
714 {
977ec0c3 715 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
f1f09810 716 return DESTROY_ME;
c60c7694 717 }
7daf5226 718
4deb8948
MW
719 charon->sender->send(charon->sender,
720 this->responding.packet->clone(this->responding.packet));
c60c7694
MW
721 if (delete)
722 {
b24be296
MW
723 if (hook)
724 {
725 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
726 }
c60c7694
MW
727 return DESTROY_ME;
728 }
6207fadb
MW
729
730 array_compress(this->passive_tasks);
731
c60c7694
MW
732 return SUCCESS;
733}
734
735/**
736 * handle an incoming request message
737 */
738static status_t process_request(private_task_manager_t *this,
739 message_t *message)
740{
a44bb934 741 enumerator_t *enumerator;
c60c7694 742 task_t *task = NULL;
c60c7694
MW
743 payload_t *payload;
744 notify_payload_t *notify;
4cb9d7a7 745 delete_payload_t *delete;
7daf5226 746
6207fadb 747 if (array_count(this->passive_tasks) == 0)
0ce19b27
MW
748 { /* create tasks depending on request type, if not already some queued */
749 switch (message->get_exchange_type(message))
c60c7694 750 {
0ce19b27
MW
751 case IKE_SA_INIT:
752 {
a5a0bcaa 753 task = (task_t*)ike_vendor_create(this->ike_sa, FALSE);
6207fadb 754 array_insert(this->passive_tasks, ARRAY_TAIL, task);
347488bd 755 task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
6207fadb 756 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 757 task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
6207fadb 758 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 759 task = (task_t*)ike_cert_pre_create(this->ike_sa, FALSE);
6207fadb 760 array_insert(this->passive_tasks, ARRAY_TAIL, task);
484a06bc 761#ifdef ME
0ce19b27 762 task = (task_t*)ike_me_create(this->ike_sa, FALSE);
6207fadb 763 array_insert(this->passive_tasks, ARRAY_TAIL, task);
dc04b7c7 764#endif /* ME */
0ce19b27 765 task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
6207fadb 766 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 767 task = (task_t*)ike_cert_post_create(this->ike_sa, FALSE);
6207fadb 768 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 769 task = (task_t*)ike_config_create(this->ike_sa, FALSE);
6207fadb 770 array_insert(this->passive_tasks, ARRAY_TAIL, task);
f669f453
MW
771 task = (task_t*)child_create_create(this->ike_sa, NULL, FALSE,
772 NULL, NULL);
6207fadb 773 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 774 task = (task_t*)ike_auth_lifetime_create(this->ike_sa, FALSE);
6207fadb 775 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 776 task = (task_t*)ike_mobike_create(this->ike_sa, FALSE);
6207fadb 777 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27
MW
778 break;
779 }
780 case CREATE_CHILD_SA:
781 { /* FIXME: we should prevent this on mediation connections */
782 bool notify_found = FALSE, ts_found = FALSE;
783 enumerator = message->create_payload_enumerator(message);
784 while (enumerator->enumerate(enumerator, &payload))
c60c7694 785 {
0ce19b27 786 switch (payload->get_type(payload))
c60c7694 787 {
0ce19b27
MW
788 case NOTIFY:
789 { /* if we find a rekey notify, its CHILD_SA rekeying */
790 notify = (notify_payload_t*)payload;
791 if (notify->get_notify_type(notify) == REKEY_SA &&
792 (notify->get_protocol_id(notify) == PROTO_AH ||
793 notify->get_protocol_id(notify) == PROTO_ESP))
794 {
795 notify_found = TRUE;
796 }
797 break;
c60c7694 798 }
0ce19b27
MW
799 case TRAFFIC_SELECTOR_INITIATOR:
800 case TRAFFIC_SELECTOR_RESPONDER:
801 { /* if we don't find a TS, its IKE rekeying */
802 ts_found = TRUE;
803 break;
804 }
805 default:
806 break;
c60c7694 807 }
c60c7694 808 }
0ce19b27 809 enumerator->destroy(enumerator);
7daf5226 810
0ce19b27 811 if (ts_found)
c60c7694 812 {
0ce19b27
MW
813 if (notify_found)
814 {
815 task = (task_t*)child_rekey_create(this->ike_sa,
816 PROTO_NONE, 0);
817 }
818 else
819 {
f669f453
MW
820 task = (task_t*)child_create_create(this->ike_sa, NULL,
821 FALSE, NULL, NULL);
0ce19b27 822 }
c60c7694
MW
823 }
824 else
825 {
0ce19b27 826 task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
c60c7694 827 }
6207fadb 828 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 829 break;
c60c7694 830 }
0ce19b27 831 case INFORMATIONAL:
c60c7694 832 {
0ce19b27
MW
833 enumerator = message->create_payload_enumerator(message);
834 while (enumerator->enumerate(enumerator, &payload))
c60c7694 835 {
0ce19b27 836 switch (payload->get_type(payload))
4cb9d7a7 837 {
0ce19b27 838 case NOTIFY:
4cb9d7a7 839 {
0ce19b27
MW
840 notify = (notify_payload_t*)payload;
841 switch (notify->get_notify_type(notify))
842 {
843 case ADDITIONAL_IP4_ADDRESS:
844 case ADDITIONAL_IP6_ADDRESS:
845 case NO_ADDITIONAL_ADDRESSES:
846 case UPDATE_SA_ADDRESSES:
847 case NO_NATS_ALLOWED:
848 case UNACCEPTABLE_ADDRESSES:
849 case UNEXPECTED_NAT_DETECTED:
850 case COOKIE2:
851 case NAT_DETECTION_SOURCE_IP:
852 case NAT_DETECTION_DESTINATION_IP:
853 task = (task_t*)ike_mobike_create(
854 this->ike_sa, FALSE);
855 break;
856 case AUTH_LIFETIME:
857 task = (task_t*)ike_auth_lifetime_create(
858 this->ike_sa, FALSE);
859 break;
ca74bf7a
MW
860 case AUTHENTICATION_FAILED:
861 /* initiator failed to authenticate us.
862 * We use ike_delete to handle this, which
863 * invokes all the required hooks. */
864 task = (task_t*)ike_delete_create(
865 this->ike_sa, FALSE);
0ce19b27
MW
866 default:
867 break;
868 }
869 break;
4cb9d7a7 870 }
0ce19b27 871 case DELETE:
4cb9d7a7 872 {
0ce19b27
MW
873 delete = (delete_payload_t*)payload;
874 if (delete->get_protocol_id(delete) == PROTO_IKE)
875 {
876 task = (task_t*)ike_delete_create(this->ike_sa,
877 FALSE);
878 }
879 else
880 {
881 task = (task_t*)child_delete_create(this->ike_sa,
3a925f74 882 PROTO_NONE, 0, FALSE);
0ce19b27
MW
883 }
884 break;
4cb9d7a7 885 }
0ce19b27
MW
886 default:
887 break;
4cb9d7a7 888 }
0ce19b27
MW
889 if (task)
890 {
4cb9d7a7 891 break;
0ce19b27 892 }
c60c7694 893 }
0ce19b27 894 enumerator->destroy(enumerator);
7daf5226 895
0ce19b27 896 if (task == NULL)
3bc62fe7 897 {
0ce19b27 898 task = (task_t*)ike_dpd_create(FALSE);
3bc62fe7 899 }
6207fadb 900 array_insert(this->passive_tasks, ARRAY_TAIL, task);
0ce19b27 901 break;
c60c7694 902 }
0ce19b27
MW
903#ifdef ME
904 case ME_CONNECT:
c60c7694 905 {
0ce19b27 906 task = (task_t*)ike_me_create(this->ike_sa, FALSE);
6207fadb 907 array_insert(this->passive_tasks, ARRAY_TAIL, task);
c60c7694 908 }
dc04b7c7 909#endif /* ME */
0ce19b27
MW
910 default:
911 break;
912 }
c60c7694 913 }
7daf5226 914
c60c7694 915 /* let the tasks process the message */
6207fadb 916 enumerator = array_create_enumerator(this->passive_tasks);
e2630434 917 while (enumerator->enumerate(enumerator, (void*)&task))
c60c7694 918 {
f1f09810
MW
919 switch (task->process(task, message))
920 {
921 case SUCCESS:
922 /* task completed, remove it */
6207fadb 923 array_remove_at(this->passive_tasks, enumerator);
f1f09810
MW
924 task->destroy(task);
925 break;
926 case NEED_MORE:
927 /* processed, but task needs at least another call to build() */
928 break;
929 case FAILED:
930 default:
977ec0c3
MW
931 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
932 /* FALL */
933 case DESTROY_ME:
f1f09810 934 /* critical failure, destroy IKE_SA */
6207fadb 935 array_remove_at(this->passive_tasks, enumerator);
e2630434 936 enumerator->destroy(enumerator);
394eb35b 937 task->destroy(task);
f1f09810
MW
938 return DESTROY_ME;
939 }
c60c7694 940 }
e2630434 941 enumerator->destroy(enumerator);
7daf5226 942
5474dc65 943 return build_response(this, message);
c60c7694
MW
944}
945
68c6863b
TB
946METHOD(task_manager_t, incr_mid, void,
947 private_task_manager_t *this, bool initiate)
948{
949 if (initiate)
950 {
951 this->initiating.mid++;
952 }
953 else
954 {
955 this->responding.mid++;
956 }
957}
958
959/**
960 * Send a notify back to the sender
961 */
962static void send_notify_response(private_task_manager_t *this,
963 message_t *request, notify_type_t type,
964 chunk_t data)
965{
966 message_t *response;
967 packet_t *packet;
968 host_t *me, *other;
969
970 response = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
971 response->set_exchange_type(response, request->get_exchange_type(request));
972 response->set_request(response, FALSE);
973 response->set_message_id(response, request->get_message_id(request));
974 response->add_notify(response, FALSE, type, data);
975 me = this->ike_sa->get_my_host(this->ike_sa);
976 if (me->is_anyaddr(me))
977 {
978 me = request->get_destination(request);
979 this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
980 }
981 other = this->ike_sa->get_other_host(this->ike_sa);
982 if (other->is_anyaddr(other))
983 {
984 other = request->get_source(request);
985 this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
986 }
987 response->set_source(response, me->clone(me));
988 response->set_destination(response, other->clone(other));
989 if (this->ike_sa->generate_message(this->ike_sa, response,
990 &packet) == SUCCESS)
991 {
992 charon->sender->send(charon->sender, packet);
993 }
994 response->destroy(response);
995}
996
997/**
998 * Parse the given message and verify that it is valid.
999 */
1000static status_t parse_message(private_task_manager_t *this, message_t *msg)
1001{
1002 status_t status;
68c6863b
TB
1003 u_int8_t type = 0;
1004
68c6863b
TB
1005 status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
1006
1007 if (status == SUCCESS)
1008 { /* check for unsupported critical payloads */
1009 enumerator_t *enumerator;
1010 unknown_payload_t *unknown;
1011 payload_t *payload;
1012
1013 enumerator = msg->create_payload_enumerator(msg);
1014 while (enumerator->enumerate(enumerator, &payload))
1015 {
1016 unknown = (unknown_payload_t*)payload;
1017 type = payload->get_type(payload);
1018 if (!payload_is_known(type) &&
1019 unknown->is_critical(unknown))
1020 {
1021 DBG1(DBG_ENC, "payload type %N is not supported, "
1022 "but its critical!", payload_type_names, type);
1023 status = NOT_SUPPORTED;
48651d8d 1024 break;
68c6863b
TB
1025 }
1026 }
1027 enumerator->destroy(enumerator);
1028 }
1029
1030 if (status != SUCCESS)
1031 {
e6732003
TB
1032 bool is_request = msg->get_request(msg);
1033
1034 switch (status)
68c6863b 1035 {
e6732003
TB
1036 case NOT_SUPPORTED:
1037 DBG1(DBG_IKE, "critical unknown payloads found");
1038 if (is_request)
1039 {
1040 send_notify_response(this, msg,
1041 UNSUPPORTED_CRITICAL_PAYLOAD,
1042 chunk_from_thing(type));
1043 incr_mid(this, FALSE);
1044 }
1045 break;
1046 case PARSE_ERROR:
1047 DBG1(DBG_IKE, "message parsing failed");
1048 if (is_request)
1049 {
1050 send_notify_response(this, msg,
1051 INVALID_SYNTAX, chunk_empty);
1052 incr_mid(this, FALSE);
1053 }
1054 break;
1055 case VERIFY_ERROR:
1056 DBG1(DBG_IKE, "message verification failed");
1057 if (is_request)
1058 {
1059 send_notify_response(this, msg,
1060 INVALID_SYNTAX, chunk_empty);
1061 incr_mid(this, FALSE);
1062 }
1063 break;
1064 case FAILED:
1065 DBG1(DBG_IKE, "integrity check failed");
1066 /* ignored */
1067 break;
1068 case INVALID_STATE:
1069 DBG1(DBG_IKE, "found encrypted message, but no keys available");
1070 default:
1071 break;
68c6863b
TB
1072 }
1073 DBG1(DBG_IKE, "%N %s with message ID %d processing failed",
1074 exchange_type_names, msg->get_exchange_type(msg),
1075 is_request ? "request" : "response",
1076 msg->get_message_id(msg));
1077
418f4bc7
MW
1078 charon->bus->alert(charon->bus, ALERT_PARSE_ERROR_BODY, msg, status);
1079
68c6863b
TB
1080 if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED)
1081 { /* invalid initiation attempt, close SA */
1082 return DESTROY_ME;
1083 }
1084 }
1085 return status;
1086}
1087
1088
9560a316
MW
1089METHOD(task_manager_t, process_message, status_t,
1090 private_task_manager_t *this, message_t *msg)
c60c7694 1091{
8ba805f4 1092 host_t *me, *other;
68c6863b 1093 status_t status;
8ba805f4
MW
1094 u_int32_t mid;
1095
47b8f6ef 1096 charon->bus->message(charon->bus, msg, TRUE, FALSE);
68c6863b
TB
1097 status = parse_message(this, msg);
1098 if (status != SUCCESS)
1099 {
1100 return status;
1101 }
1102
8ba805f4
MW
1103 me = msg->get_destination(msg);
1104 other = msg->get_source(msg);
7daf5226 1105
68c6863b
TB
1106 /* if this IKE_SA is virgin, we check for a config */
1107 if (this->ike_sa->get_ike_cfg(this->ike_sa) == NULL)
1108 {
1109 ike_sa_id_t *ike_sa_id;
1110 ike_cfg_t *ike_cfg;
1111 job_t *job;
79101163
MW
1112 ike_cfg = charon->backends->get_ike_cfg(charon->backends,
1113 me, other, IKEV2);
68c6863b
TB
1114 if (ike_cfg == NULL)
1115 {
1116 /* no config found for these hosts, destroy */
1117 DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
1118 me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
1119 send_notify_response(this, msg,
1120 NO_PROPOSAL_CHOSEN, chunk_empty);
1121 return DESTROY_ME;
1122 }
1123 this->ike_sa->set_ike_cfg(this->ike_sa, ike_cfg);
1124 ike_cfg->destroy(ike_cfg);
1125 /* add a timeout if peer does not establish it completely */
1126 ike_sa_id = this->ike_sa->get_id(this->ike_sa);
1127 job = (job_t*)delete_ike_sa_job_create(ike_sa_id, FALSE);
1128 lib->scheduler->schedule_job(lib->scheduler, job,
1129 lib->settings->get_int(lib->settings,
42500c27
TB
1130 "%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
1131 charon->name));
68c6863b
TB
1132 }
1133 this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
1134 time_monotonic(NULL));
1135
1136 mid = msg->get_message_id(msg);
c60c7694
MW
1137 if (msg->get_request(msg))
1138 {
1139 if (mid == this->responding.mid)
1140 {
cdf75a39
MW
1141 /* reject initial messages once established */
1142 if (msg->get_exchange_type(msg) == IKE_SA_INIT ||
1143 msg->get_exchange_type(msg) == IKE_AUTH)
1144 {
1145 if (this->ike_sa->get_state(this->ike_sa) != IKE_CREATED &&
1146 this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
1147 {
1148 DBG1(DBG_IKE, "ignoring %N in established IKE_SA state",
1149 exchange_type_names, msg->get_exchange_type(msg));
1150 return FAILED;
1151 }
1152 }
cd26eedc
TB
1153 if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED ||
1154 this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING ||
1155 msg->get_exchange_type(msg) != IKE_SA_INIT)
1156 { /* only do host updates based on verified messages */
1157 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
1158 { /* with MOBIKE, we do no implicit updates */
2082417d 1159 this->ike_sa->update_hosts(this->ike_sa, me, other, mid == 1);
cd26eedc
TB
1160 }
1161 }
47b8f6ef 1162 charon->bus->message(charon->bus, msg, TRUE, TRUE);
c146c3c4
MW
1163 if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
1164 { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
1165 return SUCCESS;
1166 }
c60c7694
MW
1167 if (process_request(this, msg) != SUCCESS)
1168 {
0f33e826 1169 flush(this);
c60c7694
MW
1170 return DESTROY_ME;
1171 }
1172 this->responding.mid++;
1173 }
1174 else if ((mid == this->responding.mid - 1) && this->responding.packet)
1175 {
d9d69536 1176 packet_t *clone;
8ba805f4 1177 host_t *host;
7daf5226 1178
c60c7694 1179 DBG1(DBG_IKE, "received retransmit of request with ID %d, "
b9b8a98f 1180 "retransmitting response", mid);
3c79b7b7 1181 charon->bus->alert(charon->bus, ALERT_RETRANSMIT_RECEIVE, msg);
d9d69536 1182 clone = this->responding.packet->clone(this->responding.packet);
8ba805f4
MW
1183 host = msg->get_destination(msg);
1184 clone->set_source(clone, host->clone(host));
1185 host = msg->get_source(msg);
1186 clone->set_destination(clone, host->clone(host));
d9d69536 1187 charon->sender->send(charon->sender, clone);
c60c7694
MW
1188 }
1189 else
1190 {
278396b6 1191 DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
c60c7694 1192 mid, this->responding.mid);
8f727d80
MW
1193 if (msg->get_exchange_type(msg) == IKE_SA_INIT)
1194 { /* clean up IKE_SA state if IKE_SA_INIT has invalid msg ID */
1195 return DESTROY_ME;
1196 }
c60c7694
MW
1197 }
1198 }
1199 else
1200 {
1201 if (mid == this->initiating.mid)
1202 {
cd26eedc
TB
1203 if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED ||
1204 this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING ||
1205 msg->get_exchange_type(msg) != IKE_SA_INIT)
1206 { /* only do host updates based on verified messages */
1207 if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
1208 { /* with MOBIKE, we do no implicit updates */
2082417d 1209 this->ike_sa->update_hosts(this->ike_sa, me, other, FALSE);
cd26eedc
TB
1210 }
1211 }
47b8f6ef 1212 charon->bus->message(charon->bus, msg, TRUE, TRUE);
c146c3c4
MW
1213 if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
1214 { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
1215 return SUCCESS;
1216 }
c60c7694
MW
1217 if (process_response(this, msg) != SUCCESS)
1218 {
0f33e826 1219 flush(this);
c60c7694
MW
1220 return DESTROY_ME;
1221 }
1222 }
1223 else
1224 {
278396b6 1225 DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
c60c7694
MW
1226 mid, this->initiating.mid);
1227 return SUCCESS;
1228 }
1229 }
1230 return SUCCESS;
1231}
1232
9560a316
MW
1233METHOD(task_manager_t, queue_task, void,
1234 private_task_manager_t *this, task_t *task)
c60c7694 1235{
a09972df 1236 if (task->get_type(task) == TASK_IKE_MOBIKE)
f215e919 1237 { /* there is no need to queue more than one mobike task */
e2630434 1238 enumerator_t *enumerator;
f215e919 1239 task_t *current;
7daf5226 1240
6207fadb
MW
1241 enumerator = array_create_enumerator(this->queued_tasks);
1242 while (enumerator->enumerate(enumerator, &current))
f215e919 1243 {
a09972df 1244 if (current->get_type(current) == TASK_IKE_MOBIKE)
f215e919 1245 {
e2630434 1246 enumerator->destroy(enumerator);
f215e919
MW
1247 task->destroy(task);
1248 return;
1249 }
1250 }
e2630434 1251 enumerator->destroy(enumerator);
f215e919 1252 }
c60c7694 1253 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
6207fadb 1254 array_insert(this->queued_tasks, ARRAY_TAIL, task);
c60c7694
MW
1255}
1256
8573b18d
MW
1257/**
1258 * Check if a given task has been queued already
1259 */
1260static bool has_queued(private_task_manager_t *this, task_type_t type)
a60daa07 1261{
26eee421 1262 enumerator_t *enumerator;
8573b18d 1263 bool found = FALSE;
26eee421
MW
1264 task_t *task;
1265
6207fadb 1266 enumerator = array_create_enumerator(this->queued_tasks);
26eee421
MW
1267 while (enumerator->enumerate(enumerator, &task))
1268 {
8573b18d 1269 if (task->get_type(task) == type)
26eee421 1270 {
8573b18d
MW
1271 found = TRUE;
1272 break;
26eee421
MW
1273 }
1274 }
1275 enumerator->destroy(enumerator);
8573b18d
MW
1276 return found;
1277}
26eee421 1278
8573b18d
MW
1279METHOD(task_manager_t, queue_ike, void,
1280 private_task_manager_t *this)
1281{
1282 if (!has_queued(this, TASK_IKE_VENDOR))
a60daa07 1283 {
26eee421 1284 queue_task(this, (task_t*)ike_vendor_create(this->ike_sa, TRUE));
8573b18d
MW
1285 }
1286 if (!has_queued(this, TASK_IKE_INIT))
1287 {
26eee421 1288 queue_task(this, (task_t*)ike_init_create(this->ike_sa, TRUE, NULL));
8573b18d
MW
1289 }
1290 if (!has_queued(this, TASK_IKE_NATD))
1291 {
26eee421 1292 queue_task(this, (task_t*)ike_natd_create(this->ike_sa, TRUE));
a60daa07 1293 }
8573b18d 1294 if (!has_queued(this, TASK_IKE_CERT_PRE))
26eee421
MW
1295 {
1296 queue_task(this, (task_t*)ike_cert_pre_create(this->ike_sa, TRUE));
8573b18d
MW
1297 }
1298 if (!has_queued(this, TASK_IKE_AUTH))
1299 {
26eee421 1300 queue_task(this, (task_t*)ike_auth_create(this->ike_sa, TRUE));
8573b18d
MW
1301 }
1302 if (!has_queued(this, TASK_IKE_CERT_POST))
1303 {
26eee421 1304 queue_task(this, (task_t*)ike_cert_post_create(this->ike_sa, TRUE));
8573b18d
MW
1305 }
1306 if (!has_queued(this, TASK_IKE_CONFIG))
1307 {
26eee421 1308 queue_task(this, (task_t*)ike_config_create(this->ike_sa, TRUE));
8573b18d
MW
1309 }
1310 if (!has_queued(this, TASK_IKE_AUTH_LIFETIME))
1311 {
26eee421 1312 queue_task(this, (task_t*)ike_auth_lifetime_create(this->ike_sa, TRUE));
8573b18d
MW
1313 }
1314 if (!has_queued(this, TASK_IKE_MOBIKE))
1315 {
1316 peer_cfg_t *peer_cfg;
26eee421
MW
1317
1318 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
1319 if (peer_cfg->use_mobike(peer_cfg))
1320 {
1321 queue_task(this, (task_t*)ike_mobike_create(this->ike_sa, TRUE));
1322 }
8573b18d 1323 }
a60daa07 1324#ifdef ME
8573b18d
MW
1325 if (!has_queued(this, TASK_IKE_ME))
1326 {
26eee421 1327 queue_task(this, (task_t*)ike_me_create(this->ike_sa, TRUE));
26eee421 1328 }
8573b18d 1329#endif /* ME */
a60daa07
MW
1330}
1331
dab60d64
MW
1332METHOD(task_manager_t, queue_ike_rekey, void,
1333 private_task_manager_t *this)
1334{
1335 queue_task(this, (task_t*)ike_rekey_create(this->ike_sa, TRUE));
1336}
1337
cedb412e
MW
1338METHOD(task_manager_t, queue_ike_reauth, void,
1339 private_task_manager_t *this)
1340{
1341 queue_task(this, (task_t*)ike_reauth_create(this->ike_sa));
1342}
1343
3ed148b3
MW
1344METHOD(task_manager_t, queue_ike_delete, void,
1345 private_task_manager_t *this)
1346{
1347 queue_task(this, (task_t*)ike_delete_create(this->ike_sa, TRUE));
1348}
1349
873df908
MW
1350METHOD(task_manager_t, queue_mobike, void,
1351 private_task_manager_t *this, bool roam, bool address)
1352{
1353 ike_mobike_t *mobike;
1354
1355 mobike = ike_mobike_create(this->ike_sa, TRUE);
1356 if (roam)
1357 {
1358 mobike->roam(mobike, address);
1359 }
1360 else
1361 {
1362 mobike->addresses(mobike);
1363 }
1364 queue_task(this, &mobike->task);
1365}
1366
fe43d9a2
MW
1367METHOD(task_manager_t, queue_child, void,
1368 private_task_manager_t *this, child_cfg_t *cfg, u_int32_t reqid,
1369 traffic_selector_t *tsi, traffic_selector_t *tsr)
1370{
1371 child_create_t *task;
1372
1373 task = child_create_create(this->ike_sa, cfg, FALSE, tsi, tsr);
1374 if (reqid)
1375 {
1376 task->use_reqid(task, reqid);
1377 }
1378 queue_task(this, &task->task);
1379}
1380
463a73cc
MW
1381METHOD(task_manager_t, queue_child_rekey, void,
1382 private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi)
1383{
1384 queue_task(this, (task_t*)child_rekey_create(this->ike_sa, protocol, spi));
1385}
1386
83c5fda0 1387METHOD(task_manager_t, queue_child_delete, void,
3a925f74
MW
1388 private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi,
1389 bool expired)
83c5fda0 1390{
3a925f74
MW
1391 queue_task(this, (task_t*)child_delete_create(this->ike_sa,
1392 protocol, spi, expired));
83c5fda0
MW
1393}
1394
244d715d
MW
1395METHOD(task_manager_t, queue_dpd, void,
1396 private_task_manager_t *this)
1397{
1398 ike_mobike_t *mobike;
1399
1400 if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE) &&
1401 this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
1402 {
1403 /* use mobike enabled DPD to detect NAT mapping changes */
1404 mobike = ike_mobike_create(this->ike_sa, TRUE);
1405 mobike->dpd(mobike);
1406 queue_task(this, &mobike->task);
1407 }
1408 else
1409 {
1410 queue_task(this, (task_t*)ike_dpd_create(TRUE));
1411 }
1412}
1413
9560a316
MW
1414METHOD(task_manager_t, adopt_tasks, void,
1415 private_task_manager_t *this, task_manager_t *other_public)
c60c7694 1416{
9560a316 1417 private_task_manager_t *other = (private_task_manager_t*)other_public;
c60c7694 1418 task_t *task;
7daf5226 1419
c60c7694 1420 /* move queued tasks from other to this */
6207fadb 1421 while (array_remove(other->queued_tasks, ARRAY_TAIL, &task))
c60c7694 1422 {
e23a59f6 1423 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
c60c7694 1424 task->migrate(task, this->ike_sa);
6207fadb 1425 array_insert(this->queued_tasks, ARRAY_HEAD, task);
c60c7694 1426 }
c60c7694
MW
1427}
1428
68db844f
TB
1429/**
1430 * Migrates child-creating tasks from src to dst
1431 */
1432static void migrate_child_tasks(private_task_manager_t *this,
1433 array_t *src, array_t *dst)
1434{
1435 enumerator_t *enumerator;
1436 task_t *task;
1437
1438 enumerator = array_create_enumerator(src);
1439 while (enumerator->enumerate(enumerator, &task))
1440 {
1441 if (task->get_type(task) == TASK_CHILD_CREATE)
1442 {
1443 array_remove_at(src, enumerator);
1444 task->migrate(task, this->ike_sa);
1445 array_insert(dst, ARRAY_TAIL, task);
1446 }
1447 }
1448 enumerator->destroy(enumerator);
1449}
1450
1451METHOD(task_manager_t, adopt_child_tasks, void,
1452 private_task_manager_t *this, task_manager_t *other_public)
1453{
1454 private_task_manager_t *other = (private_task_manager_t*)other_public;
1455
1456 /* move active child tasks from other to this */
1457 migrate_child_tasks(this, other->active_tasks, this->queued_tasks);
1458 /* do the same for queued tasks */
1459 migrate_child_tasks(this, other->queued_tasks, this->queued_tasks);
1460}
1461
9560a316
MW
1462METHOD(task_manager_t, busy, bool,
1463 private_task_manager_t *this)
c60c7694 1464{
6207fadb 1465 return array_count(this->active_tasks) > 0;
c60c7694
MW
1466}
1467
9560a316
MW
1468METHOD(task_manager_t, reset, void,
1469 private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
c60c7694 1470{
31d0efd7 1471 enumerator_t *enumerator;
c60c7694 1472 task_t *task;
7daf5226 1473
c60c7694
MW
1474 /* reset message counters and retransmit packets */
1475 DESTROY_IF(this->responding.packet);
1476 DESTROY_IF(this->initiating.packet);
c60c7694
MW
1477 this->responding.packet = NULL;
1478 this->initiating.packet = NULL;
b09ca747
MW
1479 if (initiate != UINT_MAX)
1480 {
1481 this->initiating.mid = initiate;
1482 }
1483 if (respond != UINT_MAX)
1484 {
1485 this->responding.mid = respond;
1486 }
1edf116c 1487 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
7daf5226 1488
7f1eb895 1489 /* reset queued tasks */
6207fadb 1490 enumerator = array_create_enumerator(this->queued_tasks);
31d0efd7 1491 while (enumerator->enumerate(enumerator, &task))
7f1eb895
TE
1492 {
1493 task->migrate(task, this->ike_sa);
7f1eb895 1494 }
31d0efd7
TE
1495 enumerator->destroy(enumerator);
1496
c60c7694 1497 /* reset active tasks */
6207fadb 1498 while (array_remove(this->active_tasks, ARRAY_TAIL, &task))
c60c7694
MW
1499 {
1500 task->migrate(task, this->ike_sa);
6207fadb 1501 array_insert(this->queued_tasks, ARRAY_HEAD, task);
c60c7694 1502 }
7daf5226 1503
17d92e97 1504 this->reset = TRUE;
c60c7694
MW
1505}
1506
665c18bd
MW
1507METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
1508 private_task_manager_t *this, task_queue_t queue)
1509{
1510 switch (queue)
1511 {
1512 case TASK_QUEUE_ACTIVE:
6207fadb 1513 return array_create_enumerator(this->active_tasks);
665c18bd 1514 case TASK_QUEUE_PASSIVE:
6207fadb 1515 return array_create_enumerator(this->passive_tasks);
665c18bd 1516 case TASK_QUEUE_QUEUED:
6207fadb 1517 return array_create_enumerator(this->queued_tasks);
665c18bd
MW
1518 default:
1519 return enumerator_create_empty();
1520 }
1521}
1522
9560a316
MW
1523METHOD(task_manager_t, destroy, void,
1524 private_task_manager_t *this)
c60c7694 1525{
0f33e826 1526 flush(this);
7daf5226 1527
6207fadb
MW
1528 array_destroy(this->active_tasks);
1529 array_destroy(this->queued_tasks);
1530 array_destroy(this->passive_tasks);
7daf5226 1531
c60c7694
MW
1532 DESTROY_IF(this->responding.packet);
1533 DESTROY_IF(this->initiating.packet);
c60c7694
MW
1534 free(this);
1535}
1536
1537/*
1538 * see header file
1539 */
e69f7dcd 1540task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
c60c7694 1541{
9560a316
MW
1542 private_task_manager_t *this;
1543
1544 INIT(this,
1545 .public = {
e69f7dcd
MW
1546 .task_manager = {
1547 .process_message = _process_message,
1548 .queue_task = _queue_task,
a60daa07 1549 .queue_ike = _queue_ike,
dab60d64 1550 .queue_ike_rekey = _queue_ike_rekey,
cedb412e 1551 .queue_ike_reauth = _queue_ike_reauth,
3ed148b3 1552 .queue_ike_delete = _queue_ike_delete,
873df908 1553 .queue_mobike = _queue_mobike,
fe43d9a2 1554 .queue_child = _queue_child,
463a73cc 1555 .queue_child_rekey = _queue_child_rekey,
83c5fda0 1556 .queue_child_delete = _queue_child_delete,
244d715d 1557 .queue_dpd = _queue_dpd,
e69f7dcd
MW
1558 .initiate = _initiate,
1559 .retransmit = _retransmit,
1560 .incr_mid = _incr_mid,
1561 .reset = _reset,
1562 .adopt_tasks = _adopt_tasks,
68db844f 1563 .adopt_child_tasks = _adopt_child_tasks,
e69f7dcd
MW
1564 .busy = _busy,
1565 .create_task_enumerator = _create_task_enumerator,
a5c79960 1566 .flush_queue = _flush_queue,
e69f7dcd
MW
1567 .destroy = _destroy,
1568 },
9560a316
MW
1569 },
1570 .ike_sa = ike_sa,
1571 .initiating.type = EXCHANGE_TYPE_UNDEFINED,
6207fadb
MW
1572 .queued_tasks = array_create(0, 0),
1573 .active_tasks = array_create(0, 0),
1574 .passive_tasks = array_create(0, 0),
9560a316 1575 .retransmit_tries = lib->settings->get_int(lib->settings,
42500c27 1576 "%s.retransmit_tries", RETRANSMIT_TRIES, charon->name),
9560a316 1577 .retransmit_timeout = lib->settings->get_double(lib->settings,
42500c27 1578 "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, charon->name),
9560a316 1579 .retransmit_base = lib->settings->get_double(lib->settings,
42500c27 1580 "%s.retransmit_base", RETRANSMIT_BASE, charon->name),
9560a316 1581 );
bc6ff2fc 1582
c60c7694
MW
1583 return &this->public;
1584}