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