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