some cleanups
[strongswan.git] / src / charon / sa / task_manager.c
1 /**
2 * @file task_manager.c
3 *
4 * @brief Implementation of task_manager_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2007 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include "task_manager.h"
24
25 #include <daemon.h>
26 #include <sa/tasks/ike_init.h>
27 #include <sa/tasks/ike_natd.h>
28 #include <sa/tasks/ike_auth.h>
29 #include <sa/tasks/ike_cert.h>
30 #include <sa/tasks/ike_rekey.h>
31 #include <sa/tasks/ike_delete.h>
32 #include <sa/tasks/ike_config.h>
33 #include <sa/tasks/ike_dpd.h>
34 #include <sa/tasks/child_create.h>
35 #include <sa/tasks/child_rekey.h>
36 #include <sa/tasks/child_delete.h>
37 #include <encoding/payloads/delete_payload.h>
38 #include <queues/jobs/retransmit_job.h>
39
40 typedef struct exchange_t exchange_t;
41
42 /**
43 * An exchange in the air, used do detect and handle retransmission
44 */
45 struct exchange_t {
46
47 /**
48 * Message ID used for this transaction
49 */
50 u_int32_t mid;
51
52 /**
53 * generated packet for retransmission
54 */
55 packet_t *packet;
56 };
57
58 typedef struct private_task_manager_t private_task_manager_t;
59
60 /**
61 * private data of the task manager
62 */
63 struct private_task_manager_t {
64
65 /**
66 * public functions
67 */
68 task_manager_t public;
69
70 /**
71 * associated IKE_SA we are serving
72 */
73 ike_sa_t *ike_sa;
74
75 /**
76 * Exchange we are currently handling as responder
77 */
78 struct {
79 /**
80 * Message ID of the exchange
81 */
82 u_int32_t mid;
83
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
100 /**
101 * how many times we have retransmitted so far
102 */
103 u_int retransmitted;
104
105 /**
106 * packet for retransmission
107 */
108 packet_t *packet;
109
110 /**
111 * type of the initated exchange
112 */
113 exchange_type_t type;
114
115 } initiating;
116
117 /**
118 * List of queued tasks not yet in action
119 */
120 linked_list_t *queued_tasks;
121
122 /**
123 * List of active tasks, initiated by ourselve
124 */
125 linked_list_t *active_tasks;
126
127 /**
128 * List of tasks initiated by peer
129 */
130 linked_list_t *passive_tasks;
131
132 /**
133 * ike_sa_init message we sent, stored here for later authentication
134 */
135 packet_t *ike_sa_init;
136 };
137
138 /**
139 * move a task of a specific type from the queue to the active list
140 */
141 static bool activate_task(private_task_manager_t *this, task_type_t type)
142 {
143 iterator_t *iterator;
144 task_t *task;
145 bool found = FALSE;
146
147 iterator = this->queued_tasks->create_iterator(this->queued_tasks, TRUE);
148 while (iterator->iterate(iterator, (void**)&task))
149 {
150 if (task->get_type(task) == type)
151 {
152 DBG2(DBG_IKE, " activating %N task", task_type_names, type);
153 iterator->remove(iterator);
154 this->active_tasks->insert_last(this->active_tasks, task);
155 found = TRUE;
156 break;
157 }
158 }
159 iterator->destroy(iterator);
160 return found;
161 }
162
163 /**
164 * Implementation of task_manager_t.retransmit
165 */
166 static status_t retransmit(private_task_manager_t *this, u_int32_t message_id)
167 {
168 if (message_id == this->initiating.mid)
169 {
170 u_int32_t timeout;
171 job_t *job;
172
173 timeout = charon->configuration->get_retransmit_timeout(
174 charon->configuration, this->initiating.retransmitted);
175 if (timeout == 0)
176 {
177 DBG1(DBG_IKE, "giving up after %d retransmits",
178 this->initiating.retransmitted - 1);
179 return DESTROY_ME;
180 }
181
182 if (this->initiating.retransmitted)
183 {
184 DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
185 this->initiating.retransmitted, message_id);
186 }
187 this->initiating.retransmitted++;
188
189 charon->send_queue->add(charon->send_queue,
190 this->initiating.packet->clone(this->initiating.packet));
191 job = (job_t*)retransmit_job_create(this->initiating.mid,
192 this->ike_sa->get_id(this->ike_sa));
193 charon->event_queue->add_relative(charon->event_queue, job, timeout);
194 }
195 return SUCCESS;
196 }
197
198 /**
199 * build a request using the active task list
200 * Implementation of task_manager_t.initiate
201 */
202 static status_t build_request(private_task_manager_t *this)
203 {
204 iterator_t *iterator;
205 task_t *task;
206 message_t *message;
207 status_t status;
208 exchange_type_t exchange = 0;
209
210 if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
211 {
212 DBG2(DBG_IKE, "delaying task initiation, exchange in progress");
213 /* do not initiate if we already have a message in the air */
214 return SUCCESS;
215 }
216
217 if (this->active_tasks->get_count(this->active_tasks) == 0)
218 {
219 DBG2(DBG_IKE, "activating new tasks");
220 switch (this->ike_sa->get_state(this->ike_sa))
221 {
222 case IKE_CREATED:
223 if (activate_task(this, IKE_INIT))
224 {
225 exchange = IKE_SA_INIT;
226 activate_task(this, IKE_NATD);
227 activate_task(this, IKE_CERT);
228 activate_task(this, IKE_AUTHENTICATE);
229 activate_task(this, IKE_CONFIG);
230 activate_task(this, CHILD_CREATE);
231 }
232 break;
233 case IKE_ESTABLISHED:
234 if (activate_task(this, CHILD_CREATE))
235 {
236 exchange = CREATE_CHILD_SA;
237 activate_task(this, IKE_CONFIG);
238 break;
239 }
240 if (activate_task(this, CHILD_DELETE))
241 {
242 exchange = INFORMATIONAL;
243 break;
244 }
245 if (activate_task(this, CHILD_REKEY))
246 {
247 exchange = CREATE_CHILD_SA;
248 break;
249 }
250 if (activate_task(this, IKE_DELETE))
251 {
252 exchange = INFORMATIONAL;
253 break;
254 }
255 if (activate_task(this, IKE_REKEY))
256 {
257 exchange = CREATE_CHILD_SA;
258 break;
259 }
260 if (activate_task(this, IKE_DEADPEER))
261 {
262 exchange = INFORMATIONAL;
263 break;
264 }
265 case IKE_REKEYING:
266 if (activate_task(this, IKE_DELETE))
267 {
268 exchange = INFORMATIONAL;
269 break;
270 }
271 case IKE_DELETING:
272 default:
273 break;
274 }
275 }
276 else
277 {
278 DBG2(DBG_IKE, "reinitiating already active tasks");
279 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
280 while (iterator->iterate(iterator, (void**)&task))
281 {
282 DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
283 switch (task->get_type(task))
284 {
285 case IKE_INIT:
286 exchange = IKE_SA_INIT;
287 break;
288 case IKE_AUTHENTICATE:
289 exchange = IKE_AUTH;
290 break;
291 default:
292 continue;
293 }
294 break;
295 }
296 iterator->destroy(iterator);
297 }
298
299 if (exchange == 0)
300 {
301 DBG2(DBG_IKE, "nothing to initiate");
302 /* nothing to do yet... */
303 return SUCCESS;
304 }
305
306 message = message_create();
307 message->set_message_id(message, this->initiating.mid);
308 message->set_exchange_type(message, exchange);
309 this->initiating.type = exchange;
310 this->initiating.retransmitted = 0;
311
312 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
313 while (iterator->iterate(iterator, (void*)&task))
314 {
315 switch (task->build(task, message))
316 {
317 case SUCCESS:
318 /* task completed, remove it */
319 iterator->remove(iterator);
320 task->destroy(task);
321 break;
322 case NEED_MORE:
323 /* processed, but task needs another exchange */
324 break;
325 case FAILED:
326 default:
327 /* critical failure, destroy IKE_SA */
328 iterator->destroy(iterator);
329 message->destroy(message);
330 return DESTROY_ME;
331 }
332 }
333 iterator->destroy(iterator);
334
335 DESTROY_IF(this->initiating.packet);
336 status = this->ike_sa->generate_message(this->ike_sa, message,
337 &this->initiating.packet);
338 message->destroy(message);
339 if (status != SUCCESS)
340 {
341 /* message generation failed. There is nothing more to do than to
342 * close the SA */
343 return DESTROY_ME;
344 }
345
346 return retransmit(this, this->initiating.mid);
347 }
348
349 /**
350 * handle an incoming response message
351 */
352 static status_t process_response(private_task_manager_t *this,
353 message_t *message)
354 {
355 iterator_t *iterator;
356 task_t *task;
357
358 if (message->get_exchange_type(message) != this->initiating.type)
359 {
360 DBG1(DBG_IKE, "received %N response, but expected %N",
361 exchange_type_names, message->get_exchange_type(message),
362 exchange_type_names, this->initiating.type);
363 return DESTROY_ME;
364 }
365
366 iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
367 while (iterator->iterate(iterator, (void*)&task))
368 {
369 switch (task->process(task, message))
370 {
371 case SUCCESS:
372 /* task completed, remove it */
373 iterator->remove(iterator);
374 task->destroy(task);
375 break;
376 case NEED_MORE:
377 /* processed, but task needs another exchange */
378 break;
379 case FAILED:
380 default:
381 /* critical failure, destroy IKE_SA */
382 iterator->destroy(iterator);
383 return DESTROY_ME;
384 }
385 }
386 iterator->destroy(iterator);
387
388 this->initiating.mid++;
389 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
390
391 return build_request(this);
392 }
393
394 /**
395 * build a response depending on the "passive" task list
396 */
397 static status_t build_response(private_task_manager_t *this,
398 exchange_type_t exchange)
399 {
400 iterator_t *iterator;
401 task_t *task;
402 message_t *message;
403 bool delete = FALSE;
404 status_t status;
405
406 message = message_create();
407 message->set_exchange_type(message, exchange);
408 message->set_message_id(message, this->responding.mid);
409 message->set_request(message, FALSE);
410
411 iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
412 while (iterator->iterate(iterator, (void*)&task))
413 {
414 switch (task->build(task, message))
415 {
416 case SUCCESS:
417 /* task completed, remove it */
418 iterator->remove(iterator);
419 task->destroy(task);
420 break;
421 case NEED_MORE:
422 /* processed, but task needs another exchange */
423 break;
424 case FAILED:
425 default:
426 /* destroy IKE_SA, but SEND response first */
427 delete = TRUE;
428 break;
429 }
430 if (delete)
431 {
432 break;
433 }
434 }
435 iterator->destroy(iterator);
436
437 /* remove resonder SPI if IKE_SA_INIT failed */
438 if (delete && exchange == IKE_SA_INIT)
439 {
440 ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa);
441 id->set_responder_spi(id, 0);
442 }
443
444 /* message complete, send it */
445 DESTROY_IF(this->responding.packet);
446 status = this->ike_sa->generate_message(this->ike_sa, message,
447 &this->responding.packet);
448 message->destroy(message);
449 if (status != SUCCESS)
450 {
451 return DESTROY_ME;
452 }
453
454 charon->send_queue->add(charon->send_queue,
455 this->responding.packet->clone(this->responding.packet));
456 if (delete)
457 {
458 return DESTROY_ME;
459 }
460 return SUCCESS;
461 }
462
463 /**
464 * handle an incoming request message
465 */
466 static status_t process_request(private_task_manager_t *this,
467 message_t *message)
468 {
469 iterator_t *iterator;
470 task_t *task = NULL;
471 exchange_type_t exchange;
472 payload_t *payload;
473 notify_payload_t *notify;
474
475 exchange = message->get_exchange_type(message);
476
477 /* create tasks depending on request type */
478 switch (exchange)
479 {
480 case IKE_SA_INIT:
481 {
482 task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL);
483 this->passive_tasks->insert_last(this->passive_tasks, task);
484 task = (task_t*)ike_natd_create(this->ike_sa, FALSE);
485 this->passive_tasks->insert_last(this->passive_tasks, task);
486 task = (task_t*)ike_cert_create(this->ike_sa, FALSE);
487 this->passive_tasks->insert_last(this->passive_tasks, task);
488 task = (task_t*)ike_config_create(this->ike_sa, NULL);
489 this->passive_tasks->insert_last(this->passive_tasks, task);
490 task = (task_t*)ike_auth_create(this->ike_sa, FALSE);
491 this->passive_tasks->insert_last(this->passive_tasks, task);
492 task = (task_t*)child_create_create(this->ike_sa, NULL);
493 this->passive_tasks->insert_last(this->passive_tasks, task);
494 break;
495 }
496 case CREATE_CHILD_SA:
497 {
498 bool notify_found = FALSE, ts_found = FALSE;
499 iterator = message->get_payload_iterator(message);
500 while (iterator->iterate(iterator, (void**)&payload))
501 {
502 switch (payload->get_type(payload))
503 {
504 case NOTIFY:
505 {
506 /* if we find a rekey notify, its CHILD_SA rekeying */
507 notify = (notify_payload_t*)payload;
508 if (notify->get_notify_type(notify) == REKEY_SA &&
509 (notify->get_protocol_id(notify) == PROTO_AH ||
510 notify->get_protocol_id(notify) == PROTO_ESP))
511 {
512 notify_found = TRUE;
513 }
514 break;
515 }
516 case TRAFFIC_SELECTOR_INITIATOR:
517 case TRAFFIC_SELECTOR_RESPONDER:
518 {
519 /* if we don't find a TS, its IKE rekeying */
520 ts_found = TRUE;
521 break;
522 }
523 default:
524 break;
525 }
526 }
527 iterator->destroy(iterator);
528
529 if (ts_found)
530 {
531 if (notify_found)
532 {
533 task = (task_t*)child_rekey_create(this->ike_sa, NULL);
534 }
535 else
536 {
537 task = (task_t*)child_create_create(this->ike_sa, NULL);
538 }
539 }
540 else
541 {
542 task = (task_t*)ike_rekey_create(this->ike_sa, FALSE);
543 }
544 this->passive_tasks->insert_last(this->passive_tasks, task);
545
546 break;
547 }
548 case INFORMATIONAL:
549 {
550 delete_payload_t *delete;
551
552 delete = (delete_payload_t*)message->get_payload(message, DELETE);
553 if (delete)
554 {
555 if (delete->get_protocol_id(delete) == PROTO_IKE)
556 {
557 task = (task_t*)ike_delete_create(this->ike_sa, FALSE);
558 this->passive_tasks->insert_last(this->passive_tasks, task);
559 }
560 else
561 {
562 task = (task_t*)child_delete_create(this->ike_sa, NULL);
563 this->passive_tasks->insert_last(this->passive_tasks, task);
564 }
565 }
566 else
567 {
568 task = (task_t*)ike_dpd_create(FALSE);
569 this->passive_tasks->insert_last(this->passive_tasks, task);
570 }
571 break;
572 }
573 default:
574 break;
575 }
576
577 /* let the tasks process the message */
578 iterator = this->passive_tasks->create_iterator(this->passive_tasks, TRUE);
579 while (iterator->iterate(iterator, (void*)&task))
580 {
581 switch (task->process(task, message))
582 {
583 case SUCCESS:
584 /* task completed, remove it */
585 iterator->remove(iterator);
586 task->destroy(task);
587 break;
588 case NEED_MORE:
589 /* processed, but task needs at least another call to build() */
590 break;
591 case FAILED:
592 default:
593 /* critical failure, destroy IKE_SA */
594 iterator->destroy(iterator);
595 return DESTROY_ME;
596 }
597 }
598 iterator->destroy(iterator);
599
600 return build_response(this, exchange);
601 }
602
603 /**
604 * Implementation of task_manager_t.process_message
605 */
606 static status_t process_message(private_task_manager_t *this, message_t *msg)
607 {
608 u_int32_t mid = msg->get_message_id(msg);
609
610 if (msg->get_request(msg))
611 {
612 if (mid == this->responding.mid)
613 {
614 if (process_request(this, msg) != SUCCESS)
615 {
616 return DESTROY_ME;
617 }
618 this->responding.mid++;
619 }
620 else if ((mid == this->responding.mid - 1) && this->responding.packet)
621 {
622 DBG1(DBG_IKE, "received retransmit of request with ID %d, "
623 "retransmitting response", mid);
624 charon->send_queue->add(charon->send_queue,
625 this->responding.packet->clone(
626 this->responding.packet));
627 }
628 else
629 {
630 DBG1(DBG_IKE, "received message ID %d, excepted %d. Ignored",
631 mid, this->responding.mid);
632 }
633 }
634 else
635 {
636 if (mid == this->initiating.mid)
637 {
638 if (process_response(this, msg) != SUCCESS)
639 {
640 return DESTROY_ME;
641 }
642 }
643 else
644 {
645 DBG1(DBG_IKE, "received message ID %d, excepted %d. Ignored",
646 mid, this->initiating.mid);
647 return SUCCESS;
648 }
649 }
650 return SUCCESS;
651 }
652
653 /**
654 * Implementation of task_manager_t.queue_task
655 */
656 static void queue_task(private_task_manager_t *this, task_t *task)
657 {
658 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
659 this->queued_tasks->insert_last(this->queued_tasks, task);
660 }
661
662 /**
663 * Implementation of task_manager_t.adopt_tasks
664 */
665 static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *other)
666 {
667 task_t *task;
668
669 /* move queued tasks from other to this */
670 while (other->queued_tasks->remove_last(other->queued_tasks,
671 (void**)&task) == SUCCESS)
672 {
673 task->migrate(task, this->ike_sa);
674 this->queued_tasks->insert_first(this->queued_tasks, task);
675 }
676
677 /* reset active tasks and move them to others queued tasks */
678 while (other->active_tasks->remove_last(other->active_tasks,
679 (void**)&task) == SUCCESS)
680 {
681 task->migrate(task, this->ike_sa);
682 this->queued_tasks->insert_first(this->queued_tasks, task);
683 }
684 }
685
686 /**
687 * Implementation of task_manager_t.busy
688 */
689 static bool busy(private_task_manager_t *this)
690 {
691 return (this->active_tasks->get_count(this->active_tasks) > 0);
692 }
693
694 /**
695 * Implementation of task_manager_t.reset
696 */
697 static void reset(private_task_manager_t *this)
698 {
699 task_t *task;
700
701 /* reset message counters and retransmit packets */
702 DESTROY_IF(this->responding.packet);
703 DESTROY_IF(this->initiating.packet);
704 DESTROY_IF(this->ike_sa_init);
705 this->responding.packet = NULL;
706 this->initiating.packet = NULL;
707 this->ike_sa_init = NULL;
708 this->responding.mid = 0;
709 this->initiating.mid = -1;
710
711 /* reset active tasks */
712 while (this->active_tasks->remove_last(this->active_tasks,
713 (void**)&task) == SUCCESS)
714 {
715 task->migrate(task, this->ike_sa);
716 this->queued_tasks->insert_first(this->queued_tasks, task);
717 }
718 }
719
720 /**
721 * Implementation of task_manager_t.destroy
722 */
723 static void destroy(private_task_manager_t *this)
724 {
725 task_t *task;
726
727 this->queued_tasks->destroy_offset(this->queued_tasks,
728 offsetof(task_t, destroy));
729 this->passive_tasks->destroy_offset(this->passive_tasks,
730 offsetof(task_t, destroy));
731
732 /* emmit outstanding signals for tasks */
733 while (this->active_tasks->remove_last(this->active_tasks,
734 (void**)&task) == SUCCESS)
735 {
736 switch (task->get_type(task))
737 {
738 case IKE_AUTH:
739 SIG(IKE_UP_FAILED, "establishing IKE_SA failed");
740 break;
741 case IKE_DELETE:
742 SIG(IKE_DOWN_FAILED, "deleting IKE_SA properly failed");
743 break;
744 case IKE_REKEY:
745 SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed");
746 break;
747 case CHILD_CREATE:
748 SIG(CHILD_UP_FAILED, "establishing CHILD_SA failed");
749 break;
750 case CHILD_DELETE:
751 SIG(CHILD_DOWN_FAILED, "deleting CHILD_SA failed");
752 break;
753 case CHILD_REKEY:
754 SIG(IKE_REKEY_FAILED, "rekeying CHILD_SA failed");
755 break;
756 default:
757 break;
758 }
759 task->destroy(task);
760 }
761 this->active_tasks->destroy(this->active_tasks);
762 DESTROY_IF(this->responding.packet);
763 DESTROY_IF(this->initiating.packet);
764 DESTROY_IF(this->ike_sa_init);
765 free(this);
766 }
767
768 /*
769 * see header file
770 */
771 task_manager_t *task_manager_create(ike_sa_t *ike_sa)
772 {
773 private_task_manager_t *this = malloc_thing(private_task_manager_t);
774
775 this->public.process_message = (status_t(*)(task_manager_t*,message_t*))process_message;
776 this->public.queue_task = (void(*)(task_manager_t*,task_t*))queue_task;
777 this->public.initiate = (status_t(*)(task_manager_t*))build_request;
778 this->public.retransmit = (status_t(*)(task_manager_t*,u_int32_t))retransmit;
779 this->public.reset = (void(*)(task_manager_t*))reset;
780 this->public.adopt_tasks = (void(*)(task_manager_t*,task_manager_t*))adopt_tasks;
781 this->public.busy = (bool(*)(task_manager_t*))busy;
782 this->public.destroy = (void(*)(task_manager_t*))destroy;
783
784 this->ike_sa = ike_sa;
785 this->responding.packet = NULL;
786 this->initiating.packet = NULL;
787 this->responding.mid = 0;
788 this->initiating.mid = 0;
789 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
790 this->queued_tasks = linked_list_create();
791 this->active_tasks = linked_list_create();
792 this->passive_tasks = linked_list_create();
793 this->ike_sa_init = NULL;
794
795 return &this->public;
796 }