diff options
Diffstat (limited to 'src/dhcpv6.c')
-rwxr-xr-x[-rw-r--r--] | src/dhcpv6.c | 77 |
1 files changed, 49 insertions, 28 deletions
diff --git a/src/dhcpv6.c b/src/dhcpv6.c index 5f8029f1..db9feb60 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); |