Generate a new mid only after we start a new task (and exchange)
[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 <daemon.h>
20 #include <sa/tasks/main_mode.h>
21 #include <sa/tasks/quick_mode.h>
22
23 typedef struct exchange_t exchange_t;
24
25 /**
26 * An exchange in the air, used do detect and handle retransmission
27 */
28 struct exchange_t {
29
30 /**
31 * Message ID used for this transaction
32 */
33 u_int32_t mid;
34
35 /**
36 * generated packet for retransmission
37 */
38 packet_t *packet;
39 };
40
41 typedef struct private_task_manager_t private_task_manager_t;
42
43 /**
44 * private data of the task manager
45 */
46 struct private_task_manager_t {
47
48 /**
49 * public functions
50 */
51 task_manager_v1_t public;
52
53 /**
54 * associated IKE_SA we are serving
55 */
56 ike_sa_t *ike_sa;
57
58 /**
59 * RNG to create message IDs
60 */
61 rng_t *rng;
62
63 /**
64 * Exchange we are currently handling as responder
65 */
66 struct {
67 /**
68 * Message ID of the exchange
69 */
70 u_int32_t mid;
71
72 /**
73 * Hash of a previously received message
74 */
75 u_int32_t hash;
76
77 /**
78 * packet for retransmission
79 */
80 packet_t *packet;
81
82 } responding;
83
84 /**
85 * Exchange we are currently handling as initiator
86 */
87 struct {
88 /**
89 * Message ID of the exchange
90 */
91 u_int32_t mid;
92
93 /**
94 * Hash of a previously received message
95 */
96 u_int32_t hash;
97
98 /**
99 * how many times we have retransmitted so far
100 */
101 u_int retransmitted;
102
103 /**
104 * packet for retransmission
105 */
106 packet_t *packet;
107
108 /**
109 * type of the initated exchange
110 */
111 exchange_type_t type;
112
113 } initiating;
114
115 /**
116 * List of queued tasks not yet in action
117 */
118 linked_list_t *queued_tasks;
119
120 /**
121 * List of active tasks, initiated by ourselve
122 */
123 linked_list_t *active_tasks;
124
125 /**
126 * List of tasks initiated by peer
127 */
128 linked_list_t *passive_tasks;
129
130 /**
131 * Number of times we retransmit messages before giving up
132 */
133 u_int retransmit_tries;
134
135 /**
136 * Retransmission timeout
137 */
138 double retransmit_timeout;
139
140 /**
141 * Base to calculate retransmission timeout
142 */
143 double retransmit_base;
144 };
145
146 /**
147 * flush all tasks in the task manager
148 */
149 static void flush(private_task_manager_t *this)
150 {
151 this->queued_tasks->destroy_offset(this->queued_tasks,
152 offsetof(task_t, destroy));
153 this->queued_tasks = linked_list_create();
154 this->passive_tasks->destroy_offset(this->passive_tasks,
155 offsetof(task_t, destroy));
156 this->passive_tasks = linked_list_create();
157 this->active_tasks->destroy_offset(this->active_tasks,
158 offsetof(task_t, destroy));
159 this->active_tasks = linked_list_create();
160 }
161
162 /**
163 * move a task of a specific type from the queue to the active list
164 */
165 static bool activate_task(private_task_manager_t *this, task_type_t type)
166 {
167 enumerator_t *enumerator;
168 task_t *task;
169 bool found = FALSE;
170
171 enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
172 while (enumerator->enumerate(enumerator, (void**)&task))
173 {
174 if (task->get_type(task) == type)
175 {
176 DBG2(DBG_IKE, " activating %N task", task_type_names, type);
177 this->queued_tasks->remove_at(this->queued_tasks, enumerator);
178 this->active_tasks->insert_last(this->active_tasks, task);
179 found = TRUE;
180 break;
181 }
182 }
183 enumerator->destroy(enumerator);
184 return found;
185 }
186
187 METHOD(task_manager_t, retransmit, status_t,
188 private_task_manager_t *this, u_int32_t message_id)
189 {
190 if (message_id == this->initiating.mid)
191 {
192 u_int32_t timeout;
193 job_t *job;
194 enumerator_t *enumerator;
195 packet_t *packet;
196 task_t *task;
197
198 if (this->initiating.retransmitted <= this->retransmit_tries)
199 {
200 timeout = (u_int32_t)(this->retransmit_timeout * 1000.0 *
201 pow(this->retransmit_base, this->initiating.retransmitted));
202 }
203 else
204 {
205 DBG1(DBG_IKE, "giving up after %d retransmits",
206 this->initiating.retransmitted - 1);
207 if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
208 {
209 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
210 }
211 return DESTROY_ME;
212 }
213
214 if (this->initiating.retransmitted)
215 {
216 DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
217 this->initiating.retransmitted, message_id);
218 }
219 packet = this->initiating.packet->clone(this->initiating.packet);
220 charon->sender->send(charon->sender, packet);
221
222 this->initiating.retransmitted++;
223 job = (job_t*)retransmit_job_create(this->initiating.mid,
224 this->ike_sa->get_id(this->ike_sa));
225 lib->scheduler->schedule_job_ms(lib->scheduler, job, timeout);
226 }
227 return SUCCESS;
228 }
229
230 METHOD(task_manager_t, initiate, status_t,
231 private_task_manager_t *this)
232 {
233 enumerator_t *enumerator;
234 task_t *task;
235 message_t *message;
236 host_t *me, *other;
237 status_t status;
238 exchange_type_t exchange = EXCHANGE_TYPE_UNDEFINED;
239 bool new_mid = FALSE;
240
241 if (!this->rng)
242 {
243 DBG1(DBG_IKE, "no RNG supported");
244 return FAILED;
245 }
246
247 if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
248 {
249 DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
250 exchange_type_names, this->initiating.type);
251 /* do not initiate if we already have a message in the air */
252 return SUCCESS;
253 }
254
255 if (this->active_tasks->get_count(this->active_tasks) == 0)
256 {
257 DBG2(DBG_IKE, "activating new tasks");
258 switch (this->ike_sa->get_state(this->ike_sa))
259 {
260 case IKE_CREATED:
261 if (activate_task(this, TASK_MAIN_MODE))
262 {
263 exchange = ID_PROT;
264 }
265 break;
266 case IKE_ESTABLISHED:
267 if (activate_task(this, TASK_QUICK_MODE))
268 {
269 exchange = QUICK_MODE;
270 new_mid = TRUE;
271 break;
272 }
273 if (activate_task(this, TASK_XAUTH_REQUEST))
274 {
275 exchange = TRANSACTION;
276 new_mid = TRUE;
277 break;
278 }
279 break;
280 default:
281 break;
282 }
283 }
284 else
285 {
286 DBG2(DBG_IKE, "reinitiating already active tasks");
287 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
288 while (enumerator->enumerate(enumerator, (void**)&task))
289 {
290 DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
291 switch (task->get_type(task))
292 {
293 case TASK_MAIN_MODE:
294 exchange = ID_PROT;
295 break;
296 case TASK_QUICK_MODE:
297 exchange = QUICK_MODE;
298 break;
299 default:
300 continue;
301 }
302 break;
303 }
304 enumerator->destroy(enumerator);
305 }
306
307 if (exchange == EXCHANGE_TYPE_UNDEFINED)
308 {
309 DBG2(DBG_IKE, "nothing to initiate");
310 /* nothing to do yet... */
311 return SUCCESS;
312 }
313
314 me = this->ike_sa->get_my_host(this->ike_sa);
315 other = this->ike_sa->get_other_host(this->ike_sa);
316
317 message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
318 if (new_mid)
319 {
320 this->rng->get_bytes(this->rng, sizeof(this->initiating.mid),
321 (void*)&this->initiating.mid);
322 }
323 message->set_message_id(message, this->initiating.mid);
324 message->set_source(message, me->clone(me));
325 message->set_destination(message, other->clone(other));
326 message->set_exchange_type(message, exchange);
327 this->initiating.type = exchange;
328 this->initiating.retransmitted = 0;
329
330 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
331 while (enumerator->enumerate(enumerator, (void*)&task))
332 {
333 switch (task->build(task, message))
334 {
335 case SUCCESS:
336 /* task completed, remove it */
337 this->active_tasks->remove_at(this->active_tasks, enumerator);
338 task->destroy(task);
339 break;
340 case NEED_MORE:
341 /* processed, but task needs another exchange */
342 break;
343 case FAILED:
344 default:
345 if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
346 {
347 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
348 }
349 /* FALL */
350 case DESTROY_ME:
351 /* critical failure, destroy IKE_SA */
352 enumerator->destroy(enumerator);
353 message->destroy(message);
354 flush(this);
355 return DESTROY_ME;
356 }
357 }
358 enumerator->destroy(enumerator);
359
360 /* update exchange type if a task changed it */
361 this->initiating.type = message->get_exchange_type(message);
362
363 status = this->ike_sa->generate_message(this->ike_sa, message,
364 &this->initiating.packet);
365 if (status != SUCCESS)
366 {
367 /* message generation failed. There is nothing more to do than to
368 * close the SA */
369 message->destroy(message);
370 flush(this);
371 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
372 return DESTROY_ME;
373 }
374 message->destroy(message);
375
376 charon->sender->send(charon->sender,
377 this->initiating.packet->clone(this->initiating.packet));
378
379 return SUCCESS;
380 }
381
382 /**
383 * handle exchange collisions
384 */
385 static bool handle_collisions(private_task_manager_t *this, task_t *task)
386 {
387 return FALSE;
388 }
389
390 /**
391 * build a response depending on the "passive" task list
392 */
393 static status_t build_response(private_task_manager_t *this, message_t *request)
394 {
395 enumerator_t *enumerator;
396 task_t *task;
397 message_t *message;
398 host_t *me, *other;
399 bool delete = FALSE;
400 status_t status;
401
402 me = request->get_destination(request);
403 other = request->get_source(request);
404
405 message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
406 message->set_exchange_type(message, request->get_exchange_type(request));
407 /* send response along the path the request came in */
408 message->set_source(message, me->clone(me));
409 message->set_destination(message, other->clone(other));
410 message->set_message_id(message, request->get_message_id(request));
411 message->set_request(message, FALSE);
412
413 enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
414 while (enumerator->enumerate(enumerator, (void*)&task))
415 {
416 switch (task->build(task, message))
417 {
418 case SUCCESS:
419 /* task completed, remove it */
420 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
421 if (!handle_collisions(this, task))
422 {
423 task->destroy(task);
424 }
425 break;
426 case NEED_MORE:
427 /* processed, but task needs another exchange */
428 if (handle_collisions(this, task))
429 {
430 this->passive_tasks->remove_at(this->passive_tasks,
431 enumerator);
432 }
433 break;
434 case FAILED:
435 default:
436 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
437 /* FALL */
438 case DESTROY_ME:
439 /* destroy IKE_SA, but SEND response first */
440 delete = TRUE;
441 break;
442 }
443 if (delete)
444 {
445 break;
446 }
447 }
448 enumerator->destroy(enumerator);
449
450 /* message complete, send it */
451 DESTROY_IF(this->responding.packet);
452 this->responding.packet = NULL;
453 status = this->ike_sa->generate_message(this->ike_sa, message,
454 &this->responding.packet);
455 message->destroy(message);
456 if (status != SUCCESS)
457 {
458 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
459 return DESTROY_ME;
460 }
461
462 charon->sender->send(charon->sender,
463 this->responding.packet->clone(this->responding.packet));
464 if (delete)
465 {
466 return DESTROY_ME;
467 }
468 return SUCCESS;
469 }
470
471 /**
472 * handle an incoming request message
473 */
474 static status_t process_request(private_task_manager_t *this,
475 message_t *message)
476 {
477 enumerator_t *enumerator;
478 task_t *task = NULL;
479
480 if (this->passive_tasks->get_count(this->passive_tasks) == 0)
481 { /* create tasks depending on request type, if not already some queued */
482 switch (message->get_exchange_type(message))
483 {
484 case ID_PROT:
485 task = (task_t *)main_mode_create(this->ike_sa, FALSE);
486 this->passive_tasks->insert_last(this->passive_tasks, task);
487 break;
488 case AGGRESSIVE:
489 /* TODO-IKEv1: agressive mode */
490 return FAILED;
491 case QUICK_MODE:
492 task = (task_t *)quick_mode_create(this->ike_sa, NULL,
493 NULL, NULL);
494 this->passive_tasks->insert_last(this->passive_tasks, task);
495 break;
496 case INFORMATIONAL_V1:
497 /* TODO-IKEv1: informational */
498 return FAILED;
499 default:
500 return FAILED;
501 }
502 }
503 /* let the tasks process the message */
504 enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
505 while (enumerator->enumerate(enumerator, (void*)&task))
506 {
507 switch (task->process(task, message))
508 {
509 case SUCCESS:
510 /* task completed, remove it */
511 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
512 task->destroy(task);
513 enumerator->destroy(enumerator);
514 return SUCCESS;
515 case NEED_MORE:
516 /* processed, but task needs at least another call to build() */
517 break;
518 case FAILED:
519 default:
520 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
521 /* FALL */
522 case DESTROY_ME:
523 /* critical failure, destroy IKE_SA */
524 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
525 enumerator->destroy(enumerator);
526 task->destroy(task);
527 return DESTROY_ME;
528 }
529 }
530 enumerator->destroy(enumerator);
531
532 return build_response(this, message);
533 }
534
535 /**
536 * handle an incoming response message
537 */
538 static status_t process_response(private_task_manager_t *this,
539 message_t *message)
540 {
541 enumerator_t *enumerator;
542 task_t *task;
543
544 if (message->get_exchange_type(message) != this->initiating.type)
545 {
546 DBG1(DBG_IKE, "received %N response, but expected %N",
547 exchange_type_names, message->get_exchange_type(message),
548 exchange_type_names, this->initiating.type);
549 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
550 return DESTROY_ME;
551 }
552
553 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
554 while (enumerator->enumerate(enumerator, (void*)&task))
555 {
556 switch (task->process(task, message))
557 {
558 case SUCCESS:
559 /* task completed, remove it */
560 this->active_tasks->remove_at(this->active_tasks, enumerator);
561 task->destroy(task);
562 break;
563 case NEED_MORE:
564 /* processed, but task needs another exchange */
565 break;
566 case FAILED:
567 default:
568 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
569 /* FALL */
570 case DESTROY_ME:
571 /* critical failure, destroy IKE_SA */
572 this->active_tasks->remove_at(this->active_tasks, enumerator);
573 enumerator->destroy(enumerator);
574 task->destroy(task);
575 return DESTROY_ME;
576 }
577 }
578 enumerator->destroy(enumerator);
579
580 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
581 this->initiating.packet->destroy(this->initiating.packet);
582 this->initiating.packet = NULL;
583
584 return initiate(this);
585 }
586
587 METHOD(task_manager_t, process_message, status_t,
588 private_task_manager_t *this, message_t *msg)
589 {
590 u_int32_t hash, mid;
591 host_t *me, *other;
592
593 mid = msg->get_message_id(msg);
594
595 /* TODO-IKEv1: update hosts more selectively */
596 me = msg->get_destination(msg);
597 other = msg->get_source(msg);
598
599 if ((mid && mid == this->initiating.mid) ||
600 (this->initiating.mid == 0 &&
601 this->active_tasks->get_count(this->active_tasks)))
602 {
603 this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
604 charon->bus->message(charon->bus, msg, FALSE);
605 if (process_response(this, msg) != SUCCESS)
606 {
607 flush(this);
608 return DESTROY_ME;
609 }
610 }
611 else
612 {
613 hash = chunk_hash(msg->get_packet_data(msg));
614 if (hash == this->responding.hash)
615 {
616 DBG1(DBG_IKE, "received retransmit of request with ID %d, "
617 "retransmitting response", mid);
618 charon->sender->send(charon->sender,
619 this->responding.packet->clone(this->responding.packet));
620 return SUCCESS;
621 }
622 this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
623 charon->bus->message(charon->bus, msg, TRUE);
624 if (process_request(this, msg) != SUCCESS)
625 {
626 flush(this);
627 return DESTROY_ME;
628 }
629
630 this->responding.mid = mid;
631 this->responding.hash = hash;
632 }
633 return SUCCESS;
634 }
635
636 METHOD(task_manager_t, queue_task, void,
637 private_task_manager_t *this, task_t *task)
638 {
639 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
640 this->queued_tasks->insert_last(this->queued_tasks, task);
641 }
642
643 METHOD(task_manager_t, adopt_tasks, void,
644 private_task_manager_t *this, task_manager_t *other_public)
645 {
646 private_task_manager_t *other = (private_task_manager_t*)other_public;
647 task_t *task;
648
649 /* move queued tasks from other to this */
650 while (other->queued_tasks->remove_last(other->queued_tasks,
651 (void**)&task) == SUCCESS)
652 {
653 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
654 task->migrate(task, this->ike_sa);
655 this->queued_tasks->insert_first(this->queued_tasks, task);
656 }
657 }
658
659 METHOD(task_manager_t, busy, bool,
660 private_task_manager_t *this)
661 {
662 return (this->active_tasks->get_count(this->active_tasks) > 0);
663 }
664
665 METHOD(task_manager_t, incr_mid, void,
666 private_task_manager_t *this, bool initiate)
667 {
668 }
669
670 METHOD(task_manager_t, reset, void,
671 private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
672 {
673 }
674
675 METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
676 private_task_manager_t *this, task_queue_t queue)
677 {
678 switch (queue)
679 {
680 case TASK_QUEUE_ACTIVE:
681 return this->active_tasks->create_enumerator(this->active_tasks);
682 case TASK_QUEUE_PASSIVE:
683 return this->passive_tasks->create_enumerator(this->passive_tasks);
684 case TASK_QUEUE_QUEUED:
685 return this->queued_tasks->create_enumerator(this->queued_tasks);
686 default:
687 return enumerator_create_empty();
688 }
689 }
690
691 METHOD(task_manager_t, destroy, void,
692 private_task_manager_t *this)
693 {
694 flush(this);
695
696 this->active_tasks->destroy(this->active_tasks);
697 this->queued_tasks->destroy(this->queued_tasks);
698 this->passive_tasks->destroy(this->passive_tasks);
699
700 DESTROY_IF(this->responding.packet);
701 DESTROY_IF(this->initiating.packet);
702 DESTROY_IF(this->rng);
703 free(this);
704 }
705
706 /*
707 * see header file
708 */
709 task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
710 {
711 private_task_manager_t *this;
712
713 INIT(this,
714 .public = {
715 .task_manager = {
716 .process_message = _process_message,
717 .queue_task = _queue_task,
718 .initiate = _initiate,
719 .retransmit = _retransmit,
720 .incr_mid = _incr_mid,
721 .reset = _reset,
722 .adopt_tasks = _adopt_tasks,
723 .busy = _busy,
724 .create_task_enumerator = _create_task_enumerator,
725 .destroy = _destroy,
726 },
727 },
728 .ike_sa = ike_sa,
729 .initiating.type = EXCHANGE_TYPE_UNDEFINED,
730 .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
731 .queued_tasks = linked_list_create(),
732 .active_tasks = linked_list_create(),
733 .passive_tasks = linked_list_create(),
734 .retransmit_tries = lib->settings->get_int(lib->settings,
735 "charon.retransmit_tries", RETRANSMIT_TRIES),
736 .retransmit_timeout = lib->settings->get_double(lib->settings,
737 "charon.retransmit_timeout", RETRANSMIT_TIMEOUT),
738 .retransmit_base = lib->settings->get_double(lib->settings,
739 "charon.retransmit_base", RETRANSMIT_BASE),
740 );
741
742 return &this->public;
743 }