diff options
Diffstat (limited to 'src/libsystemd-network/sd-dhcp-client.c')
-rw-r--r-- | src/libsystemd-network/sd-dhcp-client.c | 75 |
1 files changed, 48 insertions, 27 deletions
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 4521f8f0b1..cad1a52c09 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -43,6 +43,9 @@ #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 RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC) +#define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE) + struct sd_dhcp_client { unsigned n_ref; @@ -101,14 +104,15 @@ struct sd_dhcp_client { sd_dhcp_client_cb_t cb; void *userdata; sd_dhcp_lease *lease; + usec_t start_delay; }; static const uint8_t default_req_opts[] = { - DHCP_OPTION_SUBNET_MASK, - DHCP_OPTION_ROUTER, - DHCP_OPTION_HOST_NAME, - DHCP_OPTION_DOMAIN_NAME, - DHCP_OPTION_DOMAIN_NAME_SERVER, + SD_DHCP_OPTION_SUBNET_MASK, + SD_DHCP_OPTION_ROUTER, + SD_DHCP_OPTION_HOST_NAME, + SD_DHCP_OPTION_DOMAIN_NAME, + SD_DHCP_OPTION_DOMAIN_NAME_SERVER, }; static int client_receive_message_raw(sd_event_source *s, int fd, @@ -143,11 +147,11 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) { DHCP_STATE_STOPPED), -EBUSY); switch(option) { - case DHCP_OPTION_PAD: - case DHCP_OPTION_OVERLOAD: - case DHCP_OPTION_MESSAGE_TYPE: - case DHCP_OPTION_PARAMETER_REQUEST_LIST: - case DHCP_OPTION_END: + case SD_DHCP_OPTION_PAD: + case SD_DHCP_OPTION_OVERLOAD: + case SD_DHCP_OPTION_MESSAGE_TYPE: + case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST: + case SD_DHCP_OPTION_END: return -EINVAL; default: @@ -486,7 +490,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret, Identifier option is not set */ if (client->client_id_len) { r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, - DHCP_OPTION_CLIENT_IDENTIFIER, + SD_DHCP_OPTION_CLIENT_IDENTIFIER, client->client_id_len, &client->client_id); if (r < 0) @@ -502,7 +506,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret, messages. */ r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, - DHCP_OPTION_PARAMETER_REQUEST_LIST, + SD_DHCP_OPTION_PARAMETER_REQUEST_LIST, client->req_opts_size, client->req_opts); if (r < 0) return r; @@ -531,7 +535,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret, */ max_size = htobe16(size); r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0, - DHCP_OPTION_MAXIMUM_MESSAGE_SIZE, + SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE, 2, &max_size); if (r < 0) return r; @@ -557,7 +561,7 @@ static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false); if (r > 0) r = dhcp_option_append(message, optlen, optoffset, 0, - DHCP_OPTION_FQDN, 3 + r, buffer); + SD_DHCP_OPTION_FQDN, 3 + r, buffer); return r; } @@ -593,7 +597,7 @@ static int client_send_discover(sd_dhcp_client *client) { */ if (client->last_addr != INADDR_ANY) { r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, - DHCP_OPTION_REQUESTED_IP_ADDRESS, + SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, 4, &client->last_addr); if (r < 0) return r; @@ -609,7 +613,7 @@ static int client_send_discover(sd_dhcp_client *client) { DHCPDISCOVER but dhclient does and so we do as well */ r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, - DHCP_OPTION_HOST_NAME, + SD_DHCP_OPTION_HOST_NAME, strlen(client->hostname), client->hostname); } else r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset, @@ -620,7 +624,7 @@ static int client_send_discover(sd_dhcp_client *client) { if (client->vendor_class_identifier) { r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, - DHCP_OPTION_VENDOR_CLASS_IDENTIFIER, + SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER, strlen(client->vendor_class_identifier), client->vendor_class_identifier); if (r < 0) @@ -628,7 +632,7 @@ static int client_send_discover(sd_dhcp_client *client) { } r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, - DHCP_OPTION_END, 0, NULL); + SD_DHCP_OPTION_END, 0, NULL); if (r < 0) return r; @@ -667,13 +671,13 @@ static int client_send_request(sd_dhcp_client *client) { */ r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - DHCP_OPTION_SERVER_IDENTIFIER, + SD_DHCP_OPTION_SERVER_IDENTIFIER, 4, &client->lease->server_address); if (r < 0) return r; r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - DHCP_OPTION_REQUESTED_IP_ADDRESS, + SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, 4, &client->lease->address); if (r < 0) return r; @@ -686,7 +690,7 @@ static int client_send_request(sd_dhcp_client *client) { assigned address. ’ciaddr’ MUST be zero. */ r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - DHCP_OPTION_REQUESTED_IP_ADDRESS, + SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, 4, &client->last_addr); if (r < 0) return r; @@ -721,7 +725,7 @@ static int client_send_request(sd_dhcp_client *client) { if (client->hostname) { if (dns_name_is_single_label(client->hostname)) r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - DHCP_OPTION_HOST_NAME, + SD_DHCP_OPTION_HOST_NAME, strlen(client->hostname), client->hostname); else r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset, @@ -731,7 +735,7 @@ static int client_send_request(sd_dhcp_client *client) { } r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, - DHCP_OPTION_END, 0, NULL); + SD_DHCP_OPTION_END, 0, NULL); if (r < 0) return r; @@ -945,6 +949,7 @@ error: } static int client_initialize_time_events(sd_dhcp_client *client) { + uint64_t usec = 0; int r; assert(client); @@ -952,10 +957,15 @@ static int client_initialize_time_events(sd_dhcp_client *client) { client->timeout_resend = sd_event_source_unref(client->timeout_resend); + if (client->start_delay) { + sd_event_now(client->event, clock_boottime_or_monotonic(), &usec); + usec += client->start_delay; + } + r = sd_event_add_time(client->event, &client->timeout_resend, clock_boottime_or_monotonic(), - 0, 0, + usec, 0, client_timeout_resend, client); if (r < 0) goto error; @@ -985,7 +995,7 @@ static int client_initialize_events(sd_dhcp_client *client, return 0; } -static int client_start(sd_dhcp_client *client) { +static int client_start_delayed(sd_dhcp_client *client) { int r; assert_return(client, -EINVAL); @@ -1013,6 +1023,11 @@ static int client_start(sd_dhcp_client *client) { return client_initialize_events(client, client_receive_message_raw); } +static int client_start(sd_dhcp_client *client) { + client->start_delay = 0; + return client_start_delayed(client); +} + static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp_client *client = userdata; @@ -1362,6 +1377,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, int len) { DHCP_CLIENT_DONT_DESTROY(client); + char time_string[FORMAT_TIMESPAN_MAX]; int r = 0, notify_event = 0; assert(client); @@ -1409,6 +1425,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, r = client_handle_ack(client, message, len); if (r >= 0) { + client->start_delay = 0; client->timeout_resend = sd_event_source_unref(client->timeout_resend); client->receive_message = @@ -1458,11 +1475,15 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, if (r < 0) goto error; - r = client_start(client); + r = client_start_delayed(client); if (r < 0) goto error; - log_dhcp_client(client, "REBOOTED"); + log_dhcp_client(client, "REBOOT in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, + client->start_delay, USEC_PER_SEC)); + + client->start_delay = CLAMP(client->start_delay * 2, + RESTART_AFTER_NAK_MIN_USEC, RESTART_AFTER_NAK_MAX_USEC); return 0; } else if (r == -ENOMSG) |