From 8217ed5ec34e58ef791bcf9637e301aba608b711 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 23 Nov 2018 22:19:26 +0100 Subject: [PATCH] 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: 0e408b82b8bd7675234cf58009475d4f4c0a491a --- src/libsystemd-network/network-internal.c | 30 --------------------- src/libsystemd-network/network-internal.h | 1 - src/libsystemd-network/sd-dhcp-client.c | 27 ++++++++++--------- src/libsystemd-network/sd-dhcp6-client.c | 8 +++--- src/network/networkd-dhcp4.c | 2 ++ src/network/networkd-dhcp6.c | 8 +++--- src/network/networkd-link.c | 10 ++++--- src/network/networkd-network-gperf.gperf | 2 +- src/network/networkd-network.c | 32 +++++++++++++++++++++++ src/network/networkd-network.h | 3 +++ src/systemd/sd-dhcp-client.h | 3 +++ 11 files changed, 71 insertions(+), 55 deletions(-) diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index d35e3e2ce1..b3b134d650 100644 --- a/src/libsystemd-network/network-internal.c +++ b/src/libsystemd-network/network-internal.c @@ -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, diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h index 45020c2bcf..0c8da848c1 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -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); diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 842aeaa6b1..3bdd584bb5 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -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( diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 555ae5f5ec..8ff4585f63 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -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; } diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 31dbea9420..980d49e4ff 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -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, diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 4b5c4b8b4b..ed6b9df72b 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -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) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index d575740e83..d73e85cf25 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -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, diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 00605c0b92..48d8ae52fa 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -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) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 6f14fb270e..62dc6a0bf7 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -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; +} diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 7f64c38839..3a72c5bd9a 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -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); diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h index e388552064..bd0d429df6 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -23,6 +23,7 @@ #include #include #include +#include #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(