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