+int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
+ size_t addr_len, uint16_t arp_type) {
+ DHCP_CLIENT_DONT_DESTROY(client);
+ bool need_restart = false;
+
+ assert_return(client, -EINVAL);
+ assert_return(addr, -EINVAL);
+ assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
+ assert_return(arp_type > 0, -EINVAL);
+
+ if (arp_type == ARPHRD_ETHER)
+ assert_return(addr_len == ETH_ALEN, -EINVAL);
+ else if (arp_type == ARPHRD_INFINIBAND)
+ assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+ else
+ return -EINVAL;
+
+ if (client->mac_addr_len == addr_len &&
+ memcmp(&client->mac_addr, addr, addr_len) == 0)
+ return 0;
+
+ if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
+ log_dhcp_client(client, "Changing MAC address on running DHCP "
+ "client, restarting");
+ need_restart = true;
+ client_stop(client, DHCP_EVENT_STOP);
+ }
+
+ memcpy(&client->mac_addr, addr, addr_len);
+ client->mac_addr_len = addr_len;
+ client->arp_type = arp_type;
+
+ if (need_restart && client->state != DHCP_STATE_STOPPED)
+ sd_dhcp_client_start(client);
+
+ return 0;
+}
+
+int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
+ const uint8_t **data, size_t *data_len) {
+
+ assert_return(client, -EINVAL);
+ assert_return(type, -EINVAL);
+ assert_return(data, -EINVAL);
+ assert_return(data_len, -EINVAL);
+
+ *type = 0;
+ *data = NULL;
+ *data_len = 0;
+ if (client->client_id_len) {
+ *type = client->client_id.raw.type;
+ *data = client->client_id.raw.data;
+ *data_len = client->client_id_len -
+ sizeof (client->client_id.raw.type);
+ }
+
+ return 0;
+}
+
+int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
+ const uint8_t *data, size_t data_len) {
+ DHCP_CLIENT_DONT_DESTROY(client);
+ bool need_restart = false;
+
+ assert_return(client, -EINVAL);
+ assert_return(data, -EINVAL);
+ assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
+
+ switch (type) {
+ case ARPHRD_ETHER:
+ if (data_len != ETH_ALEN)
+ return -EINVAL;
+ break;
+ case ARPHRD_INFINIBAND:
+ if (data_len != INFINIBAND_ALEN)
+ return -EINVAL;
+ break;
+ default:
+ break;
+ }
+
+ if (client->client_id_len == data_len + sizeof (client->client_id.raw.type) &&
+ client->client_id.raw.type == type &&
+ memcmp(&client->client_id.raw.data, data, data_len) == 0)
+ return 0;
+
+ if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
+ log_dhcp_client(client, "Changing client ID on running DHCP "
+ "client, restarting");
+ need_restart = true;
+ client_stop(client, DHCP_EVENT_STOP);
+ }
+
+ client->client_id.raw.type = type;
+ memcpy(&client->client_id.raw.data, data, data_len);
+ client->client_id_len = data_len + sizeof (client->client_id.raw.type);
+
+ if (need_restart && client->state != DHCP_STATE_STOPPED)
+ sd_dhcp_client_start(client);
+
+ return 0;
+}
+
+int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
+ const char *hostname) {
+ char *new_hostname = NULL;
+