+static int client_receive_ack(sd_dhcp_client *client, DHCPPacket *offer,
+ size_t len)
+{
+ int r;
+ DHCPLease *lease;
+
+ r = client_verify_headers(client, offer, len);
+ if (r < 0)
+ return r;
+
+ lease = new0(DHCPLease, 1);
+ if (!lease)
+ return -ENOBUFS;
+
+ len = len - DHCP_IP_UDP_SIZE;
+ r = dhcp_option_parse(&offer->dhcp, len, client_parse_offer, lease);
+
+ if (r != DHCP_ACK)
+ goto error;
+
+ lease->address = offer->dhcp.yiaddr;
+
+ if (lease->address == INADDR_ANY ||
+ lease->server_address == INADDR_ANY ||
+ lease->subnet_mask == INADDR_ANY || lease->lifetime == 0) {
+ r = -ENOMSG;
+ goto error;
+ }
+
+ r = DHCP_EVENT_IP_ACQUIRE;
+ if (client->lease) {
+ if (client->lease->address != lease->address ||
+ client->lease->subnet_mask != lease->subnet_mask ||
+ client->lease->router != lease->router) {
+ r = DHCP_EVENT_IP_CHANGE;
+ }
+
+ free(client->lease);
+ }
+
+ client->lease = lease;
+
+ return r;
+
+error:
+ free(lease);
+
+ return r;
+}
+