Due to the exponential backoff a high number of retransmits only makes sense if retransmit_limit is set. However, even with that there was a problem. We first calculated the timeout for the next retransmit and only then compared that to the configured limit. Depending on the configured base and timeout the calculation overflowed the range of uint32_t after a relatively low number of retransmits (with the default values after 23) causing the timeout to first get lower (on a high level) before constantly resulting in 0 (with the default settings after 60 retransmits). Since that's obviously lower than any configured limit, all remaining retransmits were then sent without any delay, causing a lot of concurrent messages if the number of retransmits was high. This change determines the maximum number of retransmits until an overflow occurs based on the configuration and defaults to UINT32_MAX if that value is exceeded. Note that since the timeout is in milliseconds UINT32_MAX equals nearly 50 days. The calculation in task_manager_total_retransmit_timeout() uses a double variable and the result is in seconds so the maximum number would be higher there (with the default settings 1205). However, we want its result to be based on the actual IKE retransmission behavior.
83 lines
2.0 KiB
C
83 lines
2.0 KiB
C
/*
|
|
* Copyright (C) 2011 Tobias Brunner
|
|
* HSR Hochschule fuer Technik Rapperswil
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*/
|
|
|
|
#include "task_manager.h"
|
|
|
|
#include <math.h>
|
|
#include <sa/ikev1/task_manager_v1.h>
|
|
#include <sa/ikev2/task_manager_v2.h>
|
|
|
|
/*
|
|
* See header
|
|
*/
|
|
u_int task_manager_total_retransmit_timeout()
|
|
{
|
|
double timeout, base, limit = 0, total = 0;
|
|
int tries, max_tries = 0, i;
|
|
|
|
tries = lib->settings->get_int(lib->settings, "%s.retransmit_tries",
|
|
RETRANSMIT_TRIES, lib->ns);
|
|
base = lib->settings->get_double(lib->settings, "%s.retransmit_base",
|
|
RETRANSMIT_BASE, lib->ns);
|
|
timeout = lib->settings->get_double(lib->settings, "%s.retransmit_timeout",
|
|
RETRANSMIT_TIMEOUT, lib->ns);
|
|
limit = lib->settings->get_double(lib->settings, "%s.retransmit_limit",
|
|
0, lib->ns);
|
|
|
|
if (base > 1)
|
|
{
|
|
max_tries = log(UINT32_MAX/(1000.0 * timeout))/log(base);
|
|
}
|
|
|
|
for (i = 0; i <= tries; i++)
|
|
{
|
|
double interval = UINT32_MAX/1000.0;
|
|
if (max_tries && i <= max_tries)
|
|
{
|
|
interval = timeout * pow(base, i);
|
|
}
|
|
if (limit)
|
|
{
|
|
interval = min(interval, limit);
|
|
}
|
|
total += interval;
|
|
}
|
|
return (u_int)total;
|
|
}
|
|
|
|
/*
|
|
* See header
|
|
*/
|
|
task_manager_t *task_manager_create(ike_sa_t *ike_sa)
|
|
{
|
|
switch (ike_sa->get_version(ike_sa))
|
|
{
|
|
case IKEV1:
|
|
#ifdef USE_IKEV1
|
|
return &task_manager_v1_create(ike_sa)->task_manager;
|
|
#endif
|
|
break;
|
|
case IKEV2:
|
|
#ifdef USE_IKEV2
|
|
return &task_manager_v2_create(ike_sa)->task_manager;
|
|
#endif
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return NULL;
|
|
}
|
|
|