]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/sa/task_manager_v1.c
Create negotiated hasher earlier during Main Mode so it is available for building...
[thirdparty/strongswan.git] / src / libcharon / sa / task_manager_v1.c
CommitLineData
4a09d9ee 1/*
68c6863b
TB
2 * Copyright (C) 2007-2011 Tobias Brunner
3 * Copyright (C) 2007-2011 Martin Willi
4a09d9ee
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
17#include "task_manager_v1.h"
18
da063ec9
MW
19#include <math.h>
20
4a09d9ee 21#include <daemon.h>
01685247 22#include <sa/tasks/ike_vendor.h>
c73c832c 23#include <sa/tasks/main_mode.h>
744c0801 24#include <sa/tasks/quick_mode.h>
b03c700d 25#include <sa/tasks/xauth_request.h>
a2f8fc97 26#include <sa/tasks/ike_vendor_v1.h>
da063ec9 27#include <processing/jobs/retransmit_job.h>
68c6863b 28#include <processing/jobs/delete_ike_sa_job.h>
4a09d9ee
MW
29
30typedef struct exchange_t exchange_t;
31
32/**
33 * An exchange in the air, used do detect and handle retransmission
34 */
35struct exchange_t {
36
37 /**
38 * Message ID used for this transaction
39 */
40 u_int32_t mid;
41
42 /**
43 * generated packet for retransmission
44 */
45 packet_t *packet;
46};
47
48typedef struct private_task_manager_t private_task_manager_t;
49
50/**
51 * private data of the task manager
52 */
53struct private_task_manager_t {
54
55 /**
56 * public functions
57 */
58 task_manager_v1_t public;
59
60 /**
61 * associated IKE_SA we are serving
62 */
63 ike_sa_t *ike_sa;
64
73aaf76b
MW
65 /**
66 * RNG to create message IDs
67 */
68 rng_t *rng;
69
4a09d9ee
MW
70 /**
71 * Exchange we are currently handling as responder
72 */
73 struct {
74 /**
75 * Message ID of the exchange
76 */
77 u_int32_t mid;
78
9cc8bd4f
MW
79 /**
80 * Hash of a previously received message
81 */
82 u_int32_t hash;
83
4a09d9ee
MW
84 /**
85 * packet for retransmission
86 */
87 packet_t *packet;
88
89 } responding;
90
91 /**
92 * Exchange we are currently handling as initiator
93 */
94 struct {
95 /**
96 * Message ID of the exchange
97 */
98 u_int32_t mid;
99
9cc8bd4f
MW
100 /**
101 * Hash of a previously received message
102 */
103 u_int32_t hash;
104
4a09d9ee
MW
105 /**
106 * how many times we have retransmitted so far
107 */
108 u_int retransmitted;
109
110 /**
111 * packet for retransmission
112 */
113 packet_t *packet;
114
115 /**
116 * type of the initated exchange
117 */
118 exchange_type_t type;
119
120 } initiating;
121
122 /**
123 * List of queued tasks not yet in action
124 */
125 linked_list_t *queued_tasks;
126
127 /**
128 * List of active tasks, initiated by ourselve
129 */
130 linked_list_t *active_tasks;
131
132 /**
133 * List of tasks initiated by peer
134 */
135 linked_list_t *passive_tasks;
136
4a09d9ee
MW
137 /**
138 * Number of times we retransmit messages before giving up
139 */
140 u_int retransmit_tries;
141
142 /**
143 * Retransmission timeout
144 */
145 double retransmit_timeout;
146
147 /**
148 * Base to calculate retransmission timeout
149 */
150 double retransmit_base;
151};
152
153/**
154 * flush all tasks in the task manager
155 */
156static void flush(private_task_manager_t *this)
157{
158 this->queued_tasks->destroy_offset(this->queued_tasks,
159 offsetof(task_t, destroy));
160 this->queued_tasks = linked_list_create();
161 this->passive_tasks->destroy_offset(this->passive_tasks,
162 offsetof(task_t, destroy));
163 this->passive_tasks = linked_list_create();
164 this->active_tasks->destroy_offset(this->active_tasks,
165 offsetof(task_t, destroy));
166 this->active_tasks = linked_list_create();
167}
168
26b55dc6
MW
169/**
170 * move a task of a specific type from the queue to the active list
171 */
172static bool activate_task(private_task_manager_t *this, task_type_t type)
173{
174 enumerator_t *enumerator;
175 task_t *task;
176 bool found = FALSE;
177
178 enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
179 while (enumerator->enumerate(enumerator, (void**)&task))
180 {
181 if (task->get_type(task) == type)
182 {
183 DBG2(DBG_IKE, " activating %N task", task_type_names, type);
184 this->queued_tasks->remove_at(this->queued_tasks, enumerator);
185 this->active_tasks->insert_last(this->active_tasks, task);
186 found = TRUE;
187 break;
188 }
189 }
190 enumerator->destroy(enumerator);
191 return found;
192}
193
23f4e4b4
CO
194METHOD(task_manager_t, retransmit, status_t,
195 private_task_manager_t *this, u_int32_t message_id)
196{
197 if (message_id == this->initiating.mid)
198 {
199 u_int32_t timeout;
23f4e4b4 200 packet_t *packet;
da063ec9 201 job_t *job;
23f4e4b4
CO
202
203 if (this->initiating.retransmitted <= this->retransmit_tries)
204 {
205 timeout = (u_int32_t)(this->retransmit_timeout * 1000.0 *
206 pow(this->retransmit_base, this->initiating.retransmitted));
207 }
208 else
209 {
210 DBG1(DBG_IKE, "giving up after %d retransmits",
211 this->initiating.retransmitted - 1);
212 if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
213 {
214 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
215 }
216 return DESTROY_ME;
217 }
218
219 if (this->initiating.retransmitted)
220 {
221 DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
222 this->initiating.retransmitted, message_id);
223 }
224 packet = this->initiating.packet->clone(this->initiating.packet);
225 charon->sender->send(charon->sender, packet);
226
227 this->initiating.retransmitted++;
228 job = (job_t*)retransmit_job_create(this->initiating.mid,
229 this->ike_sa->get_id(this->ike_sa));
230 lib->scheduler->schedule_job_ms(lib->scheduler, job, timeout);
231 }
232 return SUCCESS;
233}
234
4a09d9ee
MW
235METHOD(task_manager_t, initiate, status_t,
236 private_task_manager_t *this)
237{
26b55dc6
MW
238 enumerator_t *enumerator;
239 task_t *task;
240 message_t *message;
241 host_t *me, *other;
242 status_t status;
73aaf76b 243 exchange_type_t exchange = EXCHANGE_TYPE_UNDEFINED;
3e246c48 244 bool new_mid = FALSE;
73aaf76b
MW
245
246 if (!this->rng)
247 {
248 DBG1(DBG_IKE, "no RNG supported");
249 return FAILED;
250 }
26b55dc6
MW
251
252 if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
253 {
254 DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
255 exchange_type_names, this->initiating.type);
256 /* do not initiate if we already have a message in the air */
257 return SUCCESS;
258 }
259
260 if (this->active_tasks->get_count(this->active_tasks) == 0)
261 {
262 DBG2(DBG_IKE, "activating new tasks");
263 switch (this->ike_sa->get_state(this->ike_sa))
264 {
265 case IKE_CREATED:
a2f8fc97 266 activate_task(this, TASK_VENDOR_V1);
a09972df 267 if (activate_task(this, TASK_MAIN_MODE))
26b55dc6
MW
268 {
269 exchange = ID_PROT;
270 }
271 break;
c5dc9d33
CO
272 case IKE_CONNECTING:
273 if (activate_task(this, TASK_XAUTH_REQUEST))
744c0801 274 {
c5dc9d33 275 exchange = TRANSACTION;
3e246c48 276 new_mid = TRUE;
744c0801 277 }
c5dc9d33
CO
278 break;
279 case IKE_ESTABLISHED:
280 if (activate_task(this, TASK_QUICK_MODE))
23f4e4b4 281 {
c5dc9d33 282 exchange = QUICK_MODE;
3e246c48
MW
283 new_mid = TRUE;
284 break;
23f4e4b4 285 }
744c0801 286 break;
26b55dc6
MW
287 default:
288 break;
289 }
290 }
291 else
292 {
293 DBG2(DBG_IKE, "reinitiating already active tasks");
294 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
295 while (enumerator->enumerate(enumerator, (void**)&task))
296 {
297 DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
298 switch (task->get_type(task))
299 {
a09972df 300 case TASK_MAIN_MODE:
26b55dc6
MW
301 exchange = ID_PROT;
302 break;
744c0801
MW
303 case TASK_QUICK_MODE:
304 exchange = QUICK_MODE;
305 break;
52ac2ceb
CO
306 case TASK_XAUTH_REQUEST:
307 exchange = TRANSACTION;
308 new_mid = TRUE;
309 break;
26b55dc6
MW
310 default:
311 continue;
312 }
313 break;
314 }
315 enumerator->destroy(enumerator);
316 }
317
73aaf76b 318 if (exchange == EXCHANGE_TYPE_UNDEFINED)
26b55dc6
MW
319 {
320 DBG2(DBG_IKE, "nothing to initiate");
321 /* nothing to do yet... */
322 return SUCCESS;
323 }
324
325 me = this->ike_sa->get_my_host(this->ike_sa);
326 other = this->ike_sa->get_other_host(this->ike_sa);
327
328 message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
3e246c48 329 if (new_mid)
26b55dc6 330 {
73aaf76b
MW
331 this->rng->get_bytes(this->rng, sizeof(this->initiating.mid),
332 (void*)&this->initiating.mid);
26b55dc6 333 }
3e246c48 334 message->set_message_id(message, this->initiating.mid);
26b55dc6
MW
335 message->set_source(message, me->clone(me));
336 message->set_destination(message, other->clone(other));
337 message->set_exchange_type(message, exchange);
338 this->initiating.type = exchange;
339 this->initiating.retransmitted = 0;
340
341 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
342 while (enumerator->enumerate(enumerator, (void*)&task))
343 {
344 switch (task->build(task, message))
345 {
346 case SUCCESS:
347 /* task completed, remove it */
348 this->active_tasks->remove_at(this->active_tasks, enumerator);
349 task->destroy(task);
350 break;
351 case NEED_MORE:
352 /* processed, but task needs another exchange */
353 break;
354 case FAILED:
355 default:
356 if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
357 {
358 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
359 }
360 /* FALL */
361 case DESTROY_ME:
362 /* critical failure, destroy IKE_SA */
363 enumerator->destroy(enumerator);
364 message->destroy(message);
365 flush(this);
366 return DESTROY_ME;
367 }
368 }
369 enumerator->destroy(enumerator);
370
371 /* update exchange type if a task changed it */
372 this->initiating.type = message->get_exchange_type(message);
373
374 status = this->ike_sa->generate_message(this->ike_sa, message,
375 &this->initiating.packet);
376 if (status != SUCCESS)
377 {
378 /* message generation failed. There is nothing more to do than to
379 * close the SA */
380 message->destroy(message);
381 flush(this);
382 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
383 return DESTROY_ME;
384 }
385 message->destroy(message);
386
387 charon->sender->send(charon->sender,
388 this->initiating.packet->clone(this->initiating.packet));
389
390 return SUCCESS;
4a09d9ee
MW
391}
392
393/**
394 * handle exchange collisions
395 */
396static bool handle_collisions(private_task_manager_t *this, task_t *task)
397{
398 return FALSE;
399}
400
401/**
402 * build a response depending on the "passive" task list
403 */
404static status_t build_response(private_task_manager_t *this, message_t *request)
405{
406 enumerator_t *enumerator;
407 task_t *task;
408 message_t *message;
409 host_t *me, *other;
410 bool delete = FALSE;
411 status_t status;
412
413 me = request->get_destination(request);
414 other = request->get_source(request);
415
416 message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
417 message->set_exchange_type(message, request->get_exchange_type(request));
418 /* send response along the path the request came in */
419 message->set_source(message, me->clone(me));
420 message->set_destination(message, other->clone(other));
73aaf76b 421 message->set_message_id(message, request->get_message_id(request));
4a09d9ee
MW
422 message->set_request(message, FALSE);
423
424 enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
425 while (enumerator->enumerate(enumerator, (void*)&task))
426 {
427 switch (task->build(task, message))
428 {
429 case SUCCESS:
430 /* task completed, remove it */
431 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
432 if (!handle_collisions(this, task))
433 {
434 task->destroy(task);
435 }
436 break;
437 case NEED_MORE:
438 /* processed, but task needs another exchange */
439 if (handle_collisions(this, task))
440 {
441 this->passive_tasks->remove_at(this->passive_tasks,
442 enumerator);
443 }
444 break;
445 case FAILED:
446 default:
447 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
448 /* FALL */
449 case DESTROY_ME:
450 /* destroy IKE_SA, but SEND response first */
451 delete = TRUE;
452 break;
453 }
454 if (delete)
455 {
456 break;
457 }
458 }
459 enumerator->destroy(enumerator);
460
461 /* message complete, send it */
462 DESTROY_IF(this->responding.packet);
463 this->responding.packet = NULL;
464 status = this->ike_sa->generate_message(this->ike_sa, message,
465 &this->responding.packet);
466 message->destroy(message);
467 if (status != SUCCESS)
468 {
469 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
470 return DESTROY_ME;
471 }
472
473 charon->sender->send(charon->sender,
474 this->responding.packet->clone(this->responding.packet));
475 if (delete)
476 {
477 return DESTROY_ME;
478 }
479 return SUCCESS;
480}
481
482/**
483 * handle an incoming request message
484 */
485static status_t process_request(private_task_manager_t *this,
486 message_t *message)
487{
488 enumerator_t *enumerator;
489 task_t *task = NULL;
490
491 if (this->passive_tasks->get_count(this->passive_tasks) == 0)
492 { /* create tasks depending on request type, if not already some queued */
493 switch (message->get_exchange_type(message))
494 {
495 case ID_PROT:
a2f8fc97 496 task = (task_t *)ike_vendor_v1_create(this->ike_sa, FALSE);
01685247 497 this->passive_tasks->insert_last(this->passive_tasks, task);
c73c832c
MW
498 task = (task_t *)main_mode_create(this->ike_sa, FALSE);
499 this->passive_tasks->insert_last(this->passive_tasks, task);
4a09d9ee
MW
500 break;
501 case AGGRESSIVE:
502 /* TODO-IKEv1: agressive mode */
503 return FAILED;
504 case QUICK_MODE:
744c0801
MW
505 task = (task_t *)quick_mode_create(this->ike_sa, NULL,
506 NULL, NULL);
507 this->passive_tasks->insert_last(this->passive_tasks, task);
508 break;
4a09d9ee
MW
509 case INFORMATIONAL_V1:
510 /* TODO-IKEv1: informational */
511 return FAILED;
c5dc9d33
CO
512 case TRANSACTION:
513 task = (task_t *)xauth_request_create(this->ike_sa, FALSE);
514 this->passive_tasks->insert_last(this->passive_tasks, task);
515 break;
4a09d9ee
MW
516 default:
517 return FAILED;
518 }
519 }
520 /* let the tasks process the message */
521 enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
522 while (enumerator->enumerate(enumerator, (void*)&task))
523 {
524 switch (task->process(task, message))
525 {
526 case SUCCESS:
527 /* task completed, remove it */
528 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
529 task->destroy(task);
21b7db99
MW
530 enumerator->destroy(enumerator);
531 return SUCCESS;
4a09d9ee
MW
532 case NEED_MORE:
533 /* processed, but task needs at least another call to build() */
534 break;
535 case FAILED:
536 default:
537 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
538 /* FALL */
539 case DESTROY_ME:
540 /* critical failure, destroy IKE_SA */
541 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
542 enumerator->destroy(enumerator);
543 task->destroy(task);
544 return DESTROY_ME;
545 }
546 }
547 enumerator->destroy(enumerator);
548
e63cb7f8 549 return build_response(this, message);
4a09d9ee
MW
550}
551
26b55dc6
MW
552/**
553 * handle an incoming response message
554 */
555static status_t process_response(private_task_manager_t *this,
556 message_t *message)
557{
558 enumerator_t *enumerator;
559 task_t *task;
560
561 if (message->get_exchange_type(message) != this->initiating.type)
562 {
563 DBG1(DBG_IKE, "received %N response, but expected %N",
564 exchange_type_names, message->get_exchange_type(message),
565 exchange_type_names, this->initiating.type);
566 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
567 return DESTROY_ME;
568 }
569
570 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
571 while (enumerator->enumerate(enumerator, (void*)&task))
572 {
573 switch (task->process(task, message))
574 {
575 case SUCCESS:
576 /* task completed, remove it */
577 this->active_tasks->remove_at(this->active_tasks, enumerator);
578 task->destroy(task);
579 break;
580 case NEED_MORE:
581 /* processed, but task needs another exchange */
582 break;
583 case FAILED:
584 default:
585 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
586 /* FALL */
587 case DESTROY_ME:
588 /* critical failure, destroy IKE_SA */
589 this->active_tasks->remove_at(this->active_tasks, enumerator);
590 enumerator->destroy(enumerator);
591 task->destroy(task);
592 return DESTROY_ME;
593 }
594 }
595 enumerator->destroy(enumerator);
596
597 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
598 this->initiating.packet->destroy(this->initiating.packet);
599 this->initiating.packet = NULL;
600
601 return initiate(this);
602}
603
b235e69c
TB
604/**
605 * Send a notify in a separate INFORMATIONAL exchange back to the sender.
606 */
607static void send_notify_response(private_task_manager_t *this,
608 message_t *request, notify_type_t type,
609 chunk_t data)
610{
611 message_t *response;
612 packet_t *packet;
613 host_t *me, *other;
614 u_int32_t mid;
615
6be8d33d
TB
616 if (request->get_exchange_type(request) == INFORMATIONAL_V1)
617 { /* don't respond to INFORMATIONAL requests to avoid a notify war */
618 DBG1(DBG_IKE, "ignore malformed INFORMATIONAL request");
619 return;
620 }
621
b235e69c
TB
622 response = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
623 response->set_exchange_type(response, INFORMATIONAL_V1);
624 response->set_request(response, TRUE);
625 this->rng->get_bytes(this->rng, sizeof(mid), (void*)&mid);
626 response->set_message_id(response, mid);
627 response->add_notify(response, FALSE, type, data);
628 me = this->ike_sa->get_my_host(this->ike_sa);
629 if (me->is_anyaddr(me))
630 {
631 me = request->get_destination(request);
632 this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
633 }
634 other = this->ike_sa->get_other_host(this->ike_sa);
635 if (other->is_anyaddr(other))
636 {
637 other = request->get_source(request);
638 this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
639 }
640 response->set_source(response, me->clone(me));
641 response->set_destination(response, other->clone(other));
642 if (this->ike_sa->generate_message(this->ike_sa, response,
643 &packet) == SUCCESS)
644 {
645 charon->sender->send(charon->sender, packet);
646 }
647 response->destroy(response);
648}
649
650/**
651 * Parse the given message and verify that it is valid.
652 */
653static status_t parse_message(private_task_manager_t *this, message_t *msg)
654{
655 status_t status;
656
657 status = msg->parse_body(msg, this->ike_sa->get_keymat(this->ike_sa));
658
659 if (status != SUCCESS)
660 {
661 switch (status)
662 {
29a5e070
TB
663 case NOT_SUPPORTED:
664 DBG1(DBG_IKE, "unsupported exchange type");
665 send_notify_response(this, msg,
666 INVALID_EXCHANGE_TYPE, chunk_empty);
667 break;
b235e69c
TB
668 case PARSE_ERROR:
669 DBG1(DBG_IKE, "message parsing failed");
670 send_notify_response(this, msg,
671 PAYLOAD_MALFORMED, chunk_empty);
672 break;
673 case VERIFY_ERROR:
674 DBG1(DBG_IKE, "message verification failed");
675 send_notify_response(this, msg,
676 PAYLOAD_MALFORMED, chunk_empty);
677 break;
678 case FAILED:
679 DBG1(DBG_IKE, "integrity check failed");
680 send_notify_response(this, msg,
37639e94 681 INVALID_HASH_INFORMATION, chunk_empty);
b235e69c
TB
682 break;
683 case INVALID_STATE:
684 DBG1(DBG_IKE, "found encrypted message, but no keys available");
685 send_notify_response(this, msg,
686 PAYLOAD_MALFORMED, chunk_empty);
687 default:
688 break;
689 }
690 DBG1(DBG_IKE, "%N %s with message ID %d processing failed",
691 exchange_type_names, msg->get_exchange_type(msg),
692 msg->get_request(msg) ? "request" : "response",
693 msg->get_message_id(msg));
694
695 if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED)
696 { /* invalid initiation attempt, close SA */
697 return DESTROY_ME;
698 }
699 }
700 return status;
701}
702
4a09d9ee
MW
703METHOD(task_manager_t, process_message, status_t,
704 private_task_manager_t *this, message_t *msg)
705{
73aaf76b 706 u_int32_t hash, mid;
3d59c5c3 707 host_t *me, *other;
68c6863b 708 status_t status;
73aaf76b 709
1960312c 710 /* TODO-IKEv1: update hosts more selectively */
3d59c5c3
TB
711 me = msg->get_destination(msg);
712 other = msg->get_source(msg);
68c6863b 713 mid = msg->get_message_id(msg);
1960312c 714
73aaf76b
MW
715 if ((mid && mid == this->initiating.mid) ||
716 (this->initiating.mid == 0 &&
717 this->active_tasks->get_count(this->active_tasks)))
4a09d9ee 718 {
7519106d 719 msg->set_request(msg, FALSE);
b235e69c 720 status = parse_message(this, msg);
1960312c
TB
721 if (status != SUCCESS)
722 {
723 return status;
724 }
725 this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
726 time_monotonic(NULL));
3d59c5c3 727 this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
73aaf76b
MW
728 charon->bus->message(charon->bus, msg, FALSE);
729 if (process_response(this, msg) != SUCCESS)
4a09d9ee
MW
730 {
731 flush(this);
732 return DESTROY_ME;
733 }
734 }
735 else
736 {
9cc8bd4f
MW
737 hash = chunk_hash(msg->get_packet_data(msg));
738 if (hash == this->responding.hash)
73aaf76b
MW
739 {
740 DBG1(DBG_IKE, "received retransmit of request with ID %d, "
741 "retransmitting response", mid);
742 charon->sender->send(charon->sender,
743 this->responding.packet->clone(this->responding.packet));
744 return SUCCESS;
745 }
7519106d 746 msg->set_request(msg, TRUE);
b235e69c 747 status = parse_message(this, msg);
1960312c
TB
748 if (status != SUCCESS)
749 {
750 return status;
751 }
752 /* if this IKE_SA is virgin, we check for a config */
753 if (this->ike_sa->get_ike_cfg(this->ike_sa) == NULL)
754 {
755 ike_sa_id_t *ike_sa_id;
756 ike_cfg_t *ike_cfg;
757 job_t *job;
758 ike_cfg = charon->backends->get_ike_cfg(charon->backends, me, other);
759 if (ike_cfg == NULL)
760 {
761 /* no config found for these hosts, destroy */
4cfd0db8
TB
762 DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N",
763 me, other, notify_type_names, NO_PROPOSAL_CHOSEN);
764 send_notify_response(this, msg,
765 NO_PROPOSAL_CHOSEN, chunk_empty);
1960312c
TB
766 return DESTROY_ME;
767 }
768 this->ike_sa->set_ike_cfg(this->ike_sa, ike_cfg);
769 ike_cfg->destroy(ike_cfg);
770 /* add a timeout if peer does not establish it completely */
771 ike_sa_id = this->ike_sa->get_id(this->ike_sa);
772 job = (job_t*)delete_ike_sa_job_create(ike_sa_id, FALSE);
773 lib->scheduler->schedule_job(lib->scheduler, job,
774 lib->settings->get_int(lib->settings,
775 "charon.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT));
776 }
777 this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
778 time_monotonic(NULL));
3d59c5c3 779 this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
73aaf76b
MW
780 charon->bus->message(charon->bus, msg, TRUE);
781 if (process_request(this, msg) != SUCCESS)
26b55dc6
MW
782 {
783 flush(this);
784 return DESTROY_ME;
785 }
73aaf76b 786
73aaf76b 787 this->responding.mid = mid;
9cc8bd4f 788 this->responding.hash = hash;
4a09d9ee
MW
789 }
790 return SUCCESS;
791}
792
793METHOD(task_manager_t, queue_task, void,
794 private_task_manager_t *this, task_t *task)
795{
796 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
797 this->queued_tasks->insert_last(this->queued_tasks, task);
798}
799
800METHOD(task_manager_t, adopt_tasks, void,
801 private_task_manager_t *this, task_manager_t *other_public)
802{
803 private_task_manager_t *other = (private_task_manager_t*)other_public;
804 task_t *task;
805
806 /* move queued tasks from other to this */
807 while (other->queued_tasks->remove_last(other->queued_tasks,
808 (void**)&task) == SUCCESS)
809 {
810 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
811 task->migrate(task, this->ike_sa);
812 this->queued_tasks->insert_first(this->queued_tasks, task);
813 }
814}
815
816METHOD(task_manager_t, busy, bool,
817 private_task_manager_t *this)
818{
819 return (this->active_tasks->get_count(this->active_tasks) > 0);
820}
821
822METHOD(task_manager_t, incr_mid, void,
823 private_task_manager_t *this, bool initiate)
824{
4a09d9ee
MW
825}
826
827METHOD(task_manager_t, reset, void,
828 private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
829{
4a09d9ee
MW
830}
831
832METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
833 private_task_manager_t *this, task_queue_t queue)
834{
835 switch (queue)
836 {
837 case TASK_QUEUE_ACTIVE:
838 return this->active_tasks->create_enumerator(this->active_tasks);
839 case TASK_QUEUE_PASSIVE:
840 return this->passive_tasks->create_enumerator(this->passive_tasks);
841 case TASK_QUEUE_QUEUED:
842 return this->queued_tasks->create_enumerator(this->queued_tasks);
843 default:
844 return enumerator_create_empty();
845 }
846}
847
848METHOD(task_manager_t, destroy, void,
849 private_task_manager_t *this)
850{
851 flush(this);
852
853 this->active_tasks->destroy(this->active_tasks);
854 this->queued_tasks->destroy(this->queued_tasks);
855 this->passive_tasks->destroy(this->passive_tasks);
856
857 DESTROY_IF(this->responding.packet);
858 DESTROY_IF(this->initiating.packet);
73aaf76b 859 DESTROY_IF(this->rng);
4a09d9ee
MW
860 free(this);
861}
862
863/*
864 * see header file
865 */
866task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
867{
868 private_task_manager_t *this;
869
870 INIT(this,
871 .public = {
872 .task_manager = {
873 .process_message = _process_message,
874 .queue_task = _queue_task,
875 .initiate = _initiate,
876 .retransmit = _retransmit,
877 .incr_mid = _incr_mid,
878 .reset = _reset,
879 .adopt_tasks = _adopt_tasks,
880 .busy = _busy,
881 .create_task_enumerator = _create_task_enumerator,
882 .destroy = _destroy,
883 },
884 },
885 .ike_sa = ike_sa,
886 .initiating.type = EXCHANGE_TYPE_UNDEFINED,
73aaf76b 887 .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
4a09d9ee
MW
888 .queued_tasks = linked_list_create(),
889 .active_tasks = linked_list_create(),
890 .passive_tasks = linked_list_create(),
891 .retransmit_tries = lib->settings->get_int(lib->settings,
892 "charon.retransmit_tries", RETRANSMIT_TRIES),
893 .retransmit_timeout = lib->settings->get_double(lib->settings,
894 "charon.retransmit_timeout", RETRANSMIT_TIMEOUT),
895 .retransmit_base = lib->settings->get_double(lib->settings,
896 "charon.retransmit_base", RETRANSMIT_BASE),
897 );
898
899 return &this->public;
900}