@@ -45,6 +45,8 @@
client->state = (s)
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
+#define CLIENT_MAX_ATTEMPT_LIMIT 30
+#define CLIENT_MIN_ATTEMPT_LIMIT 3
enum dhcp_state {
DHCP_STATE_INIT,
@@ -159,6 +161,7 @@ struct l_dhcp_client {
uint32_t rtnl_add_cmdid;
struct l_rtnl_address *rtnl_configured_address;
uint8_t attempt;
+ uint8_t max_attempts;
l_dhcp_client_event_cb_t event_handler;
void *event_data;
l_dhcp_destroy_cb_t event_destroy;
@@ -558,9 +561,16 @@ static void dhcp_client_timeout_resend(struct l_timeout *timeout,
* "The retransmission delay SHOULD be doubled with subsequent
* retransmissions up to a maximum of 64 seconds.
*/
- client->attempt += 1;
- next_timeout = minsize(2 << client->attempt, 64);
- break;
+ if (client->attempt < client->max_attempts) {
+ next_timeout = minsize(2 << client->attempt++, 64);
+ break;
+ }
+
+ CLIENT_DEBUG("Max request/discover attempts reached");
+
+ dhcp_client_event_notify(client,
+ L_DHCP_CLIENT_EVENT_MAX_ATTEMPTS_REACHED);
+ return;
case DHCP_STATE_INIT:
case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_REBOOTING:
@@ -988,6 +998,7 @@ LIB_EXPORT struct l_dhcp_client *l_dhcp_client_new(uint32_t ifindex)
client->state = DHCP_STATE_INIT;
client->ifindex = ifindex;
+ client->max_attempts = CLIENT_MAX_ATTEMPT_LIMIT;
/* Enable these options by default */
dhcp_enable_option(client, L_DHCP_OPTION_SUBNET_MASK);
@@ -1309,3 +1320,21 @@ LIB_EXPORT bool l_dhcp_client_set_rtnl(struct l_dhcp_client *client,
client->rtnl = rtnl;
return true;
}
+
+LIB_EXPORT bool l_dhcp_client_set_max_attempts(struct l_dhcp_client *client,
+ uint8_t attempts)
+{
+ if (unlikely(!client))
+ return false;
+
+ if (unlikely(client->state != DHCP_STATE_INIT))
+ return false;
+
+ if (attempts < CLIENT_MIN_ATTEMPT_LIMIT ||
+ attempts > CLIENT_MAX_ATTEMPT_LIMIT)
+ return false;
+
+ client->max_attempts = attempts;
+
+ return true;
+}
@@ -41,6 +41,7 @@ enum l_dhcp_client_event {
L_DHCP_CLIENT_EVENT_LEASE_EXPIRED,
L_DHCP_CLIENT_EVENT_LEASE_RENEWED,
L_DHCP_CLIENT_EVENT_NO_LEASE,
+ L_DHCP_CLIENT_EVENT_MAX_ATTEMPTS_REACHED,
};
enum l_dhcp_server_event {
@@ -73,6 +74,8 @@ bool l_dhcp_client_set_hostname(struct l_dhcp_client *client,
bool l_dhcp_client_set_rtnl(struct l_dhcp_client *client,
struct l_netlink *rtnl);
+bool l_dhcp_client_set_max_attempts(struct l_dhcp_client *client,
+ uint8_t attempts);
const struct l_dhcp_lease *l_dhcp_client_get_lease(
const struct l_dhcp_client *client);
@@ -255,6 +255,7 @@ global:
l_dhcp_client_set_rtnl;
l_dhcp_client_set_hostname;
l_dhcp_client_get_lease;
+ l_dhcp_client_set_max_attempts;
l_dhcp_client_start;
l_dhcp_client_stop;
l_dhcp_client_set_event_handler;
@@ -548,6 +548,12 @@ static void netconfig_dhcp_event_handler(struct l_dhcp_client *client,
if (!l_dhcp_client_start(nc->dhcp_client))
netconfig_failed(nc, AF_INET);
+ break;
+ case L_DHCP_CLIENT_EVENT_MAX_ATTEMPTS_REACHED:
+ L_WARN_ON(nc->v4_configured);
+
+ netconfig_failed(nc, AF_INET);
+
break;
}
}