summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2012-01-05 13:38:14 +0200
committerDaniel Wagner <daniel.wagner@bmw-carit.de>2012-01-05 13:17:26 +0100
commit53f38ce0bc6505c8b8a7342b0243df442b7db5a4 (patch)
treeed3550a683f4f77ab7936374f4464ce19d1fbc5d /src
parent5f5b3609c4f9884954623d7e6bf2ae1ae7096637 (diff)
downloadconnman-53f38ce0bc6505c8b8a7342b0243df442b7db5a4.tar.gz
connman-53f38ce0bc6505c8b8a7342b0243df442b7db5a4.tar.bz2
connman-53f38ce0bc6505c8b8a7342b0243df442b7db5a4.zip
dhcpv6: Release message implemented.
Diffstat (limited to 'src')
-rw-r--r--src/connman.h2
-rw-r--r--src/dhcpv6.c64
-rw-r--r--src/network.c17
3 files changed, 82 insertions, 1 deletions
diff --git a/src/connman.h b/src/connman.h
index d99d4b4d..5dc588a6 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -286,6 +286,8 @@ int __connman_dhcpv6_start(struct connman_network *network,
GSList *prefixes, dhcp_cb callback);
int __connman_dhcpv6_start_renew(struct connman_network *network,
dhcp_cb callback);
+int __connman_dhcpv6_start_release(struct connman_network *network,
+ dhcp_cb callback);
int __connman_ipv4_init(void);
void __connman_ipv4_cleanup(void);
diff --git a/src/dhcpv6.c b/src/dhcpv6.c
index fd6e0ebe..f2c7da60 100644
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -66,6 +66,7 @@ struct connman_dhcpv6 {
gboolean use_ta; /* set to TRUE if IPv6 privacy is enabled */
GSList *prefixes; /* network prefixes from radvd */
int request_count; /* how many times REQUEST have been sent */
+ gboolean stateless; /* TRUE if stateless DHCPv6 is used */
};
static GHashTable *network_table;
@@ -236,6 +237,10 @@ static void clear_callbacks(GDHCPClient *dhcp_client)
NULL, NULL);
g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_RELEASE,
+ NULL, NULL);
+
+ g_dhcp_client_register_event(dhcp_client,
G_DHCP_CLIENT_EVENT_INFORMATION_REQ,
NULL, NULL);
}
@@ -854,6 +859,64 @@ int __connman_dhcpv6_start_renew(struct connman_network *network,
return 0;
}
+static void release_cb(GDHCPClient *dhcp_client, gpointer user_data)
+{
+ struct connman_dhcpv6 *dhcp = user_data;
+
+ DBG("dhcpv6 release msg %p", dhcp);
+
+ if (dhcp->callback != NULL) {
+ uint16_t status = g_dhcpv6_client_get_status(dhcp_client);
+ dhcp->callback(dhcp->network, status == 0 ? TRUE : FALSE);
+ }
+}
+
+int __connman_dhcpv6_start_release(struct connman_network *network,
+ dhcp_cb callback)
+{
+ struct connman_dhcpv6 *dhcp;
+ GDHCPClient *dhcp_client;
+
+ if (network_table == NULL)
+ return 0; /* we are already released */
+
+ dhcp = g_hash_table_lookup(network_table, network);
+ if (dhcp == NULL)
+ return -ENOENT;
+
+ DBG("dhcp %p stateless %d", dhcp, dhcp->stateless);
+
+ if (dhcp->stateless == TRUE)
+ return -EINVAL;
+
+ if (dhcp->timeout > 0) {
+ g_source_remove(dhcp->timeout);
+ dhcp->timeout = 0;
+ }
+
+ dhcp_client = dhcp->dhcp_client;
+
+ g_dhcp_client_clear_requests(dhcp_client);
+ g_dhcp_client_clear_values(dhcp_client);
+
+ g_dhcp_client_set_request(dhcp_client, G_DHCPV6_CLIENTID);
+ g_dhcp_client_set_request(dhcp_client, G_DHCPV6_SERVERID);
+
+ g_dhcpv6_client_set_ia(dhcp_client,
+ connman_network_get_index(dhcp->network),
+ dhcp->use_ta == TRUE ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA,
+ NULL, NULL, TRUE);
+
+ clear_callbacks(dhcp_client);
+
+ g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_RELEASE,
+ release_cb, dhcp);
+
+ dhcp->dhcp_client = dhcp_client;
+
+ return g_dhcp_client_start(dhcp_client, NULL);
+}
+
static int dhcpv6_release(struct connman_dhcpv6 *dhcp)
{
DBG("dhcp %p", dhcp);
@@ -932,6 +995,7 @@ int __connman_dhcpv6_start_info(struct connman_network *network,
dhcp->network = network;
dhcp->callback = callback;
+ dhcp->stateless = TRUE;
connman_network_ref(network);
diff --git a/src/network.c b/src/network.c
index bff0e7e2..2637ba5d 100644
--- a/src/network.c
+++ b/src/network.c
@@ -974,6 +974,21 @@ static void stop_dhcpv6(struct connman_network *network)
__connman_dhcpv6_stop(network);
}
+static void dhcpv6_release_callback(struct connman_network *network,
+ connman_bool_t success)
+{
+ DBG("success %d", success);
+
+ stop_dhcpv6(network);
+}
+
+static void release_dhcpv6(struct connman_network *network)
+{
+ if (__connman_dhcpv6_start_release(network,
+ dhcpv6_release_callback) < 0)
+ stop_dhcpv6(network);
+}
+
static void dhcpv6_info_callback(struct connman_network *network,
connman_bool_t success)
{
@@ -1211,7 +1226,7 @@ static gboolean set_connected(gpointer user_data)
break;
case CONNMAN_IPCONFIG_METHOD_DHCP:
case CONNMAN_IPCONFIG_METHOD_AUTO:
- stop_dhcpv6(network);
+ release_dhcpv6(network);
break;
}