---
gdhcp/client.c | 123 ++++++++++++++++++++++++++++++++++++++++++--------------
gdhcp/gdhcp.h | 3 ++
2 files changed, 95 insertions(+), 31 deletions(-)
diff --git a/gdhcp/client.c b/gdhcp/client.c
index e6106d1..ddcbeb3 100644
--- a/gdhcp/client.c
+++ b/gdhcp/client.c
@@ -118,6 +118,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 +172,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)
{
@@ -537,7 +552,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,
@@ -1388,7 +1403,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;
@@ -1430,7 +1445,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*/
@@ -1597,7 +1612,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);
}
@@ -1639,7 +1654,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);
@@ -1682,7 +1697,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,
@@ -1710,7 +1725,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;
@@ -1738,7 +1753,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);
@@ -2324,7 +2340,7 @@ 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);
@@ -2341,6 +2357,8 @@ static gboolean listener_event(GIOChannel *channel,
GIOCondition condition,
dhcp_client->lease_seconds = get_lease(&packet);
+ dhcp_client->expire = time(NULL) +
dhcp_client->lease_seconds;
+
get_request(dhcp_client, &packet);
switch_listening_mode(dhcp_client, L_NONE);
@@ -2571,7 +2589,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;
}
@@ -2592,7 +2610,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)
@@ -2612,7 +2630,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++;
@@ -2632,80 +2650,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);
@@ -2715,7 +2733,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;
}
@@ -2732,7 +2750,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;
@@ -2788,7 +2806,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;
}
@@ -2833,6 +2851,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;
@@ -2935,6 +2957,45 @@ char *g_dhcp_client_get_netmask(GDHCPClient *dhcp_client)
return NULL;
}
+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..4a3e6d2 100644
--- a/gdhcp/gdhcp.h
+++ b/gdhcp/gdhcp.h
@@ -63,6 +63,7 @@ typedef enum {
G_DHCP_CLIENT_EVENT_RELEASE,
G_DHCP_CLIENT_EVENT_CONFIRM,
G_DHCP_CLIENT_EVENT_DECLINE,
+ G_DHCP_CLIENT_EVENT_CHANGED,
} GDHCPClientEvent;
typedef enum {
@@ -156,6 +157,8 @@ GList *g_dhcp_client_get_option(GDHCPClient *client,
unsigned char option_code);
int g_dhcp_client_get_index(GDHCPClient *client);
+const char* g_dhcp_client_get_state(GDHCPClient *state);
+
void g_dhcp_client_set_debug(GDHCPClient *client,
GDHCPDebugFunc func, gpointer user_data);
int g_dhcpv6_create_duid(GDHCPDuidType duid_type, int index, int type,
--
1.7.9.5
_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman