summaryrefslogtreecommitdiff
path: root/src/libsystemd-network/sd-dhcp-client.c
diff options
context:
space:
mode:
authorPatrik Flykt <patrik.flykt@linux.intel.com>2014-01-31 11:31:22 +0200
committerPatrik Flykt <patrik.flykt@linux.intel.com>2014-03-19 10:52:40 +0200
commit8b1243f72ed321bd11f0939405b6d0963ce5eea5 (patch)
treed25952fa0cefd111d1679c70474b21dde0d1c7d1 /src/libsystemd-network/sd-dhcp-client.c
parent0f941add365638ad487ba94017cc2cf1f8d45195 (diff)
libsystemd-network: Add Init-Reboot support
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 broadcast 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.
Diffstat (limited to 'src/libsystemd-network/sd-dhcp-client.c')
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c57
1 files changed, 51 insertions, 6 deletions
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 792e4af9c6..84111412d1 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -338,7 +338,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);
@@ -350,6 +360,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);
@@ -416,9 +436,15 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
next_timeout = time_now + 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:
@@ -473,6 +499,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:
@@ -480,11 +507,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 = time_now;
break;
- case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_REBOOTING:
case DHCP_STATE_BOUND:
@@ -853,20 +882,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 (IN_SET(client->state, DHCP_STATE_REQUESTING,
+ DHCP_STATE_REBOOTING))
notify_event = DHCP_EVENT_IP_ACQUIRE;
else if (r != DHCP_EVENT_IP_ACQUIRE)
notify_event = r;
@@ -894,7 +940,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;