mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-10 01:17:44 +03:00
sd-dhcp-client: add fallback subnet masks
The DHCP RFC does not require the DHCP server to send a subnet mask, so if it is missing, let's try to use the default subnet masks based on address class. In case the class the address belongs to does not have a default subnet mask, we fail as before. Also improve logging when handling invalid dhcp messages, and simply ignore them rather than stop the whole dhcp client.
This commit is contained in:
parent
022446adf9
commit
9e64dd7276
@ -57,5 +57,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
|
||||
int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
|
||||
int dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret);
|
||||
|
||||
int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_lease*, sd_dhcp_lease_unref);
|
||||
#define _cleanup_dhcp_lease_unref_ _cleanup_(sd_dhcp_lease_unrefp)
|
||||
|
@ -673,8 +673,10 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
|
||||
return r;
|
||||
|
||||
r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
|
||||
if (r != DHCP_OFFER)
|
||||
if (r != DHCP_OFFER) {
|
||||
log_dhcp_client(client, "receieved message was not an OFFER, ignoring");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
lease->next_server = offer->siaddr;
|
||||
|
||||
@ -682,9 +684,21 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
|
||||
|
||||
if (lease->address == INADDR_ANY ||
|
||||
lease->server_address == INADDR_ANY ||
|
||||
lease->subnet_mask == INADDR_ANY ||
|
||||
lease->lifetime == 0)
|
||||
lease->lifetime == 0) {
|
||||
log_dhcp_client(client, "receieved lease lacks address, server "
|
||||
"address or lease lifetime, ignoring");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
if (lease->subnet_mask == INADDR_ANY) {
|
||||
r = dhcp_lease_set_default_subnet_mask(lease);
|
||||
if (r < 0) {
|
||||
log_dhcp_client(client, "receieved lease lacks subnet "
|
||||
"mask, and a fallback one can not be "
|
||||
"generated, ignoring");
|
||||
return -ENOMSG;
|
||||
}
|
||||
}
|
||||
|
||||
client->lease = lease;
|
||||
lease = NULL;
|
||||
@ -709,8 +723,10 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
|
||||
return DHCP_EVENT_NO_LEASE;
|
||||
}
|
||||
|
||||
if (r != DHCP_ACK)
|
||||
if (r != DHCP_ACK) {
|
||||
log_dhcp_client(client, "receieved message was not an ACK, ignoring");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
lease->next_server = ack->siaddr;
|
||||
|
||||
@ -718,8 +734,21 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
|
||||
|
||||
if (lease->address == INADDR_ANY ||
|
||||
lease->server_address == INADDR_ANY ||
|
||||
lease->subnet_mask == INADDR_ANY || lease->lifetime == 0)
|
||||
lease->lifetime == 0) {
|
||||
log_dhcp_client(client, "receieved lease lacks address, server "
|
||||
"address or lease lifetime, ignoring");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
if (lease->subnet_mask == INADDR_ANY) {
|
||||
r = dhcp_lease_set_default_subnet_mask(lease);
|
||||
if (r < 0) {
|
||||
log_dhcp_client(client, "receieved lease lacks subnet "
|
||||
"mask, and a fallback one can not be "
|
||||
"generated, ignoring");
|
||||
return -ENOMSG;
|
||||
}
|
||||
}
|
||||
|
||||
r = DHCP_EVENT_IP_ACQUIRE;
|
||||
if (client->lease) {
|
||||
@ -940,7 +969,9 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
|
||||
client->event_priority);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
}
|
||||
} else if (r == -ENOMSG)
|
||||
/* invalid message, let's ignore it */
|
||||
return 0;
|
||||
|
||||
break;
|
||||
|
||||
@ -950,7 +981,6 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
|
||||
case DHCP_STATE_REBINDING:
|
||||
|
||||
r = client_handle_ack(client, message, len);
|
||||
|
||||
if (r == DHCP_EVENT_NO_LEASE) {
|
||||
|
||||
client->timeout_resend =
|
||||
@ -967,9 +997,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
|
||||
}
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (r >= 0) {
|
||||
} else if (r >= 0) {
|
||||
client->timeout_resend =
|
||||
sd_event_source_unref(client->timeout_resend);
|
||||
|
||||
@ -994,9 +1022,9 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
|
||||
client->receive_message =
|
||||
sd_event_source_unref(client->receive_message);
|
||||
client->fd = safe_close(client->fd);
|
||||
}
|
||||
|
||||
r = 0;
|
||||
} else if (r == -ENOMSG)
|
||||
/* invalid message, let's ignore it */
|
||||
return 0;
|
||||
|
||||
break;
|
||||
|
||||
|
@ -481,3 +481,29 @@ int dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {
|
||||
uint32_t address;
|
||||
|
||||
assert(lease);
|
||||
assert(lease->address != INADDR_ANY);
|
||||
|
||||
address = be32toh(lease->address);
|
||||
|
||||
/* fall back to the default subnet masks based on address class */
|
||||
|
||||
if ((address >> 31) == 0x0)
|
||||
/* class A, leading bits: 0 */
|
||||
lease->subnet_mask = htobe32(0xff000000);
|
||||
else if ((address >> 30) == 0x2)
|
||||
/* class B, leading bits 10 */
|
||||
lease->subnet_mask = htobe32(0xffff0000);
|
||||
else if ((address >> 29) == 0x6)
|
||||
/* class C, leading bits 110 */
|
||||
lease->subnet_mask = htobe32(0xffffff00);
|
||||
else
|
||||
/* class D or E, no default mask. give up */
|
||||
return -ERANGE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user