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