network: fix handling of uninitialized and zero IAID setting

An earlier commit 0e408b82b (dhcp6-client: handle IAID with value zero)
introduced a flag to sd_dhcp6_client to distinguish between an unset
IAID and a value set to zero.

However, that was not sufficient and broke leaving the setting
uninitialized in networkd configuration. The configuration parsing
also must distinguish between the default, unset value and an
explict zero configuration.

Fixes: 0e408b82b8
This commit is contained in:
Thomas Haller 2018-11-23 22:19:26 +01:00 committed by Lennart Poettering
parent 1d4c6f5bef
commit 8217ed5ec3
11 changed files with 71 additions and 55 deletions

View File

@ -371,36 +371,6 @@ int config_parse_hwaddrs(const char *unit,
return 0;
}
int config_parse_iaid(const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
uint32_t iaid;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = safe_atou32(rvalue, &iaid);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Unable to read IAID, ignoring assignment: %s", rvalue);
return 0;
}
*((uint32_t *)data) = iaid;
return 0;
}
int config_parse_bridge_port_priority(
const char *unit,
const char *filename,

View File

@ -35,7 +35,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
int net_get_unique_predictable_data(sd_device *device, uint64_t *result);

View File

@ -345,8 +345,9 @@ int sd_dhcp_client_set_client_id(
*/
static int dhcp_client_set_iaid_duid_internal(
sd_dhcp_client *client,
bool iaid_append,
bool iaid_set,
uint32_t iaid,
bool append_iaid,
uint16_t duid_type,
const void *duid,
size_t duid_len,
@ -368,17 +369,17 @@ static int dhcp_client_set_iaid_duid_internal(
zero(client->client_id);
client->client_id.type = 255;
if (append_iaid) {
/* If IAID is not configured, generate it. */
if (iaid == 0) {
if (iaid_append) {
if (iaid_set)
client->client_id.ns.iaid = htobe32(iaid);
else {
r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
client->mac_addr_len,
true,
&client->client_id.ns.iaid);
if (r < 0)
return r;
} else
client->client_id.ns.iaid = htobe32(iaid);
}
}
if (duid != NULL) {
@ -418,10 +419,10 @@ static int dhcp_client_set_iaid_duid_internal(
}
client->client_id_len = sizeof(client->client_id.type) + len +
(append_iaid ? sizeof(client->client_id.ns.iaid) : 0);
(iaid_append ? sizeof(client->client_id.ns.iaid) : 0);
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
log_dhcp_client(client, "Configured %sDUID, restarting.", append_iaid ? "IAID+" : "");
log_dhcp_client(client, "Configured %sDUID, restarting.", iaid_append ? "IAID+" : "");
client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
sd_dhcp_client_start(client);
}
@ -431,18 +432,20 @@ static int dhcp_client_set_iaid_duid_internal(
int sd_dhcp_client_set_iaid_duid(
sd_dhcp_client *client,
bool iaid_set,
uint32_t iaid,
uint16_t duid_type,
const void *duid,
size_t duid_len) {
return dhcp_client_set_iaid_duid_internal(client, iaid, true, duid_type, duid, duid_len, 0);
return dhcp_client_set_iaid_duid_internal(client, true, iaid_set, iaid, duid_type, duid, duid_len, 0);
}
int sd_dhcp_client_set_iaid_duid_llt(
sd_dhcp_client *client,
bool iaid_set,
uint32_t iaid,
usec_t llt_time) {
return dhcp_client_set_iaid_duid_internal(client, iaid, true, DUID_TYPE_LLT, NULL, 0, llt_time);
return dhcp_client_set_iaid_duid_internal(client, true, iaid_set, iaid, DUID_TYPE_LLT, NULL, 0, llt_time);
}
int sd_dhcp_client_set_duid(
@ -450,13 +453,13 @@ int sd_dhcp_client_set_duid(
uint16_t duid_type,
const void *duid,
size_t duid_len) {
return dhcp_client_set_iaid_duid_internal(client, 0, false, duid_type, duid, duid_len, 0);
return dhcp_client_set_iaid_duid_internal(client, false, false, 0, duid_type, duid, duid_len, 0);
}
int sd_dhcp_client_set_duid_llt(
sd_dhcp_client *client,
usec_t llt_time) {
return dhcp_client_set_iaid_duid_internal(client, 0, false, DUID_TYPE_LLT, NULL, 0, llt_time);
return dhcp_client_set_iaid_duid_internal(client, false, false, 0, DUID_TYPE_LLT, NULL, 0, llt_time);
}
int sd_dhcp_client_set_hostname(

View File

@ -56,7 +56,7 @@ struct sd_dhcp6_client {
struct sd_dhcp6_lease *lease;
int fd;
bool information_request;
bool has_iaid;
bool iaid_set;
be16_t *req_opts;
size_t req_opts_allocated;
size_t req_opts_len;
@ -268,7 +268,7 @@ int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
client->ia_na.ia_na.id = htobe32(iaid);
client->ia_pd.ia_pd.id = htobe32(iaid);
client->has_iaid = true;
client->iaid_set = true;
return 0;
}
@ -792,7 +792,7 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
assert(client);
if (client->has_iaid)
if (client->iaid_set)
return 0;
r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, true, &iaid);
@ -801,7 +801,7 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
client->ia_na.ia_na.id = iaid;
client->ia_pd.ia_pd.id = iaid;
client->has_iaid = true;
client->iaid_set = true;
return 0;
}

View File

@ -670,10 +670,12 @@ int dhcp4_set_client_identifier(Link *link) {
if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
r = sd_dhcp_client_set_iaid_duid_llt(link->dhcp_client,
link->network->iaid_set,
link->network->iaid,
duid->llt_time);
else
r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
link->network->iaid_set,
link->network->iaid,
duid->type,
duid->raw_data_len > 0 ? duid->raw_data : NULL,

View File

@ -655,9 +655,11 @@ int dhcp6_configure(Link *link) {
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set MAC address: %m");
r = sd_dhcp6_client_set_iaid(client, link->network->iaid);
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set IAID: %m");
if (link->network->iaid_set) {
r = sd_dhcp6_client_set_iaid(client, link->network->iaid);
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set IAID: %m");
}
duid = link_get_duid(link);
if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)

View File

@ -3637,10 +3637,12 @@ int link_update(Link *link, sd_netlink_message *m) {
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
r = sd_dhcp6_client_set_iaid(link->dhcp6_client,
link->network->iaid);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m");
if (link->network->iaid_set) {
r = sd_dhcp6_client_set_iaid(link->dhcp6_client,
link->network->iaid);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m");
}
r = sd_dhcp6_client_set_duid(link->dhcp6_client,
duid->type,

View File

@ -141,7 +141,7 @@ DHCP.DUIDRawData, config_parse_duid_rawdata,
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
DHCP.RouteTable, config_parse_dhcp_route_table, 0, 0
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
DHCP.IAID, config_parse_iaid, 0, offsetof(Network, iaid)
DHCP.IAID, config_parse_iaid, 0, 0
DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port)
DHCP.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit)
DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)

View File

@ -1473,3 +1473,35 @@ static const char* const lldp_mode_table[_LLDP_MODE_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);
int config_parse_iaid(const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *network = data;
uint32_t iaid;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(network);
r = safe_atou32(rvalue, &iaid);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Unable to read IAID, ignoring assignment: %s", rvalue);
return 0;
}
network->iaid = iaid;
network->iaid_set = true;
return 0;
}

View File

@ -227,6 +227,8 @@ struct Network {
uint32_t iaid;
DUID duid;
bool iaid_set;
bool required_for_online; /* Is this network required to be considered online? */
LLDPMode lldp_mode; /* LLDP reception */
@ -306,6 +308,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_lldp_mode);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_route_table);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
/* Legacy IPv4LL support */
CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);

View File

@ -23,6 +23,7 @@
#include <net/ethernet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <stdbool.h>
#include "sd-dhcp-lease.h"
#include "sd-event.h"
@ -127,12 +128,14 @@ int sd_dhcp_client_set_client_id(
size_t data_len);
int sd_dhcp_client_set_iaid_duid(
sd_dhcp_client *client,
bool iaid_set,
uint32_t iaid,
uint16_t duid_type,
const void *duid,
size_t duid_len);
int sd_dhcp_client_set_iaid_duid_llt(
sd_dhcp_client *client,
bool iaid_set,
uint32_t iaid,
uint64_t llt_time);
int sd_dhcp_client_set_duid(