32f847f8ac2158fdfb9a92852723967f325751d8
[strongswan.git] / src / libcharon / sa / task_manager_v1.c
1 /*
2 * Copyright (C) 2007 Tobias Brunner
3 * Copyright (C) 2007-2010 Martin Willi
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
19 #include <math.h>
20
21 #include <daemon.h>
22 #include <sa/tasks/ike_vendor.h>
23 #include <sa/tasks/main_mode.h>
24 #include <sa/tasks/quick_mode.h>
25 #include <processing/jobs/retransmit_job.h>
26
27 typedef struct exchange_t exchange_t;
28
29 /**
30 * An exchange in the air, used do detect and handle retransmission
31 */
32 struct exchange_t {
33
34 /**
35 * Message ID used for this transaction
36 */
37 u_int32_t mid;
38
39 /**
40 * generated packet for retransmission
41 */
42 packet_t *packet;
43 };
44
45 typedef struct private_task_manager_t private_task_manager_t;
46
47 /**
48 * private data of the task manager
49 */
50 struct private_task_manager_t {
51
52 /**
53 * public functions
54 */
55 task_manager_v1_t public;
56
57 /**
58 * associated IKE_SA we are serving
59 */
60 ike_sa_t *ike_sa;
61
62 /**
63 * RNG to create message IDs
64 */
65 rng_t *rng;
66
67 /**
68 * Exchange we are currently handling as responder
69 */
70 struct {
71 /**
72 * Message ID of the exchange
73 */
74 u_int32_t mid;
75
76 /**
77 * Hash of a previously received message
78 */
79 u_int32_t hash;
80
81 /**
82 * packet for retransmission
83 */
84 packet_t *packet;
85
86 } responding;
87
88 /**
89 * Exchange we are currently handling as initiator
90 */
91 struct {
92 /**
93 * Message ID of the exchange
94 */
95 u_int32_t mid;
96
97 /**
98 * Hash of a previously received message
99 */
100 u_int32_t hash;
101
102 /**
103 * how many times we have retransmitted so far
104 */
105 u_int retransmitted;
106
107 /**
108 * packet for retransmission
109 */
110 packet_t *packet;
111
112 /**
113 * type of the initated exchange
114 */
115 exchange_type_t type;
116
117 } initiating;
118
119 /**
120 * List of queued tasks not yet in action
121 */
122 linked_list_t *queued_tasks;
123
124 /**
125 * List of active tasks, initiated by ourselve
126 */
127 linked_list_t *active_tasks;
128
129 /**
130 * List of tasks initiated by peer
131 */
132 linked_list_t *passive_tasks;
133
134 /**
135 * Number of times we retransmit messages before giving up
136 */
137 u_int retransmit_tries;
138
139 /**
140 * Retransmission timeout
141 */
142 double retransmit_timeout;
143
144 /**
145 * Base to calculate retransmission timeout
146 */
147 double retransmit_base;
148
149 /**
150 * Signal to the task manager that we need to initiate a transaction after the response is sent.
151 */
152 bool initiate_later_flag;
153 };
154
155 /**
156 * flush all tasks in the task manager
157 */
158 static void flush(private_task_manager_t *this)
159 {
160 this->queued_tasks->destroy_offset(this->queued_tasks,
161 offsetof(task_t, destroy));
162 this->queued_tasks = linked_list_create();
163 this->passive_tasks->destroy_offset(this->passive_tasks,
164 offsetof(task_t, destroy));
165 this->passive_tasks = linked_list_create();
166 this->active_tasks->destroy_offset(this->active_tasks,
167 offsetof(task_t, destroy));
168 this->active_tasks = linked_list_create();
169 }
170
171 /**
172 * move a task of a specific type from the queue to the active list
173 */
174 static bool activate_task(private_task_manager_t *this, task_type_t type)
175 {
176 enumerator_t *enumerator;
177 task_t *task;
178 bool found = FALSE;
179
180 enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
181 while (enumerator->enumerate(enumerator, (void**)&task))
182 {
183 if (task->get_type(task) == type)
184 {
185 DBG2(DBG_IKE, " activating %N task", task_type_names, type);
186 this->queued_tasks->remove_at(this->queued_tasks, enumerator);
187 this->active_tasks->insert_last(this->active_tasks, task);
188 found = TRUE;
189 break;
190 }
191 }
192 enumerator->destroy(enumerator);
193 return found;
194 }
195
196 METHOD(task_manager_t, retransmit, status_t,
197 private_task_manager_t *this, u_int32_t message_id)
198 {
199 if (message_id == this->initiating.mid)
200 {
201 u_int32_t timeout;
202 packet_t *packet;
203 job_t *job;
204
205 if (this->initiating.retransmitted <= this->retransmit_tries)
206 {
207 timeout = (u_int32_t)(this->retransmit_timeout * 1000.0 *
208 pow(this->retransmit_base, this->initiating.retransmitted));
209 }
210 else
211 {
212 DBG1(DBG_IKE, "giving up after %d retransmits",
213 this->initiating.retransmitted - 1);
214 if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
215 {
216 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
217 }
218 return DESTROY_ME;
219 }
220
221 if (this->initiating.retransmitted)
222 {
223 DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
224 this->initiating.retransmitted, message_id);
225 }
226 packet = this->initiating.packet->clone(this->initiating.packet);
227 charon->sender->send(charon->sender, packet);
228
229 this->initiating.retransmitted++;
230 job = (job_t*)retransmit_job_create(this->initiating.mid,
231 this->ike_sa->get_id(this->ike_sa));
232 lib->scheduler->schedule_job_ms(lib->scheduler, job, timeout);
233 }
234 return SUCCESS;
235 }
236
237 METHOD(task_manager_t, initiate, status_t,
238 private_task_manager_t *this)
239 {
240 enumerator_t *enumerator;
241 task_t *task;
242 message_t *message;
243 host_t *me, *other;
244 status_t status;
245 exchange_type_t exchange = EXCHANGE_TYPE_UNDEFINED;
246 bool new_mid = FALSE;
247
248 if (!this->rng)
249 {
250 DBG1(DBG_IKE, "no RNG supported");
251 return FAILED;
252 }
253
254 if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
255 {
256 DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
257 exchange_type_names, this->initiating.type);
258 /* do not initiate if we already have a message in the air */
259 return SUCCESS;
260 }
261
262 if (this->active_tasks->get_count(this->active_tasks) == 0)
263 {
264 DBG2(DBG_IKE, "activating new tasks");
265 switch (this->ike_sa->get_state(this->ike_sa))
266 {
267 case IKE_CREATED:
268 if (activate_task(this, TASK_MAIN_MODE))
269 {
270 exchange = ID_PROT;
271 }
272 break;
273 case IKE_ESTABLISHED:
274 if (activate_task(this, TASK_QUICK_MODE))
275 {
276 exchange = QUICK_MODE;
277 new_mid = TRUE;
278 break;
279 }
280 if (activate_task(this, TASK_XAUTH_REQUEST))
281 {
282 exchange = TRANSACTION;
283 new_mid = TRUE;
284 break;
285 }
286 break;
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 {
300 case TASK_MAIN_MODE:
301 exchange = ID_PROT;
302 break;
303 case TASK_QUICK_MODE:
304 exchange = QUICK_MODE;
305 break;
306 case TASK_XAUTH_REQUEST:
307 exchange = TRANSACTION;
308 new_mid = TRUE;
309 break;
310 default:
311 continue;
312 }
313 break;
314 }
315 enumerator->destroy(enumerator);
316 }
317
318 if (exchange == EXCHANGE_TYPE_UNDEFINED)
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);
329 if (new_mid)
330 {
331 this->rng->get_bytes(this->rng, sizeof(this->initiating.mid),
332 (void*)&this->initiating.mid);
333 }
334 message->set_message_id(message, this->initiating.mid);
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;
391 }
392
393 /**
394 * handle exchange collisions
395 */
396 static 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 */
404 static 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));
421 message->set_message_id(message, request->get_message_id(request));
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 */
485 static status_t process_request(private_task_manager_t *this,
486 message_t *message)
487 {
488 enumerator_t *enumerator;
489 task_t *task = NULL;
490 status_t process_status;
491
492 if (this->passive_tasks->get_count(this->passive_tasks) == 0)
493 { /* create tasks depending on request type, if not already some queued */
494 switch (message->get_exchange_type(message))
495 {
496 case ID_PROT:
497 task = (task_t *)ike_vendor_create(this->ike_sa, FALSE);
498 this->passive_tasks->insert_last(this->passive_tasks, task);
499 task = (task_t *)main_mode_create(this->ike_sa, FALSE);
500 this->passive_tasks->insert_last(this->passive_tasks, task);
501 break;
502 case AGGRESSIVE:
503 /* TODO-IKEv1: agressive mode */
504 return FAILED;
505 case QUICK_MODE:
506 task = (task_t *)quick_mode_create(this->ike_sa, NULL,
507 NULL, NULL);
508 this->passive_tasks->insert_last(this->passive_tasks, task);
509 break;
510 case INFORMATIONAL_V1:
511 /* TODO-IKEv1: informational */
512 return FAILED;
513 default:
514 return FAILED;
515 }
516 }
517 /* let the tasks process the message */
518 enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
519 while (enumerator->enumerate(enumerator, (void*)&task))
520 {
521 switch (task->process(task, message))
522 {
523 case SUCCESS:
524 /* task completed, remove it */
525 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
526 task->destroy(task);
527 enumerator->destroy(enumerator);
528 return SUCCESS;
529 case NEED_MORE:
530 /* processed, but task needs at least another call to build() */
531 break;
532 case FAILED:
533 default:
534 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
535 /* FALL */
536 case DESTROY_ME:
537 /* critical failure, destroy IKE_SA */
538 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
539 enumerator->destroy(enumerator);
540 task->destroy(task);
541 return DESTROY_ME;
542 }
543 }
544 enumerator->destroy(enumerator);
545
546 process_status = build_response(this, message);
547
548 if(((process_status == SUCCESS) || (process_status == NEED_MORE)) && (this->initiate_later_flag == TRUE))
549 {
550 this->initiate_later_flag = FALSE;
551 return initiate(this);
552 }
553 return process_status;
554 }
555
556 /**
557 * handle an incoming response message
558 */
559 static status_t process_response(private_task_manager_t *this,
560 message_t *message)
561 {
562 enumerator_t *enumerator;
563 task_t *task;
564
565 if (message->get_exchange_type(message) != this->initiating.type)
566 {
567 DBG1(DBG_IKE, "received %N response, but expected %N",
568 exchange_type_names, message->get_exchange_type(message),
569 exchange_type_names, this->initiating.type);
570 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
571 return DESTROY_ME;
572 }
573
574 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
575 while (enumerator->enumerate(enumerator, (void*)&task))
576 {
577 switch (task->process(task, message))
578 {
579 case SUCCESS:
580 /* task completed, remove it */
581 this->active_tasks->remove_at(this->active_tasks, enumerator);
582 task->destroy(task);
583 break;
584 case NEED_MORE:
585 /* processed, but task needs another exchange */
586 break;
587 case FAILED:
588 default:
589 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
590 /* FALL */
591 case DESTROY_ME:
592 /* critical failure, destroy IKE_SA */
593 this->active_tasks->remove_at(this->active_tasks, enumerator);
594 enumerator->destroy(enumerator);
595 task->destroy(task);
596 return DESTROY_ME;
597 }
598 }
599 enumerator->destroy(enumerator);
600
601 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
602 this->initiating.packet->destroy(this->initiating.packet);
603 this->initiating.packet = NULL;
604
605 return initiate(this);
606 }
607
608 METHOD(task_manager_t, process_message, status_t,
609 private_task_manager_t *this, message_t *msg)
610 {
611 u_int32_t hash, mid;
612 host_t *me, *other;
613
614 mid = msg->get_message_id(msg);
615
616 /* TODO-IKEv1: update hosts more selectively */
617 me = msg->get_destination(msg);
618 other = msg->get_source(msg);
619
620 if ((mid && mid == this->initiating.mid) ||
621 (this->initiating.mid == 0 &&
622 this->active_tasks->get_count(this->active_tasks)))
623 {
624 this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
625 charon->bus->message(charon->bus, msg, FALSE);
626 if (process_response(this, msg) != SUCCESS)
627 {
628 flush(this);
629 return DESTROY_ME;
630 }
631 }
632 else
633 {
634 hash = chunk_hash(msg->get_packet_data(msg));
635 if (hash == this->responding.hash)
636 {
637 DBG1(DBG_IKE, "received retransmit of request with ID %d, "
638 "retransmitting response", mid);
639 charon->sender->send(charon->sender,
640 this->responding.packet->clone(this->responding.packet));
641 return SUCCESS;
642 }
643 this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
644 charon->bus->message(charon->bus, msg, TRUE);
645 if (process_request(this, msg) != SUCCESS)
646 {
647 flush(this);
648 return DESTROY_ME;
649 }
650
651 this->responding.mid = mid;
652 this->responding.hash = hash;
653 }
654 return SUCCESS;
655 }
656
657 METHOD(task_manager_t, queue_task, void,
658 private_task_manager_t *this, task_t *task)
659 {
660 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
661 this->queued_tasks->insert_last(this->queued_tasks, task);
662 }
663
664 METHOD(task_manager_t, adopt_tasks, void,
665 private_task_manager_t *this, task_manager_t *other_public)
666 {
667 private_task_manager_t *other = (private_task_manager_t*)other_public;
668 task_t *task;
669
670 /* move queued tasks from other to this */
671 while (other->queued_tasks->remove_last(other->queued_tasks,
672 (void**)&task) == SUCCESS)
673 {
674 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
675 task->migrate(task, this->ike_sa);
676 this->queued_tasks->insert_first(this->queued_tasks, task);
677 }
678 }
679
680 METHOD(task_manager_t, busy, bool,
681 private_task_manager_t *this)
682 {
683 return (this->active_tasks->get_count(this->active_tasks) > 0);
684 }
685
686 METHOD(task_manager_t, incr_mid, void,
687 private_task_manager_t *this, bool initiate)
688 {
689 }
690
691 METHOD(task_manager_t, reset, void,
692 private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
693 {
694 }
695
696 METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
697 private_task_manager_t *this, task_queue_t queue)
698 {
699 switch (queue)
700 {
701 case TASK_QUEUE_ACTIVE:
702 return this->active_tasks->create_enumerator(this->active_tasks);
703 case TASK_QUEUE_PASSIVE:
704 return this->passive_tasks->create_enumerator(this->passive_tasks);
705 case TASK_QUEUE_QUEUED:
706 return this->queued_tasks->create_enumerator(this->queued_tasks);
707 default:
708 return enumerator_create_empty();
709 }
710 }
711
712 METHOD(task_manager_t, destroy, void,
713 private_task_manager_t *this)
714 {
715 flush(this);
716
717 this->active_tasks->destroy(this->active_tasks);
718 this->queued_tasks->destroy(this->queued_tasks);
719 this->passive_tasks->destroy(this->passive_tasks);
720
721 DESTROY_IF(this->responding.packet);
722 DESTROY_IF(this->initiating.packet);
723 DESTROY_IF(this->rng);
724 free(this);
725 }
726
727 METHOD(task_manager_t, initiate_later, void,
728 private_task_manager_t *this)
729 {
730 this->initiate_later_flag = TRUE;
731 }
732
733 /*
734 * see header file
735 */
736 task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
737 {
738 private_task_manager_t *this;
739
740 INIT(this,
741 .public = {
742 .task_manager = {
743 .process_message = _process_message,
744 .queue_task = _queue_task,
745 .initiate = _initiate,
746 .retransmit = _retransmit,
747 .incr_mid = _incr_mid,
748 .reset = _reset,
749 .adopt_tasks = _adopt_tasks,
750 .busy = _busy,
751 .create_task_enumerator = _create_task_enumerator,
752 .destroy = _destroy,
753 .initiate_later = _initiate_later,
754 },
755 },
756 .ike_sa = ike_sa,
757 .initiating.type = EXCHANGE_TYPE_UNDEFINED,
758 .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
759 .queued_tasks = linked_list_create(),
760 .active_tasks = linked_list_create(),
761 .passive_tasks = linked_list_create(),
762 .retransmit_tries = lib->settings->get_int(lib->settings,
763 "charon.retransmit_tries", RETRANSMIT_TRIES),
764 .retransmit_timeout = lib->settings->get_double(lib->settings,
765 "charon.retransmit_timeout", RETRANSMIT_TIMEOUT),
766 .retransmit_base = lib->settings->get_double(lib->settings,
767 "charon.retransmit_base", RETRANSMIT_BASE),
768 .initiate_later_flag = FALSE,
769 );
770
771 return &this->public;
772 }