summaryrefslogtreecommitdiff
path: root/src/dhcpv6.c
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/dhcpv6.c
parent5f5b3609c4f9884954623d7e6bf2ae1ae7096637 (diff)
downloadconnman-53f38ce0bc6505c8b8a7342b0243df442b7db5a4.tar.gz
connman-53f38ce0bc6505c8b8a7342b0243df442b7db5a4.tar.bz2
connman-53f38ce0bc6505c8b8a7342b0243df442b7db5a4.zip
dhcpv6: Release message implemented.
Diffstat (limited to 'src/dhcpv6.c')
-rw-r--r--src/dhcpv6.c64
1 files changed, 64 insertions, 0 deletions
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);