Init-Reboot is tried if a client IP address has been given when the DHCP client is started. In Init-Reboot, start by sending a broadcasted DHCP Request including the supplied client IP address but without the server identifier. After sending the request, enter Reboot state.
If a DHCP Ack is received, proceed to Bound state as usual. If a DHCP Nak is received or the first timeout triggers, start the address acquisition over from DHCP Init state. See RFC 2131, sections 4.3.2, 4.4, 4.4.1 and 4.4.2 for details. --- src/libsystemd-network/sd-dhcp-client.c | 57 +++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 74e560b..c301a3f 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -340,7 +340,17 @@ static int client_send_request(sd_dhcp_client *client, uint16_t secs) { if (err < 0) return err; - if (client->state == DHCP_STATE_REQUESTING) { + switch (client->state) { + + case DHCP_STATE_INIT_REBOOT: + err = dhcp_option_append(&opt, &optlen, + DHCP_OPTION_REQUESTED_IP_ADDRESS, + 4, &client->last_addr); + if (err < 0) + return err; + break; + + case DHCP_STATE_REQUESTING: err = dhcp_option_append(&opt, &optlen, DHCP_OPTION_REQUESTED_IP_ADDRESS, 4, &client->lease->address); @@ -352,6 +362,16 @@ static int client_send_request(sd_dhcp_client *client, uint16_t secs) { 4, &client->lease->server_address); if (err < 0) return err; + break; + + case DHCP_STATE_INIT: + case DHCP_STATE_SELECTING: + case DHCP_STATE_REBOOTING: + case DHCP_STATE_BOUND: + case DHCP_STATE_RENEWING: + case DHCP_STATE_REBINDING: + + break; } err = dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL); @@ -413,9 +433,15 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, next_timeout = usec + time_left * USEC_PER_SEC; break; + case DHCP_STATE_REBOOTING: + /* start over as we did not receive a timely ack or nak */ + client->state = DHCP_STATE_INIT; + client->attempt = 1; + client->xid = random_u32(); + + /* fall through */ case DHCP_STATE_INIT: case DHCP_STATE_INIT_REBOOT: - case DHCP_STATE_REBOOTING: case DHCP_STATE_SELECTING: case DHCP_STATE_REQUESTING: case DHCP_STATE_BOUND: @@ -470,6 +496,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, break; + case DHCP_STATE_INIT_REBOOT: case DHCP_STATE_REQUESTING: case DHCP_STATE_RENEWING: case DHCP_STATE_REBINDING: @@ -477,11 +504,13 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, if (r < 0 && client->attempt >= 64) goto error; + if (client->state == DHCP_STATE_INIT_REBOOT) + client->state = DHCP_STATE_REBOOTING; + client->request_sent = usec; break; - case DHCP_STATE_INIT_REBOOT: case DHCP_STATE_REBOOTING: case DHCP_STATE_BOUND: @@ -859,20 +888,37 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, break; + case DHCP_STATE_REBOOTING: case DHCP_STATE_REQUESTING: case DHCP_STATE_RENEWING: case DHCP_STATE_REBINDING: r = client_handle_ack(client, message, len); - if (r == DHCP_EVENT_NO_LEASE) + if (r == DHCP_EVENT_NO_LEASE) { + + client->timeout_resend = + sd_event_source_unref(client->timeout_resend); + + if (client->state == DHCP_STATE_REBOOTING) { + r = client_initialize(client); + if (r < 0) + goto error; + + r = client_start(client); + if (r < 0) + goto error; + } + goto error; + } if (r >= 0) { client->timeout_resend = sd_event_source_unref(client->timeout_resend); - if (client->state == DHCP_STATE_REQUESTING) + if (client->state == DHCP_STATE_REQUESTING || + client->state == DHCP_STATE_REBOOTING) notify_event = DHCP_EVENT_IP_ACQUIRE; else if (r != DHCP_EVENT_IP_ACQUIRE) notify_event = r; @@ -901,7 +947,6 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, case DHCP_STATE_INIT: case DHCP_STATE_INIT_REBOOT: - case DHCP_STATE_REBOOTING: case DHCP_STATE_BOUND: break; -- 1.8.5.2 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel