dhcp/v6: On renew/rebind, send ipconfig_changed notification event
ipconfig: Adding stats getters to allow plugins to query new lease stats
---
gdhcp/client.c | 158 +++++++++++++++++++++++++++++++++++++++++-----------
gdhcp/gdhcp.h | 6 ++
include/ipconfig.h | 18 ++++++
src/connman.h | 6 ++
src/dhcp.c | 75 +++++++++++++++++++++++++
src/dhcpv6.c | 93 +++++++++++++++++++++++++++++++
src/ipconfig.c | 35 ++++++++++++
src/service.c | 6 ++
8 files changed, 366 insertions(+), 31 deletions(-)
diff --git a/gdhcp/client.c b/gdhcp/client.c
index b24d19d..2a74ff0 100644
--- a/gdhcp/client.c
+++ b/gdhcp/client.c
@@ -94,6 +94,8 @@ struct _GDHCPClient {
char *assigned_ip;
time_t start;
uint32_t lease_seconds;
+ uint32_t last_renew;
+ uint32_t last_rebind;
ListenMode listen_mode;
int listener_sockfd;
uint8_t retry_times;
@@ -118,6 +120,8 @@ struct _GDHCPClient {
gpointer ipv4ll_lost_data;
GDHCPClientEventFunc address_conflict_cb;
gpointer address_conflict_data;
+ GDHCPClientEventFunc changed_cb;
+ gpointer changed_data;
GDHCPDebugFunc debug_func;
gpointer debug_data;
GDHCPClientEventFunc information_req_cb;
@@ -170,6 +174,19 @@ static inline void debug(GDHCPClient *client, const char
*format, ...)
va_end(ap);
}
+static void set_state(GDHCPClient *dhcp_client, ClientState state)
+{
+ if (state != dhcp_client->state)
+ {
+ dhcp_client->state = state;
+ debug(dhcp_client, "setting state");
+
+ if (dhcp_client->changed_cb!= NULL)
+ dhcp_client->changed_cb(dhcp_client,
+ dhcp_client->changed_data);
+ }
+}
+
/* Initialize the packet with the proper defaults */
static void init_packet(GDHCPClient *dhcp_client, gpointer pkt, char type)
{
@@ -477,6 +494,8 @@ static int send_renew(GDHCPClient *dhcp_client)
add_send_options(dhcp_client, &packet);
+ dhcp_client->last_renew = time(NULL);
+
return dhcp_send_kernel_packet(&packet,
dhcp_client->requested_ip, CLIENT_PORT,
dhcp_client->server_ip, SERVER_PORT);
@@ -496,6 +515,8 @@ static int send_rebound(GDHCPClient *dhcp_client)
add_send_options(dhcp_client, &packet);
+ dhcp_client->last_rebind = time(NULL);
+
return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT,
INADDR_BROADCAST, SERVER_PORT,
MAC_BCAST_ADDR, dhcp_client->ifindex);
@@ -537,7 +558,7 @@ static gboolean send_probe_packet(gpointer dhcp_data)
debug(dhcp_client, "sending IPV4LL probe request");
if (dhcp_client->retry_times == 1) {
- dhcp_client->state = IPV4LL_PROBE;
+ set_state(dhcp_client, IPV4LL_PROBE);
switch_listening_mode(dhcp_client, L_ARP);
}
ipv4ll_send_arp_packet(dhcp_client->mac_address, 0,
@@ -1389,7 +1410,7 @@ static void ipv4ll_stop(GDHCPClient *dhcp_client)
dhcp_client->listener_watch = 0;
}
- dhcp_client->state = IPV4LL_PROBE;
+ set_state(dhcp_client, IPV4LL_PROBE);
dhcp_client->retry_times = 0;
dhcp_client->requested_ip = 0;
@@ -1431,7 +1452,7 @@ static int ipv4ll_recv_arp_packet(GDHCPClient
*dhcp_client)
if (dhcp_client->state == IPV4LL_MONITOR) {
if (!source_conflict)
return 0;
- dhcp_client->state = IPV4LL_DEFEND;
+ set_state(dhcp_client, IPV4LL_DEFEND);
debug(dhcp_client, "DEFEND mode conflicts : %d",
dhcp_client->conflicts);
/*Try to defend with a single announce*/
@@ -1598,7 +1619,7 @@ static void start_request(GDHCPClient *dhcp_client)
}
if (dhcp_client->retry_times == 0) {
- dhcp_client->state = REQUESTING;
+ set_state(dhcp_client, REQUESTING);
switch_listening_mode(dhcp_client, L2);
}
@@ -1640,7 +1661,7 @@ static void restart_dhcp(GDHCPClient *dhcp_client, int
retry_times)
dhcp_client->retry_times = retry_times;
dhcp_client->requested_ip = 0;
- dhcp_client->state = INIT_SELECTING;
+ set_state(dhcp_client, INIT_SELECTING);
switch_listening_mode(dhcp_client, L2);
g_dhcp_client_start(dhcp_client, dhcp_client->last_address);
@@ -1683,7 +1704,7 @@ static void start_rebound(GDHCPClient *dhcp_client)
{
debug(dhcp_client, "start rebound");
- dhcp_client->state = REBINDING;
+ set_state(dhcp_client, REBINDING);
dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
dhcp_client->lease_seconds >> 1,
@@ -1711,7 +1732,7 @@ static gboolean start_renew_timeout(gpointer user_data)
debug(dhcp_client, "start renew timeout");
- dhcp_client->state = RENEWING;
+ set_state(dhcp_client, RENEWING);
dhcp_client->lease_seconds >>= 1;
@@ -1739,7 +1760,8 @@ static void start_bound(GDHCPClient *dhcp_client)
{
debug(dhcp_client, "start bound");
- dhcp_client->state = BOUND;
+ set_state(dhcp_client, BOUND);
+
if (dhcp_client->timeout > 0)
g_source_remove(dhcp_client->timeout);
@@ -2325,13 +2347,14 @@ static gboolean listener_event(GIOChannel *channel,
GIOCondition condition,
dhcp_client->server_ip = get_be32(option);
dhcp_client->requested_ip = ntohl(packet.yiaddr);
- dhcp_client->state = REQUESTING;
+ set_state(dhcp_client, REQUESTING);
start_request(dhcp_client);
return TRUE;
case REQUESTING:
case RENEWING:
+ dhcp_client->last_renew = time(NULL);
case REBINDING:
if (*message_type == DHCPACK) {
dhcp_client->retry_times = 0;
@@ -2342,6 +2365,10 @@ static gboolean listener_event(GIOChannel *channel,
GIOCondition condition,
dhcp_client->lease_seconds = get_lease(&packet);
+ dhcp_client->expire = time(NULL) +
dhcp_client->lease_seconds;
+
+ dhcp_client->last_rebind = time(NULL);
+
get_request(dhcp_client, &packet);
switch_listening_mode(dhcp_client, L_NONE);
@@ -2572,7 +2599,7 @@ static gboolean ipv4ll_defend_timeout(gpointer dhcp_data)
debug(dhcp_client, "back to MONITOR mode");
dhcp_client->conflicts = 0;
- dhcp_client->state = IPV4LL_MONITOR;
+ set_state(dhcp_client, IPV4LL_MONITOR);
return FALSE;
}
@@ -2593,7 +2620,7 @@ static gboolean ipv4ll_announce_timeout(gpointer
dhcp_data)
ip = htonl(dhcp_client->requested_ip);
debug(dhcp_client, "switching to monitor mode");
- dhcp_client->state = IPV4LL_MONITOR;
+ set_state(dhcp_client, IPV4LL_MONITOR);
dhcp_client->assigned_ip = get_ip(ip);
if (dhcp_client->ipv4ll_available_cb)
@@ -2613,7 +2640,7 @@ static gboolean ipv4ll_probe_timeout(gpointer dhcp_data)
dhcp_client->retry_times);
if (dhcp_client->retry_times == PROBE_NUM) {
- dhcp_client->state = IPV4LL_ANNOUNCE;
+ set_state(dhcp_client, IPV4LL_ANNOUNCE);
dhcp_client->retry_times = 0;
dhcp_client->retry_times++;
@@ -2633,80 +2660,80 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const
char *last_address)
if (dhcp_client->type == G_DHCP_IPV6) {
if (dhcp_client->information_req_cb) {
- dhcp_client->state = INFORMATION_REQ;
+ set_state(dhcp_client, INFORMATION_REQ);
re = switch_listening_mode(dhcp_client, L3);
if (re != 0) {
switch_listening_mode(dhcp_client, L_NONE);
- dhcp_client->state = 0;
+ set_state(dhcp_client, 0);
return re;
}
send_information_req(dhcp_client);
} else if (dhcp_client->solicitation_cb) {
- dhcp_client->state = SOLICITATION;
+ set_state(dhcp_client, SOLICITATION);
re = switch_listening_mode(dhcp_client, L3);
if (re != 0) {
switch_listening_mode(dhcp_client, L_NONE);
- dhcp_client->state = 0;
+ set_state(dhcp_client, 0);
return re;
}
send_solicitation(dhcp_client);
} else if (dhcp_client->request_cb) {
- dhcp_client->state = REQUEST;
+ set_state(dhcp_client, REQUEST);
re = switch_listening_mode(dhcp_client, L3);
if (re != 0) {
switch_listening_mode(dhcp_client, L_NONE);
- dhcp_client->state = 0;
+ set_state(dhcp_client, 0);
return re;
}
send_dhcpv6_request(dhcp_client);
} else if (dhcp_client->confirm_cb) {
- dhcp_client->state = CONFIRM;
+ set_state(dhcp_client, CONFIRM);
re = switch_listening_mode(dhcp_client, L3);
if (re != 0) {
switch_listening_mode(dhcp_client, L_NONE);
- dhcp_client->state = 0;
+ set_state(dhcp_client, 0);
return re;
}
send_dhcpv6_confirm(dhcp_client);
} else if (dhcp_client->renew_cb) {
- dhcp_client->state = RENEW;
+ set_state(dhcp_client, RENEW);
re = switch_listening_mode(dhcp_client, L3);
if (re != 0) {
switch_listening_mode(dhcp_client, L_NONE);
- dhcp_client->state = 0;
+ set_state(dhcp_client, 0);
return re;
}
send_dhcpv6_renew(dhcp_client);
} else if (dhcp_client->rebind_cb) {
- dhcp_client->state = REBIND;
+ set_state(dhcp_client, REBIND);
re = switch_listening_mode(dhcp_client, L3);
if (re != 0) {
switch_listening_mode(dhcp_client, L_NONE);
- dhcp_client->state = 0;
+ set_state(dhcp_client, 0);
return re;
}
send_dhcpv6_rebind(dhcp_client);
} else if (dhcp_client->release_cb) {
- dhcp_client->state = RENEW;
+ set_state(dhcp_client, RENEW);
re = switch_listening_mode(dhcp_client, L3);
if (re != 0) {
switch_listening_mode(dhcp_client, L_NONE);
- dhcp_client->state = 0;
+ set_state(dhcp_client, 0);
return re;
}
send_dhcpv6_release(dhcp_client);
} else if (dhcp_client->decline_cb) {
- dhcp_client->state = DECLINE;
+ set_state(dhcp_client, DECLINE);
re = switch_listening_mode(dhcp_client, L3);
if (re != 0) {
switch_listening_mode(dhcp_client, L_NONE);
- dhcp_client->state = 0;
+ set_state(dhcp_client, 0);
return re;
}
send_dhcpv6_decline(dhcp_client);
@@ -2716,7 +2743,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const
char *last_address)
}
if (dhcp_client->type == G_DHCP_IPV4LL) {
- dhcp_client->state = INIT_SELECTING;
+ set_state(dhcp_client, INIT_SELECTING);
ipv4ll_start(dhcp_client);
return 0;
}
@@ -2733,7 +2760,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const
char *last_address)
g_free(dhcp_client->assigned_ip);
dhcp_client->assigned_ip = NULL;
- dhcp_client->state = INIT_SELECTING;
+ set_state(dhcp_client, INIT_SELECTING);
re = switch_listening_mode(dhcp_client, L2);
if (re != 0)
return re;
@@ -2789,7 +2816,7 @@ void g_dhcp_client_stop(GDHCPClient *dhcp_client)
dhcp_client->ack_retry_times = 0;
dhcp_client->requested_ip = 0;
- dhcp_client->state = RELEASED;
+ set_state(dhcp_client, RELEASED);
dhcp_client->lease_seconds = 0;
}
@@ -2834,6 +2861,10 @@ void g_dhcp_client_register_event(GDHCPClient
*dhcp_client,
dhcp_client->address_conflict_cb = func;
dhcp_client->address_conflict_data = data;
return;
+ case G_DHCP_CLIENT_EVENT_CHANGED:
+ dhcp_client->changed_cb = func;
+ dhcp_client->changed_data = data;
+ return;
case G_DHCP_CLIENT_EVENT_INFORMATION_REQ:
if (dhcp_client->type != G_DHCP_IPV6)
return;
@@ -2936,6 +2967,71 @@ char *g_dhcp_client_get_netmask(GDHCPClient *dhcp_client)
return NULL;
}
+int g_dhcp_client_get_timeouts(GDHCPClient *dhcp_client,
+ uint32_t *lease_seconds, time_t *last_renew,
+ time_t *last_rebind, time_t *expire)
+{
+
+ if (dhcp_client == NULL || dhcp_client->type == G_DHCP_IPV6)
+ return -EINVAL;
+
+ if (lease_seconds != NULL)
+ *lease_seconds = dhcp_client->lease_seconds;
+
+ if (last_renew != NULL)
+ *last_renew = dhcp_client->last_renew;
+
+ if (last_rebind != NULL)
+ *last_rebind = dhcp_client->last_rebind;
+
+ if (expire != NULL)
+ *expire = dhcp_client->expire;
+
+ return 0;
+
+
+}
+
+const char* g_dhcp_client_get_state(GDHCPClient *dhcp_client)
+{
+ switch (dhcp_client->state) {
+ case INIT_SELECTING:
+ return "INIT_SELECTING";
+ case REQUESTING:
+ return "REQUESTING";
+ case BOUND:
+ return "BOUND";
+ case RENEWING:
+ return "RENEWING";
+ case REBINDING:
+ return "REBINDING";
+ case RELEASED:
+ return "RELEASED";
+ case IPV4LL_PROBE:
+ return "IPV4LL_PROBE";
+ case IPV4LL_ANNOUNCE:
+ return "IPV4LL_ANNOUNCE";
+ case IPV4LL_MONITOR:
+ return "IPV4LL_MONITOR";
+ case IPV4LL_DEFEND:
+ return "IPV4LL_DEFEND";
+ case INFORMATION_REQ:
+ return "INFORMATION_REQ";
+ case SOLICITATION:
+ return "SOLICITATION";
+ case REQUEST:
+ return "REQUEST";
+ case RENEW:
+ return "RENEW";
+ case REBIND:
+ return "REBIND";
+ case RELEASE:
+ return "RELEASE";
+ default:
+ return NULL;
+ }
+
+}
GDHCPClientError g_dhcp_client_set_request(GDHCPClient *dhcp_client,
unsigned int option_code)
{
diff --git a/gdhcp/gdhcp.h b/gdhcp/gdhcp.h
index 0d79361..84286a8 100644
--- a/gdhcp/gdhcp.h
+++ b/gdhcp/gdhcp.h
@@ -61,6 +61,7 @@ typedef enum {
G_DHCP_CLIENT_EVENT_RENEW,
G_DHCP_CLIENT_EVENT_REBIND,
G_DHCP_CLIENT_EVENT_RELEASE,
+ G_DHCP_CLIENT_EVENT_CHANGED,
G_DHCP_CLIENT_EVENT_CONFIRM,
G_DHCP_CLIENT_EVENT_DECLINE,
} GDHCPClientEvent;
@@ -155,6 +156,11 @@ char *g_dhcp_client_get_netmask(GDHCPClient *client);
GList *g_dhcp_client_get_option(GDHCPClient *client,
unsigned char option_code);
int g_dhcp_client_get_index(GDHCPClient *client);
+int g_dhcp_client_get_timeouts(GDHCPClient *dhcp_client,
+ uint32_t *lease_seconds, time_t *last_renew,
+ time_t *last_rebind, time_t *expire);
+
+const char* g_dhcp_client_get_state(GDHCPClient *state);
void g_dhcp_client_set_debug(GDHCPClient *client,
GDHCPDebugFunc func, gpointer user_data);
diff --git a/include/ipconfig.h b/include/ipconfig.h
index a86b295..0a8357c 100644
--- a/include/ipconfig.h
+++ b/include/ipconfig.h
@@ -23,6 +23,8 @@
#define __CONNMAN_IPCONFIG_H
#include <connman/ipaddress.h>
+#include <time.h>
+#include <stdint.h>
#ifdef __cplusplus
extern "C" {
@@ -51,6 +53,22 @@ enum connman_ipconfig_method {
};
struct connman_ipconfig;
+struct connman_dhcp;
+struct connman_dhcpv6;
+
+struct dhcp_stats{
+ char* state;
+ time_t lease_time;
+ uint32_t lease_seconds;
+ time_t last_renew;
+ time_t last_rebind;
+ time_t expire;
+};
+
+enum connman_ipconfig_method connman_ipconfig_get_ipconfig_method(struct
connman_ipconfig *ipconfig);
+enum connman_ipconfig_type connman_ipconfig_get_ipconfig_type(struct
connman_ipconfig *ipconfig);
+struct dhcp_stats* connman_ipconfig_get_dhcp_stats(struct connman_ipconfig
*ipconfig);
+struct dhcp_stats* connman_ipconfig_get_dhcpv6_stats(struct connman_ipconfig
*ipconfig);
#ifdef __cplusplus
}
diff --git a/src/connman.h b/src/connman.h
index bf59dbf..c1e7962 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -393,6 +393,9 @@ void __connman_ipconfig_set_dhcpv6_prefixes(struct
connman_ipconfig *ipconfig,
char **prefixes);
char **__connman_ipconfig_get_dhcpv6_prefixes(struct connman_ipconfig
*ipconfig);
+void __connman_ipconfig_set_dhcp(struct connman_ipconfig *ipconfig,
+ void *dhcp);
+
int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
GKeyFile *keyfile, const char *identifier, const char *prefix);
int __connman_ipconfig_save(struct connman_ipconfig *ipconfig,
@@ -438,6 +441,8 @@ int __connman_dhcp_start(struct connman_network *network,
dhcp_cb callback);
void __connman_dhcp_stop(struct connman_network *network);
int __connman_dhcp_init(void);
void __connman_dhcp_cleanup(void);
+struct dhcp_stats* __connman_dhcp_get_stats(struct connman_dhcp *dhcp);
+struct dhcp_stats* __connman_dhcpv6_get_stats(struct connman_dhcpv6 *dhcp);
int __connman_dhcpv6_init(void);
void __connman_dhcpv6_cleanup(void);
int __connman_dhcpv6_start_info(struct connman_network *network,
@@ -710,6 +715,7 @@ void __connman_service_return_error(struct connman_service
*service,
void __connman_service_reply_dbus_pending(DBusMessage *pending, int error,
const char *path);
+void __connman_service_ipconfig_changed(struct connman_service *service,
struct connman_ipconfig *ipconfig);
int __connman_service_provision_changed(const char *ident);
void __connman_service_set_config(struct connman_service *service,
const char *file_id, const char *section);
diff --git a/src/dhcp.c b/src/dhcp.c
index 2193e4d..1ab8fc9 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -50,6 +50,7 @@ struct connman_dhcp {
GDHCPClient *ipv4ll_client;
GDHCPClient *dhcp_client;
+ struct dhcp_stats stats;
char *ipv4ll_debug_prefix;
char *dhcp_debug_prefix;
};
@@ -120,6 +121,14 @@ static void dhcp_invalidate(struct connman_dhcp *dhcp,
bool callback)
__connman_ipconfig_set_dhcp_address(ipconfig,
__connman_ipconfig_get_local(ipconfig));
+ __connman_ipconfig_set_dhcp(ipconfig, NULL);
+
+ dhcp->stats.lease_time = 0;
+ dhcp->stats.lease_seconds = 0;
+ dhcp->stats.last_renew = 0;
+ dhcp->stats.last_rebind = 0;
+ dhcp->stats.expire = 0;
+
DBG("last address %s", __connman_ipconfig_get_dhcp_address(ipconfig));
__connman_ipconfig_address_remove(ipconfig);
@@ -297,6 +306,53 @@ static bool compare_string_arrays(char **array_a, char
**array_b)
return true;
}
+static void lease_renew_cb(GDHCPClient *dhcp_client, gpointer user_data)
+{
+ struct connman_dhcp *dhcp = user_data;
+ struct connman_service *service;
+ struct connman_ipconfig *ipconfig;
+
+ //copy info into local storage
+ g_dhcp_client_get_timeouts(dhcp_client,&(dhcp->stats.lease_seconds),
+
&(dhcp->stats.last_renew),&(dhcp->stats.last_rebind),&(dhcp->stats.expire));
+ //inform service about the change
+ service = connman_service_lookup_from_network(dhcp->network);
+ if (service == NULL)
+ return;
+
+ ipconfig = __connman_service_get_ip4config(service);
+ if (ipconfig == NULL)
+ return;
+ __connman_service_ipconfig_changed(service,ipconfig);
+}
+
+static void dhcp_state_cb(GDHCPClient *dhcp_client, gpointer user_data)
+{
+
+ struct connman_dhcp *dhcp = user_data;
+ struct connman_service *service;
+ struct connman_ipconfig *ipconfig;
+ const char *state;
+
+ state = g_dhcp_client_get_state(dhcp_client);
+
+ g_free(dhcp->stats.state);
+ dhcp->stats.state = g_strdup(state);
+
+ //inform service about the change
+ service = connman_service_lookup_from_network(dhcp->network);
+ if (service == NULL)
+ return;
+
+ ipconfig = __connman_service_get_ip4config(service);
+
+ if (ipconfig == NULL)
+ return;
+
+ __connman_service_ipconfig_changed(service,ipconfig);
+
+}
+
static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data)
{
struct connman_dhcp *dhcp = user_data;
@@ -335,10 +391,15 @@ static void lease_available_cb(GDHCPClient *dhcp_client,
gpointer user_data)
c_prefixlen = __connman_ipconfig_get_prefixlen(ipconfig);
address = g_dhcp_client_get_address(dhcp_client);
+ dhcp->stats.lease_time = time(NULL);
__connman_ipconfig_set_dhcp_address(ipconfig, address);
+ __connman_ipconfig_set_dhcp(ipconfig, dhcp);
DBG("last address %s", address);
+
g_dhcp_client_get_timeouts(dhcp_client,&(dhcp->stats.lease_seconds),&(dhcp->stats.last_renew),
+ &(dhcp->stats.last_rebind),&(dhcp->stats.expire));
+
option = g_dhcp_client_get_option(dhcp_client, G_DHCP_SUBNET);
if (option)
netmask = g_strdup(option->data);
@@ -543,11 +604,20 @@ static int dhcp_request(struct connman_dhcp *dhcp)
lease_available_cb, dhcp);
g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_RENEW, lease_renew_cb, dhcp);
+
+ g_dhcp_client_register_event(dhcp_client,
G_DHCP_CLIENT_EVENT_LEASE_LOST, lease_lost_cb, dhcp);
g_dhcp_client_register_event(dhcp_client,
G_DHCP_CLIENT_EVENT_NO_LEASE, no_lease_cb, dhcp);
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcp_state_cb, dhcp);
+
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcp_state_cb, dhcp);
+
dhcp->dhcp_client = dhcp_client;
ipconfig = __connman_service_get_ip4config(service);
@@ -644,3 +714,8 @@ void __connman_dhcp_cleanup(void)
g_hash_table_destroy(network_table);
network_table = NULL;
}
+
+struct dhcp_stats* __connman_dhcp_get_stats(struct connman_dhcp *instance)
+{
+ return &(instance->stats);
+}
diff --git a/src/dhcpv6.c b/src/dhcpv6.c
index 789db10..23afdf4 100644
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -81,6 +81,7 @@ struct connman_dhcpv6 {
int request_count; /* how many times REQUEST have been sent */
bool stateless; /* TRUE if stateless DHCPv6 is used */
bool started; /* TRUE if we have DHCPv6 started */
+ struct dhcp_stats stats;
};
static GHashTable *network_table;
@@ -283,8 +284,38 @@ static void clear_callbacks(GDHCPClient *dhcp_client)
g_dhcp_client_register_event(dhcp_client,
G_DHCP_CLIENT_EVENT_INFORMATION_REQ,
NULL, NULL);
+
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED,
+ NULL, NULL);
}
+static void dhcpv6_state_cb(GDHCPClient *dhcp_client, gpointer user_data)
+{
+
+ struct connman_dhcpv6 *dhcp = user_data;
+ struct connman_service *service;
+ struct connman_ipconfig *ipconfig;
+ const char *state;
+
+ state = g_dhcp_client_get_state(dhcp_client);
+
+ g_free(dhcp->stats.state);
+ dhcp->stats.state = g_strdup(state);
+
+ //inform service about the change
+ service = connman_service_lookup_from_network(dhcp->network);
+ if (service == NULL)
+ return;
+
+ ipconfig = __connman_service_get_ip6config(service);
+
+ if (ipconfig == NULL)
+ return;
+
+ __connman_service_ipconfig_changed(service,ipconfig);
+
+}
static void info_req_cb(GDHCPClient *dhcp_client, gpointer user_data)
{
struct connman_dhcpv6 *dhcp = user_data;
@@ -413,6 +444,12 @@ static int dhcpv6_info_request(struct connman_dhcpv6 *dhcp)
g_dhcp_client_register_event(dhcp_client,
G_DHCP_CLIENT_EVENT_INFORMATION_REQ, info_req_cb, dhcp);
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcpv6_state_cb, dhcp);
+
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcpv6_state_cb, dhcp);
+
dhcp->dhcp_client = dhcp_client;
return g_dhcp_client_start(dhcp_client, NULL);
@@ -1035,6 +1072,8 @@ static void re_cb(enum request_type req_type, GDHCPClient
*dhcp_client,
{
struct connman_dhcpv6 *dhcp = user_data;
uint16_t status;
+ time_t expired;
+ time_t lease_time;
clear_timer(dhcp);
@@ -1042,6 +1081,17 @@ static void re_cb(enum request_type req_type,
GDHCPClient *dhcp_client,
DBG("dhcpv6 cb msg %p status %d", dhcp, status);
+ g_dhcpv6_client_get_timeouts(dhcp->dhcp_client, NULL, NULL,
+ &lease_time, &expired);
+
+ //write stats out
+
+ dhcp->stats.lease_time = lease_time;
+ dhcp->stats.lease_seconds = expired - lease_time;
+ //dhcp->stats.last_renew = last_renew;
+ //dhcp->stats.last_rebind = last_rebind;
+ dhcp->stats.expire = expired;
+
/*
* RFC 3315, 18.1.8 handle the resend if error
*/
@@ -1151,6 +1201,12 @@ static int dhcpv6_rebind(struct connman_dhcpv6 *dhcp)
g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_REBIND,
rebind_cb, dhcp);
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcpv6_state_cb, dhcp);
+
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcpv6_state_cb, dhcp);
+
dhcp->dhcp_client = dhcp_client;
return g_dhcp_client_start(dhcp_client, NULL);
@@ -1270,6 +1326,12 @@ static int dhcpv6_request(struct connman_dhcpv6 *dhcp,
g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_REQUEST,
request_cb, dhcp);
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcpv6_state_cb, dhcp);
+
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcpv6_state_cb, dhcp);
+
dhcp->dhcp_client = dhcp_client;
return g_dhcp_client_start(dhcp_client, NULL);
@@ -1341,6 +1403,12 @@ static int dhcpv6_renew(struct connman_dhcpv6 *dhcp)
g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_RENEW,
renew_cb, dhcp);
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcpv6_state_cb, dhcp);
+
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcpv6_state_cb, dhcp);
+
dhcp->dhcp_client = dhcp_client;
return g_dhcp_client_start(dhcp_client, NULL);
@@ -1744,6 +1812,12 @@ static int dhcpv6_solicitation(struct connman_dhcpv6
*dhcp)
G_DHCP_CLIENT_EVENT_ADVERTISE,
advertise_cb, dhcp);
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcpv6_state_cb, dhcp);
+
+ g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_CHANGED, dhcpv6_state_cb, dhcp);
+
dhcp->dhcp_client = dhcp_client;
return g_dhcp_client_start(dhcp_client, NULL);
@@ -1922,6 +1996,13 @@ int __connman_dhcpv6_start(struct connman_network
*network,
if (!dhcp)
return -ENOMEM;
+ service = connman_service_lookup_from_network(dhcp->network);
+ if (service == NULL)
+ return -1;
+
+ ipconfig_ipv6 = __connman_service_get_ip6config(service);
+ __connman_ipconfig_set_dhcp(ipconfig_ipv6, dhcp);
+
dhcp->network = network;
dhcp->callback = callback;
dhcp->prefixes = prefixes;
@@ -2680,6 +2761,7 @@ int __connman_dhcpv6_start_pd(int index, GSList
*prefixes, dhcpv6_cb callback)
struct connman_service *service;
struct connman_network *network;
struct connman_dhcpv6 *dhcp;
+ struct connman_ipconfig *ipconfig_ipv6;
if (index < 0)
return 0;
@@ -2704,6 +2786,13 @@ int __connman_dhcpv6_start_pd(int index, GSList
*prefixes, dhcpv6_cb callback)
if (!dhcp)
return -ENOMEM;
+ service = connman_service_lookup_from_network(dhcp->network);
+ if (service == NULL)
+ return -1;
+
+ ipconfig_ipv6 = __connman_service_get_ip6config(service);
+ __connman_ipconfig_set_dhcp(ipconfig_ipv6, dhcp);
+
dhcp->network = network;
dhcp->callback = callback;
dhcp->started = true;
@@ -2794,3 +2883,7 @@ void __connman_dhcpv6_cleanup(void)
g_hash_table_destroy(network_pd_table);
network_pd_table = NULL;
}
+struct dhcp_stats* __connman_dhcpv6_get_stats(struct connman_dhcpv6 *instance)
+{
+ return &(instance->stats);
+}
diff --git a/src/ipconfig.c b/src/ipconfig.c
index 9452125..86bce56 100644
--- a/src/ipconfig.c
+++ b/src/ipconfig.c
@@ -57,6 +57,7 @@ struct connman_ipconfig {
int ipv6_privacy_config;
char *last_dhcp_address;
+ void *dhcp;
char **last_dhcpv6_prefixes;
};
@@ -1478,6 +1479,16 @@ void __connman_ipconfig_set_dhcp_address(struct
connman_ipconfig *ipconfig,
ipconfig->last_dhcp_address = g_strdup(address);
}
+void __connman_ipconfig_set_dhcp(struct connman_ipconfig *ipconfig,
+ void *dhcp)
+{
+ if (ipconfig == NULL)
+ return;
+
+ ipconfig->dhcp= dhcp;
+
+}
+
char *__connman_ipconfig_get_dhcp_address(struct connman_ipconfig *ipconfig)
{
if (!ipconfig)
@@ -2395,3 +2406,27 @@ void __connman_ipconfig_cleanup(void)
g_hash_table_destroy(ipdevice_hash);
ipdevice_hash = NULL;
}
+
+enum connman_ipconfig_method connman_ipconfig_get_ipconfig_method(struct
connman_ipconfig *ipconfig)
+{
+ return ipconfig->method;
+
+}
+enum connman_ipconfig_type connman_ipconfig_get_ipconfig_type(struct
connman_ipconfig *ipconfig)
+{
+ return ipconfig->type;
+}
+struct dhcp_stats* connman_ipconfig_get_dhcp_stats(struct connman_ipconfig
*ipconfig)
+{
+ if(ipconfig->dhcp){
+ return __connman_dhcp_get_stats(ipconfig->dhcp);
+ }
+ return NULL;
+}
+struct dhcp_stats* connman_ipconfig_get_dhcpv6_stats(struct connman_ipconfig
*ipconfig)
+{
+ if(ipconfig->dhcp){
+ return __connman_dhcpv6_get_stats(ipconfig->dhcp);
+ }
+ return NULL;
+}
diff --git a/src/service.c b/src/service.c
index 33cce14..ecb3388 100644
--- a/src/service.c
+++ b/src/service.c
@@ -1842,6 +1842,12 @@ static void settings_changed(struct connman_service
*service,
__connman_notifier_ipconfig_changed(service, ipconfig);
}
+void __connman_service_ipconfig_changed(struct connman_service *service,
+ struct connman_ipconfig *ipconfig)
+{
+ settings_changed(service, ipconfig);
+}
+
static void ipv4_configuration_changed(struct connman_service *service)
{
if (!allow_property_changed(service))
--
1.7.9.5
_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman