d5474d9627a4d351787dfa88a043aee643c224bf
[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 void migrate_tasks(linked_list_t *from, linked_list_t *to)
238 {
239 enumerator_t *enumerator;
240 task_t *task;
241
242 enumerator = from->create_enumerator(from);
243 while(enumerator->enumerate(enumerator, (void**)&task))
244 {
245 DBG4(DBG_IKE, " Migrating %N task to new queue", task_type_names, task->get_type(task));
246 if(task->swap_initiator)
247 {
248 task->swap_initiator(task);
249 }
250 to->insert_last(to, task);
251 from->remove_at(from, enumerator);
252 }
253 enumerator->destroy(enumerator);
254 }
255
256 METHOD(task_manager_t, initiate, status_t,
257 private_task_manager_t *this)
258 {
259 enumerator_t *enumerator;
260 task_t *task;
261 message_t *message;
262 host_t *me, *other;
263 status_t status;
264 exchange_type_t exchange = EXCHANGE_TYPE_UNDEFINED;
265 bool new_mid = FALSE;
266
267 if (!this->rng)
268 {
269 DBG1(DBG_IKE, "no RNG supported");
270 return FAILED;
271 }
272
273 if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
274 {
275 DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
276 exchange_type_names, this->initiating.type);
277 /* do not initiate if we already have a message in the air */
278 return SUCCESS;
279 }
280
281 if (this->active_tasks->get_count(this->active_tasks) == 0)
282 {
283 DBG2(DBG_IKE, "activating new tasks");
284 switch (this->ike_sa->get_state(this->ike_sa))
285 {
286 case IKE_CREATED:
287 if (activate_task(this, TASK_MAIN_MODE))
288 {
289 exchange = ID_PROT;
290 }
291 break;
292 case IKE_ESTABLISHED:
293 if (activate_task(this, TASK_QUICK_MODE))
294 {
295 exchange = QUICK_MODE;
296 new_mid = TRUE;
297 break;
298 }
299 if (activate_task(this, TASK_XAUTH_REQUEST))
300 {
301 exchange = TRANSACTION;
302 new_mid = TRUE;
303 break;
304 }
305 break;
306 default:
307 break;
308 }
309 }
310 else
311 {
312 DBG2(DBG_IKE, "reinitiating already active tasks");
313 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
314 while (enumerator->enumerate(enumerator, (void**)&task))
315 {
316 DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task));
317 switch (task->get_type(task))
318 {
319 case TASK_MAIN_MODE:
320 exchange = ID_PROT;
321 break;
322 case TASK_QUICK_MODE:
323 exchange = QUICK_MODE;
324 break;
325 case TASK_XAUTH_REQUEST:
326 exchange = TRANSACTION;
327 new_mid = TRUE;
328 break;
329 default:
330 continue;
331 }
332 break;
333 }
334 enumerator->destroy(enumerator);
335 }
336
337 if (exchange == EXCHANGE_TYPE_UNDEFINED)
338 {
339 DBG2(DBG_IKE, "nothing to initiate");
340 /* nothing to do yet... */
341 return SUCCESS;
342 }
343
344 me = this->ike_sa->get_my_host(this->ike_sa);
345 other = this->ike_sa->get_other_host(this->ike_sa);
346
347 message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
348 if (new_mid)
349 {
350 this->rng->get_bytes(this->rng, sizeof(this->initiating.mid),
351 (void*)&this->initiating.mid);
352 }
353 message->set_message_id(message, this->initiating.mid);
354 message->set_source(message, me->clone(me));
355 message->set_destination(message, other->clone(other));
356 message->set_exchange_type(message, exchange);
357 this->initiating.type = exchange;
358 this->initiating.retransmitted = 0;
359
360 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
361 while (enumerator->enumerate(enumerator, (void*)&task))
362 {
363 switch (task->build(task, message))
364 {
365 case SUCCESS:
366 /* task completed, remove it */
367 this->active_tasks->remove_at(this->active_tasks, enumerator);
368 task->destroy(task);
369 break;
370 case MIGRATE:
371 /* task completed, remove it */
372 this->active_tasks->remove_at(this->active_tasks, enumerator);
373 task->destroy(task);
374 /* migrate the remaining active tasks to the passive queue */
375 migrate_tasks(this->active_tasks, this->passive_tasks);
376 break;
377 case NEED_MORE:
378 /* processed, but task needs another exchange */
379 break;
380 case FAILED:
381 default:
382 if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
383 {
384 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
385 }
386 /* FALL */
387 case DESTROY_ME:
388 /* critical failure, destroy IKE_SA */
389 enumerator->destroy(enumerator);
390 message->destroy(message);
391 flush(this);
392 return DESTROY_ME;
393 }
394 }
395 enumerator->destroy(enumerator);
396
397 /* update exchange type if a task changed it */
398 this->initiating.type = message->get_exchange_type(message);
399
400 status = this->ike_sa->generate_message(this->ike_sa, message,
401 &this->initiating.packet);
402 if (status != SUCCESS)
403 {
404 /* message generation failed. There is nothing more to do than to
405 * close the SA */
406 message->destroy(message);
407 flush(this);
408 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
409 return DESTROY_ME;
410 }
411 message->destroy(message);
412
413 charon->sender->send(charon->sender,
414 this->initiating.packet->clone(this->initiating.packet));
415
416 return SUCCESS;
417 }
418
419 /**
420 * handle exchange collisions
421 */
422 static bool handle_collisions(private_task_manager_t *this, task_t *task)
423 {
424 return FALSE;
425 }
426
427 /**
428 * build a response depending on the "passive" task list
429 */
430 static status_t build_response(private_task_manager_t *this, message_t *request)
431 {
432 enumerator_t *enumerator;
433 task_t *task;
434 message_t *message;
435 host_t *me, *other;
436 bool delete = FALSE;
437 status_t status;
438 bool migrate = FALSE;
439
440 me = request->get_destination(request);
441 other = request->get_source(request);
442
443 message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
444 message->set_exchange_type(message, request->get_exchange_type(request));
445 /* send response along the path the request came in */
446 message->set_source(message, me->clone(me));
447 message->set_destination(message, other->clone(other));
448 message->set_message_id(message, request->get_message_id(request));
449 message->set_request(message, FALSE);
450
451 enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
452 while (enumerator->enumerate(enumerator, (void*)&task))
453 {
454 switch (task->build(task, message))
455 {
456 case MIGRATE:
457 migrate = TRUE;
458 /* FALL */
459 case SUCCESS:
460 /* task completed, remove it */
461 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
462 if (!handle_collisions(this, task))
463 {
464 task->destroy(task);
465 }
466 break;
467 case NEED_MORE:
468 /* processed, but task needs another exchange */
469 if (handle_collisions(this, task))
470 {
471 this->passive_tasks->remove_at(this->passive_tasks,
472 enumerator);
473 }
474 break;
475 case FAILED:
476 default:
477 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
478 /* FALL */
479 case DESTROY_ME:
480 /* destroy IKE_SA, but SEND response first */
481 delete = TRUE;
482 break;
483 }
484 if (delete)
485 {
486 break;
487 }
488 }
489 enumerator->destroy(enumerator);
490
491 /* message complete, send it */
492 DESTROY_IF(this->responding.packet);
493 this->responding.packet = NULL;
494 status = this->ike_sa->generate_message(this->ike_sa, message,
495 &this->responding.packet);
496 message->destroy(message);
497 if (status != SUCCESS)
498 {
499 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
500 return DESTROY_ME;
501 }
502
503 charon->sender->send(charon->sender,
504 this->responding.packet->clone(this->responding.packet));
505
506 if (migrate)
507 {
508 migrate_tasks(this->passive_tasks, this->queued_tasks);
509 /* Kick off the newly installed tasks */
510 initiate(this);
511 }
512
513 if (delete)
514 {
515 return DESTROY_ME;
516 }
517 return SUCCESS;
518 }
519
520 /**
521 * handle an incoming request message
522 */
523 static status_t process_request(private_task_manager_t *this,
524 message_t *message)
525 {
526 enumerator_t *enumerator;
527 task_t *task = NULL;
528 status_t process_status;
529
530 if (this->passive_tasks->get_count(this->passive_tasks) == 0)
531 { /* create tasks depending on request type, if not already some queued */
532 switch (message->get_exchange_type(message))
533 {
534 case ID_PROT:
535 task = (task_t *)ike_vendor_create(this->ike_sa, FALSE);
536 this->passive_tasks->insert_last(this->passive_tasks, task);
537 task = (task_t *)main_mode_create(this->ike_sa, FALSE);
538 this->passive_tasks->insert_last(this->passive_tasks, task);
539 break;
540 case AGGRESSIVE:
541 /* TODO-IKEv1: agressive mode */
542 return FAILED;
543 case QUICK_MODE:
544 task = (task_t *)quick_mode_create(this->ike_sa, NULL,
545 NULL, NULL);
546 this->passive_tasks->insert_last(this->passive_tasks, task);
547 break;
548 case INFORMATIONAL_V1:
549 /* TODO-IKEv1: informational */
550 return FAILED;
551 default:
552 return FAILED;
553 }
554 }
555 /* let the tasks process the message */
556 enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
557 while (enumerator->enumerate(enumerator, (void*)&task))
558 {
559 switch (task->process(task, message))
560 {
561 case SUCCESS:
562 /* task completed, remove it */
563 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
564 task->destroy(task);
565 enumerator->destroy(enumerator);
566 return SUCCESS;
567 case MIGRATE:
568 /* task completed, remove it */
569 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
570 task->destroy(task);
571 enumerator->destroy(enumerator);
572 /* migrate the remaining tasks */
573 migrate_tasks(this->passive_tasks, this->queued_tasks);
574 /* Kick off the newly installed tasks */
575 initiate(this);
576 return SUCCESS;
577 case NEED_MORE:
578 /* processed, but task needs at least another call to build() */
579 break;
580 case FAILED:
581 default:
582 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
583 /* FALL */
584 case DESTROY_ME:
585 /* critical failure, destroy IKE_SA */
586 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
587 enumerator->destroy(enumerator);
588 task->destroy(task);
589 return DESTROY_ME;
590 }
591 }
592 enumerator->destroy(enumerator);
593
594 process_status = build_response(this, message);
595
596 if(((process_status == SUCCESS) || (process_status == NEED_MORE)) && (this->initiate_later_flag == TRUE))
597 {
598 this->initiate_later_flag = FALSE;
599 return initiate(this);
600 }
601 return process_status;
602 }
603
604 /**
605 * handle an incoming response message
606 */
607 static status_t process_response(private_task_manager_t *this,
608 message_t *message)
609 {
610 enumerator_t *enumerator;
611 task_t *task;
612
613 if (message->get_exchange_type(message) != this->initiating.type)
614 {
615 DBG1(DBG_IKE, "received %N response, but expected %N",
616 exchange_type_names, message->get_exchange_type(message),
617 exchange_type_names, this->initiating.type);
618 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
619 return DESTROY_ME;
620 }
621
622 enumerator = this->active_tasks->create_enumerator(this->active_tasks);
623 while (enumerator->enumerate(enumerator, (void*)&task))
624 {
625 switch (task->process(task, message))
626 {
627 case SUCCESS:
628 /* task completed, remove it */
629 this->active_tasks->remove_at(this->active_tasks, enumerator);
630 task->destroy(task);
631 break;
632 case NEED_MORE:
633 /* processed, but task needs another exchange */
634 break;
635 case FAILED:
636 default:
637 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
638 /* FALL */
639 case DESTROY_ME:
640 /* critical failure, destroy IKE_SA */
641 this->active_tasks->remove_at(this->active_tasks, enumerator);
642 enumerator->destroy(enumerator);
643 task->destroy(task);
644 return DESTROY_ME;
645 }
646 }
647 enumerator->destroy(enumerator);
648
649 this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
650 this->initiating.packet->destroy(this->initiating.packet);
651 this->initiating.packet = NULL;
652
653 return initiate(this);
654 }
655
656 METHOD(task_manager_t, process_message, status_t,
657 private_task_manager_t *this, message_t *msg)
658 {
659 u_int32_t hash, mid;
660 host_t *me, *other;
661
662 mid = msg->get_message_id(msg);
663
664 /* TODO-IKEv1: update hosts more selectively */
665 me = msg->get_destination(msg);
666 other = msg->get_source(msg);
667
668 if ((mid && mid == this->initiating.mid) ||
669 (this->initiating.mid == 0 &&
670 this->active_tasks->get_count(this->active_tasks)))
671 {
672 this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
673 charon->bus->message(charon->bus, msg, FALSE);
674 if (process_response(this, msg) != SUCCESS)
675 {
676 flush(this);
677 return DESTROY_ME;
678 }
679 }
680 else
681 {
682 hash = chunk_hash(msg->get_packet_data(msg));
683 if (hash == this->responding.hash)
684 {
685 DBG1(DBG_IKE, "received retransmit of request with ID %d, "
686 "retransmitting response", mid);
687 charon->sender->send(charon->sender,
688 this->responding.packet->clone(this->responding.packet));
689 return SUCCESS;
690 }
691 this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
692 charon->bus->message(charon->bus, msg, TRUE);
693 if (process_request(this, msg) != SUCCESS)
694 {
695 flush(this);
696 return DESTROY_ME;
697 }
698
699 this->responding.mid = mid;
700 this->responding.hash = hash;
701 }
702 return SUCCESS;
703 }
704
705 METHOD(task_manager_t, queue_task, void,
706 private_task_manager_t *this, task_t *task)
707 {
708 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
709 this->queued_tasks->insert_last(this->queued_tasks, task);
710 }
711
712 METHOD(task_manager_t, adopt_tasks, void,
713 private_task_manager_t *this, task_manager_t *other_public)
714 {
715 private_task_manager_t *other = (private_task_manager_t*)other_public;
716 task_t *task;
717
718 /* move queued tasks from other to this */
719 while (other->queued_tasks->remove_last(other->queued_tasks,
720 (void**)&task) == SUCCESS)
721 {
722 DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
723 task->migrate(task, this->ike_sa);
724 this->queued_tasks->insert_first(this->queued_tasks, task);
725 }
726 }
727
728 METHOD(task_manager_t, busy, bool,
729 private_task_manager_t *this)
730 {
731 return (this->active_tasks->get_count(this->active_tasks) > 0);
732 }
733
734 METHOD(task_manager_t, incr_mid, void,
735 private_task_manager_t *this, bool initiate)
736 {
737 }
738
739 METHOD(task_manager_t, reset, void,
740 private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
741 {
742 }
743
744 METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
745 private_task_manager_t *this, task_queue_t queue)
746 {
747 switch (queue)
748 {
749 case TASK_QUEUE_ACTIVE:
750 return this->active_tasks->create_enumerator(this->active_tasks);
751 case TASK_QUEUE_PASSIVE:
752 return this->passive_tasks->create_enumerator(this->passive_tasks);
753 case TASK_QUEUE_QUEUED:
754 return this->queued_tasks->create_enumerator(this->queued_tasks);
755 default:
756 return enumerator_create_empty();
757 }
758 }
759
760 METHOD(task_manager_t, destroy, void,
761 private_task_manager_t *this)
762 {
763 flush(this);
764
765 this->active_tasks->destroy(this->active_tasks);
766 this->queued_tasks->destroy(this->queued_tasks);
767 this->passive_tasks->destroy(this->passive_tasks);
768
769 DESTROY_IF(this->responding.packet);
770 DESTROY_IF(this->initiating.packet);
771 DESTROY_IF(this->rng);
772 free(this);
773 }
774
775 METHOD(task_manager_t, initiate_later, void,
776 private_task_manager_t *this)
777 {
778 this->initiate_later_flag = TRUE;
779 }
780
781 /*
782 * see header file
783 */
784 task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
785 {
786 private_task_manager_t *this;
787
788 INIT(this,
789 .public = {
790 .task_manager = {
791 .process_message = _process_message,
792 .queue_task = _queue_task,
793 .initiate = _initiate,
794 .retransmit = _retransmit,
795 .incr_mid = _incr_mid,
796 .reset = _reset,
797 .adopt_tasks = _adopt_tasks,
798 .busy = _busy,
799 .create_task_enumerator = _create_task_enumerator,
800 .destroy = _destroy,
801 .initiate_later = _initiate_later,
802 },
803 },
804 .ike_sa = ike_sa,
805 .initiating.type = EXCHANGE_TYPE_UNDEFINED,
806 .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
807 .queued_tasks = linked_list_create(),
808 .active_tasks = linked_list_create(),
809 .passive_tasks = linked_list_create(),
810 .retransmit_tries = lib->settings->get_int(lib->settings,
811 "charon.retransmit_tries", RETRANSMIT_TRIES),
812 .retransmit_timeout = lib->settings->get_double(lib->settings,
813 "charon.retransmit_timeout", RETRANSMIT_TIMEOUT),
814 .retransmit_base = lib->settings->get_double(lib->settings,
815 "charon.retransmit_base", RETRANSMIT_BASE),
816 .initiate_later_flag = FALSE,
817 );
818
819 return &this->public;
820 }