#include <net/if_arp.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <sys/ioctl.h>
#include <linux/if_infiniband.h>
#define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
#define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
-struct sd_dhcp_option {
- unsigned n_ref;
-
- uint8_t option;
- void *data;
- size_t length;
-};
-
struct sd_dhcp_client {
unsigned n_ref;
DHCP_CLIENT_DONT_DESTROY(client);
bool need_restart = false;
+ int r;
assert_return(client, -EINVAL);
assert_return(addr, -EINVAL);
client->mac_addr_len = addr_len;
client->arp_type = arp_type;
- if (need_restart && client->state != DHCP_STATE_STOPPED)
- sd_dhcp_client_start(client);
+ if (need_restart && client->state != DHCP_STATE_STOPPED) {
+ r = sd_dhcp_client_start(client);
+ if (r < 0)
+ return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m");
+ }
return 0;
}
DHCP_CLIENT_DONT_DESTROY(client);
bool need_restart = false;
+ int r;
assert_return(client, -EINVAL);
assert_return(data, -EINVAL);
memcpy(&client->client_id.raw.data, data, data_len);
client->client_id_len = data_len + sizeof (client->client_id.type);
- if (need_restart && client->state != DHCP_STATE_STOPPED)
- sd_dhcp_client_start(client);
+ if (need_restart && client->state != DHCP_STATE_STOPPED) {
+ r = sd_dhcp_client_start(client);
+ if (r < 0)
+ return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m");
+ }
return 0;
}
if (duid) {
r = dhcp_validate_duid_len(duid_type, duid_len, true);
if (r < 0)
- return r;
+ return log_dhcp_client_errno(client, r, "Failed to validate length of DUID: %m");
}
zero(client->client_id);
true,
&client->client_id.ns.iaid);
if (r < 0)
- return r;
+ return log_dhcp_client_errno(client, r, "Failed to set IAID: %m");
}
}
switch (duid_type) {
case DUID_TYPE_LLT:
if (client->mac_addr_len == 0)
- return -EOPNOTSUPP;
+ return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LLT, MAC address is not set.");
r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &len);
if (r < 0)
- return r;
+ return log_dhcp_client_errno(client, r, "Failed to set DUID-LLT: %m");
break;
case DUID_TYPE_EN:
r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
if (r < 0)
- return r;
+ return log_dhcp_client_errno(client, r, "Failed to set DUID-EN: %m");
break;
case DUID_TYPE_LL:
if (client->mac_addr_len == 0)
- return -EOPNOTSUPP;
+ return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LL, MAC address is not set.");
r = dhcp_identifier_set_duid_ll(&client->client_id.ns.duid, client->mac_addr, client->mac_addr_len, client->arp_type, &len);
if (r < 0)
- return r;
+ return log_dhcp_client_errno(client, r, "Failed to set DUID-LL: %m");
break;
case DUID_TYPE_UUID:
r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len);
if (r < 0)
- return r;
+ return log_dhcp_client_errno(client, r, "Failed to set DUID-UUID: %m");
break;
default:
- return -EINVAL;
+ return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Invalid DUID type");
}
client->client_id_len = sizeof(client->client_id.type) + len +
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
log_dhcp_client(client, "Configured %sDUID, restarting.", iaid_append ? "IAID+" : "");
client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
- sd_dhcp_client_start(client);
+ r = sd_dhcp_client_start(client);
+ if (r < 0)
+ return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m");
}
return 0;
return 0;
}
-static sd_dhcp_option* dhcp_option_free(sd_dhcp_option *i) {
- if (!i)
- return NULL;
-
- free(i->data);
- return mfree(i);
-}
-
-int sd_dhcp_option_new(uint8_t option, void *data, size_t length, sd_dhcp_option **ret) {
- _cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *p = NULL;
- _cleanup_free_ void *q = NULL;
-
- assert(ret);
-
- q = memdup(data, length);
- if (!q)
- return -ENOMEM;
-
- p = new(sd_dhcp_option, 1);
- if (!p)
- return -ENOMEM;
-
- *p = (sd_dhcp_option) {
- .n_ref = 1,
- .option = option,
- .length = length,
- .data = TAKE_PTR(q),
- };
-
- *ret = TAKE_PTR(p);
- return 0;
-}
-
-DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option, sd_dhcp_option, dhcp_option_free);
-DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
- dhcp_option_hash_ops,
- void,
- trivial_hash_func,
- trivial_compare_func,
- sd_dhcp_option,
- sd_dhcp_option_unref);
-
int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v) {
int r;
address be assigned, and may include the ’IP address lease time’
option to suggest the lease time it would like.
*/
- if (client->last_addr != INADDR_ANY) {
+ /* RFC7844 section 3:
+ SHOULD NOT contain any other option. */
+ if (!client->anonymize && client->last_addr != INADDR_ANY) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
4, &client->last_addr);
}
static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) {
- assert(client);
+ if (!client)
+ return NULL;
log_dhcp_client(client, "FREE");
DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free);
int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
- _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL;
-
assert_return(ret, -EINVAL);
- client = new(sd_dhcp_client, 1);
+ _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = new(sd_dhcp_client, 1);
if (!client)
return -ENOMEM;