return client_initialize_time_events(client);
}
-static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_t len) {
+static int client_parse_message(
+ sd_dhcp_client *client,
+ DHCPMessage *message,
+ size_t len,
+ sd_dhcp_lease **ret) {
+
_cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
+ _cleanup_free_ char *error_message = NULL;
int r;
+ assert(client);
+ assert(message);
+ assert(ret);
+
r = dhcp_lease_new(&lease);
if (r < 0)
return r;
return r;
}
- r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease, NULL);
- if (r != DHCP_OFFER)
- return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
- "received message was not an OFFER, ignoring");
+ r = dhcp_option_parse(message, len, dhcp_lease_parse_options, lease, &error_message);
+ if (r < 0)
+ return log_dhcp_client_errno(client, r, "Failed to parse DHCP options, ignoring: %m");
- lease->next_server = offer->siaddr;
- lease->address = offer->yiaddr;
+ switch (client->state) {
+ case DHCP_STATE_SELECTING:
+ if (r != DHCP_OFFER)
+ return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
+ "received message was not an OFFER, ignoring.");
- if (lease->lifetime == 0 && client->fallback_lease_lifetime > 0)
- lease->lifetime = client->fallback_lease_lifetime;
+ if (lease->lifetime == 0 && client->fallback_lease_lifetime > 0)
+ lease->lifetime = client->fallback_lease_lifetime;
+
+ break;
+
+ case DHCP_STATE_REBOOTING:
+ case DHCP_STATE_REQUESTING:
+ case DHCP_STATE_RENEWING:
+ case DHCP_STATE_REBINDING:
+ if (r == DHCP_NAK)
+ return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
+ "NAK: %s", strna(error_message));
+ if (r != DHCP_ACK)
+ return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
+ "received message was not an ACK, ignoring.");
+ break;
+
+ default:
+ assert_not_reached();
+ }
+
+ lease->next_server = message->siaddr;
+ lease->address = message->yiaddr;
if (lease->address == 0 ||
lease->server_address == 0 ||
lease->lifetime == 0)
return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
- "received lease lacks address, server address or lease lifetime, ignoring");
+ "received lease lacks address, server address or lease lifetime, ignoring.");
r = dhcp_lease_set_default_subnet_mask(lease);
if (r < 0)
return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
"received lease lacks subnet mask, and a fallback one cannot be generated, ignoring.");
+ *ret = TAKE_PTR(lease);
+ return 0;
+}
+
+static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *message, size_t len) {
+ _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
+ int r;
+
+ assert(client);
+ assert(message);
+
+ r = client_parse_message(client, message, len, &lease);
+ if (r < 0)
+ return r;
+
dhcp_lease_unref_and_replace(client->lease, lease);
if (client_notify(client, SD_DHCP_CLIENT_EVENT_SELECTING) < 0)
return true;
}
-static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t len) {
+static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *message, size_t len) {
_cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
- _cleanup_free_ char *error_message = NULL;
int r;
- r = dhcp_lease_new(&lease);
- if (r < 0)
- return r;
-
- if (client->client_id_len > 0) {
- r = dhcp_lease_set_client_id(lease,
- (uint8_t *) &client->client_id,
- client->client_id_len);
- if (r < 0)
- return r;
- }
-
- r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease, &error_message);
- if (r == DHCP_NAK)
- return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
- "NAK: %s", strna(error_message));
-
- if (r != DHCP_ACK)
- return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
- "received message was not an ACK, ignoring");
-
- lease->next_server = ack->siaddr;
-
- lease->address = ack->yiaddr;
-
- if (lease->address == INADDR_ANY ||
- lease->server_address == INADDR_ANY ||
- lease->lifetime == 0)
- return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
- "received lease lacks address, server address or lease lifetime, ignoring");
+ assert(client);
+ assert(message);
- r = dhcp_lease_set_default_subnet_mask(lease);
+ r = client_parse_message(client, message, len, &lease);
if (r < 0)
- return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
- "received lease lacks subnet mask, and a fallback one cannot be generated, ignoring.");
+ return r;
if (!client->lease)
r = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
case DHCP_STATE_SELECTING:
r = client_handle_offer(client, message, len);
- if (r == -ENOMSG)
- return 0; /* invalid message, let's ignore it */
- if (r < 0)
+ if (ERRNO_IS_NEG_RESOURCE(r))
goto error;
+ if (r < 0)
+ return 0; /* invalid message, let's ignore it */
r = client_enter_requesting(client);
break;
case DHCP_STATE_REBINDING:
r = client_handle_ack(client, message, len);
- if (r == -ENOMSG)
- return 0; /* invalid message, let's ignore it */
+ if (ERRNO_IS_NEG_RESOURCE(r))
+ goto error;
if (r == -EADDRNOTAVAIL) {
/* got a NAK, let's restart the client */
client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED);
return 0;
}
if (r < 0)
- goto error;
+ return 0; /* invalid message, let's ignore it */
r = client_enter_bound(client, r);
break;