Otherwise current value is 6 and after 6 it will give up.
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>MaxAttempts=</varname></term>
+ <listitem>
+ <para>Specifies how many times the DHCPv4 client configuration should be attempted. Takes a
+ number or <literal>infinity</literal>. Defaults to <literal>infinity</literal>.
+ Note that the time between retries is increased exponentially, so the network will not be
+ overloaded even if this number is high.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>DUIDType=</varname></term>
<listitem>
#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
-#define MAX_CLIENT_ATTEMPT 6
-
#define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
#define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
uint32_t mtu;
uint32_t xid;
usec_t start_time;
- unsigned attempt;
+ uint64_t attempt;
+ uint64_t max_attempts;
usec_t request_sent;
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
return 0;
}
+int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempts) {
+ assert_return(client, -EINVAL);
+
+ client->max_attempts = max_attempts;
+
+ return 0;
+}
+
int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
assert_return(client, -EINVAL);
case DHCP_STATE_REQUESTING:
case DHCP_STATE_BOUND:
- if (client->attempt < MAX_CLIENT_ATTEMPT)
+ if (client->attempt < client->max_attempts)
client->attempt++;
else
goto error;
- next_timeout = time_now + ((UINT64_C(1) << client->attempt) - 1) * USEC_PER_SEC;
+ next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC;
break;
if (r >= 0) {
client->state = DHCP_STATE_SELECTING;
client->attempt = 0;
- } else {
- if (client->attempt >= MAX_CLIENT_ATTEMPT)
- goto error;
- }
+ } else if (client->attempt >= client->max_attempts)
+ goto error;
break;
case DHCP_STATE_SELECTING:
r = client_send_discover(client);
- if (r < 0 && client->attempt >= MAX_CLIENT_ATTEMPT)
+ if (r < 0 && client->attempt >= client->max_attempts)
goto error;
break;
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
r = client_send_request(client);
- if (r < 0 && client->attempt >= MAX_CLIENT_ATTEMPT)
+ if (r < 0 && client->attempt >= client->max_attempts)
goto error;
if (client->state == DHCP_STATE_INIT_REBOOT)
.mtu = DHCP_DEFAULT_MIN_SIZE,
.port = DHCP_PORT_CLIENT,
.anonymize = !!anonymize,
+ .max_attempts = (uint64_t) -1,
};
/* NOTE: this could be moved to a function. */
if (anonymize) {
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set listen port: %m");
}
+ if (link->network->dhcp_max_attempts > 0) {
+ r = sd_dhcp_client_set_max_attempts(link->dhcp_client, link->network->dhcp_max_attempts);
+ if (r < 0)
+ return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set max attempts: %m");
+ }
+
return dhcp4_set_client_identifier(link);
}
DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast)
DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
+DHCP.MaxAttempts, config_parse_dhcp_max_attempts, 0, 0
DHCP.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class)
DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid)
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
return 0;
}
+int config_parse_dhcp_max_attempts(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *network = data;
+ uint64_t a;
+ int r;
+
+ assert(network);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ network->dhcp_max_attempts = 0;
+ return 0;
+ }
+
+ if (streq(rvalue, "infinity")) {
+ network->dhcp_max_attempts = (uint64_t) -1;
+ return 0;
+ }
+
+ r = safe_atou64(rvalue, &a);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (a == 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue);
+ return 0;
+ }
+
+ network->dhcp_max_attempts = a;
+
+ return 0;
+}
+
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
"Failed to parse DHCP use domains setting");
char *dhcp_vendor_class_identifier;
char **dhcp_user_class;
char *dhcp_hostname;
+ uint64_t dhcp_max_attempts;
unsigned dhcp_route_metric;
uint32_t dhcp_route_table;
uint16_t dhcp_client_port;
CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
/* Legacy IPv4LL support */
CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
int sd_dhcp_client_set_mtu(
sd_dhcp_client *client,
uint32_t mtu);
+int sd_dhcp_client_set_max_attempts(
+ sd_dhcp_client *client,
+ uint64_t attempt);
int sd_dhcp_client_set_client_port(
sd_dhcp_client *client,
uint16_t port);
DefaultLeaseTimeSec=
EmitTimezone=
DNS=
+MaxAttempts=
[DHCPv4]
UseHostname=
UseMTU=