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;
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;
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;
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) {
client->event_priority);
if (r < 0)
goto error;
- }
+ } else if (r == -ENOMSG)
+ /* invalid message, let's ignore it */
+ return 0;
break;
case DHCP_STATE_REBINDING:
r = client_handle_ack(client, message, len);
-
if (r == DHCP_EVENT_NO_LEASE) {
client->timeout_resend =
}
goto error;
- }
-
- if (r >= 0) {
+ } else if (r >= 0) {
client->timeout_resend =
sd_event_source_unref(client->timeout_resend);
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;
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;
+}