[systemd-devel] [PATCH 3/6] libsystemd-dhcp: Add Init-Reboot support
Patrik Flykt
patrik.flykt at linux.intel.com
Fri Jan 31 01:31:22 PST 2014
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-dhcp/sd-dhcp-client.c | 59 ++++++++++++++++++++++++++++++++----
1 file changed, 53 insertions(+), 6 deletions(-)
diff --git a/src/libsystemd-dhcp/sd-dhcp-client.c b/src/libsystemd-dhcp/sd-dhcp-client.c
index ffb304d..79a92e5 100644
--- a/src/libsystemd-dhcp/sd-dhcp-client.c
+++ b/src/libsystemd-dhcp/sd-dhcp-client.c
@@ -513,7 +513,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);
@@ -525,6 +535,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);
@@ -578,9 +598,14 @@ 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;
+
+ /* 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:
@@ -628,6 +653,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:
@@ -635,11 +661,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:
@@ -1096,20 +1124,37 @@ static int client_receive_message(sd_event_source *s, int fd,
break;
+ case DHCP_STATE_REBOOTING:
case DHCP_STATE_REQUESTING:
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
r = client_receive_ack(client, buf, 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) {
+ client->state = DHCP_STATE_INIT;
+ client->attempt = 1;
+ client->receive_message =
+ sd_event_source_unref(client->receive_message);
+
+ client_initialize_events(client, time_now);
+ return 0;
+ }
+
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;
@@ -1138,7 +1183,6 @@ static int client_receive_message(sd_event_source *s, int fd,
case DHCP_STATE_INIT:
case DHCP_STATE_INIT_REBOOT:
- case DHCP_STATE_REBOOTING:
case DHCP_STATE_BOUND:
break;
@@ -1160,6 +1204,9 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
assert_return(client->state == DHCP_STATE_INIT ||
client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
+ if (client->last_addr)
+ client->state = DHCP_STATE_INIT_REBOOT;
+
client->xid = random_u32();
r = dhcp_network_bind_raw_socket(client->index, &client->link);
--
1.8.5.2
More information about the systemd-devel
mailing list