summaryrefslogtreecommitdiff
path: root/src/dhcpv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dhcpv6.c')
-rwxr-xr-x[-rw-r--r--]src/dhcpv6.c77
1 files changed, 49 insertions, 28 deletions
diff --git a/src/dhcpv6.c b/src/dhcpv6.c
index 5f8029f..db9feb6 100644..100755
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -105,25 +105,37 @@ static void clear_timer(struct connman_dhcpv6 *dhcp)
}
}
-static inline float get_random(void)
+static inline guint get_random(void)
{
- return (rand() % 200 - 100) / 1000.0;
+ uint64_t val;
+
+ __connman_util_get_random(&val);
+
+ /* Make sure the value is always positive so strip MSB */
+ return ((uint32_t)val) >> 1;
+}
+
+static guint compute_random(guint val)
+{
+ return val - val / 10 +
+ (get_random() % (2 * 1000)) * val / 10 / 1000;
}
/* Calculate a random delay, RFC 3315 chapter 14 */
/* RT and MRT are milliseconds */
static guint calc_delay(guint RT, guint MRT)
{
- float delay = get_random();
- float rt = RT * (2 + delay);
+ if (MRT && (RT > MRT / 2))
+ RT = compute_random(MRT);
+ else
+ RT += compute_random(RT);
- if (rt > MRT)
- rt = MRT * (1 + delay);
-
- if (rt < 0)
- rt = MRT;
+ return RT;
+}
- return (guint)rt;
+static guint initial_rt(guint timeout)
+{
+ return compute_random(timeout);
}
static void free_prefix(gpointer data)
@@ -493,7 +505,7 @@ static int set_other_addresses(GDHCPClient *dhcp_client,
for (i = 0, list = option; list;
list = list->next, i++)
domains[i] = g_strdup(list->data);
- __connman_service_update_search_domains(service, domains);
+ __connman_service_set_search_domains(service, domains);
g_strfreev(domains);
}
}
@@ -1095,7 +1107,7 @@ static void re_cb(enum request_type req_type, GDHCPClient *dhcp_client,
if (!option) {
switch (req_type) {
case REQ_REQUEST:
- dhcpv6_request(dhcp, true);
+ do_resend_request(dhcp);
break;
case REQ_REBIND:
dhcpv6_rebind(dhcp);
@@ -1220,7 +1232,7 @@ static gboolean start_rebind(gpointer user_data)
if (check_restart(dhcp) < 0)
return FALSE;
- dhcp->RT = REB_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REB_TIMEOUT);
DBG("rebind initial RT timeout %d msec", dhcp->RT);
@@ -1387,7 +1399,7 @@ static gboolean start_renew(gpointer user_data)
{
struct connman_dhcpv6 *dhcp = user_data;
- dhcp->RT = REN_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REN_TIMEOUT);
DBG("renew initial RT timeout %d msec", dhcp->RT);
@@ -1585,7 +1597,7 @@ static gboolean start_info_req(gpointer user_data)
struct connman_dhcpv6 *dhcp = user_data;
/* Set the retransmission timeout, RFC 3315 chapter 14 */
- dhcp->RT = INF_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(INF_TIMEOUT);
DBG("info initial RT timeout %d msec", dhcp->RT);
@@ -1601,6 +1613,7 @@ int __connman_dhcpv6_start_info(struct connman_network *network,
{
struct connman_dhcpv6 *dhcp;
int delay;
+ uint64_t rand;
DBG("");
@@ -1626,7 +1639,8 @@ int __connman_dhcpv6_start_info(struct connman_network *network,
g_hash_table_replace(network_table, network, dhcp);
/* Initial timeout, RFC 3315, 18.1.5 */
- delay = rand() % 1000;
+ __connman_util_get_random(&rand);
+ delay = rand % 1000;
dhcp->timeout = g_timeout_add(delay, start_info_req, dhcp);
@@ -1650,7 +1664,7 @@ static void advertise_cb(GDHCPClient *dhcp_client, gpointer user_data)
return;
}
- dhcp->RT = REQ_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REQ_TIMEOUT);
DBG("request initial RT timeout %d msec", dhcp->RT);
dhcp->timeout = g_timeout_add(dhcp->RT, timeout_request, dhcp);
@@ -1668,9 +1682,16 @@ static void solicitation_cb(GDHCPClient *dhcp_client, gpointer user_data)
clear_timer(dhcp);
- do_dad(dhcp_client, dhcp);
-
g_dhcpv6_client_clear_retransmit(dhcp_client);
+
+ if (g_dhcpv6_client_get_status(dhcp_client) != 0) {
+ if (dhcp->callback)
+ dhcp->callback(dhcp->network,
+ CONNMAN_DHCPV6_STATUS_FAIL, NULL);
+ return;
+ }
+
+ do_dad(dhcp_client, dhcp);
}
static gboolean timeout_solicitation(gpointer user_data)
@@ -1761,7 +1782,7 @@ static gboolean start_solicitation(gpointer user_data)
struct connman_dhcpv6 *dhcp = user_data;
/* Set the retransmission timeout, RFC 3315 chapter 14 */
- dhcp->RT = SOL_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(SOL_TIMEOUT);
DBG("solicit initial RT timeout %d msec", dhcp->RT);
@@ -1778,6 +1799,7 @@ int __connman_dhcpv6_start(struct connman_network *network,
struct connman_service *service;
struct connman_dhcpv6 *dhcp;
int delay;
+ uint64_t rand;
DBG("");
@@ -1807,7 +1829,8 @@ int __connman_dhcpv6_start(struct connman_network *network,
g_hash_table_replace(network_table, network, dhcp);
/* Initial timeout, RFC 3315, 17.1.2 */
- delay = rand() % 1000;
+ __connman_util_get_random(&rand);
+ delay = rand % 1000;
/*
* Start from scratch.
@@ -2171,7 +2194,7 @@ static gboolean start_pd_rebind(gpointer user_data)
if (check_pd_restart(dhcp) < 0)
return FALSE;
- dhcp->RT = REB_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REB_TIMEOUT);
DBG("rebind initial RT timeout %d msec", dhcp->RT);
@@ -2223,7 +2246,7 @@ static gboolean start_pd_rebind_with_confirm(gpointer user_data)
{
struct connman_dhcpv6 *dhcp = user_data;
- dhcp->RT = CNF_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(CNF_TIMEOUT);
DBG("rebind with confirm initial RT timeout %d msec", dhcp->RT);
@@ -2260,7 +2283,7 @@ static gboolean start_pd_renew(gpointer user_data)
{
struct connman_dhcpv6 *dhcp = user_data;
- dhcp->RT = REN_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REN_TIMEOUT);
DBG("renew initial RT timeout %d msec", dhcp->RT);
@@ -2476,7 +2499,7 @@ static void advertise_pd_cb(GDHCPClient *dhcp_client, gpointer user_data)
return;
}
- dhcp->RT = REQ_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REQ_TIMEOUT);
DBG("request initial RT timeout %d msec", dhcp->RT);
dhcp->timeout = g_timeout_add(dhcp->RT, timeout_pd_request, dhcp);
@@ -2531,7 +2554,7 @@ static gboolean start_pd_solicitation(gpointer user_data)
struct connman_dhcpv6 *dhcp = user_data;
/* Set the retransmission timeout, RFC 3315 chapter 14 */
- dhcp->RT = SOL_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(SOL_TIMEOUT);
DBG("solicit initial RT timeout %d msec", dhcp->RT);
@@ -2640,8 +2663,6 @@ int __connman_dhcpv6_init(void)
{
DBG("");
- srand(time(NULL));
-
network_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, remove_network);