diff options
-rw-r--r-- | src/network/networkd-conf.c | 69 | ||||
-rw-r--r-- | src/network/networkd-dhcp4.c | 31 | ||||
-rw-r--r-- | src/network/networkd-dhcp6.c | 11 | ||||
-rw-r--r-- | src/network/networkd-gperf.gperf | 2 | ||||
-rw-r--r-- | src/network/networkd-network-gperf.gperf | 2 | ||||
-rw-r--r-- | src/network/networkd-network.h | 1 | ||||
-rw-r--r-- | src/network/test-networkd-conf.c | 27 |
7 files changed, 115 insertions, 28 deletions
diff --git a/src/network/networkd-conf.c b/src/network/networkd-conf.c index 05bbc0b3e9..334ffc3c57 100644 --- a/src/network/networkd-conf.c +++ b/src/network/networkd-conf.c @@ -31,7 +31,74 @@ static const char* const duid_type_table[_DUID_TYPE_MAX] = { [DUID_TYPE_UUID] = "uuid", }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType); -DEFINE_CONFIG_PARSE_ENUM(config_parse_duid_type, duid_type, DUIDType, "Failed to parse DUID type"); + +int config_parse_duid_type( + 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) { + + _cleanup_free_ char *type_string = NULL; + const char *p = rvalue; + DUID *duid = data; + DUIDType type; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(duid); + + r = extract_first_word(&p, &type_string, ":", 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + if (r == 0) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to extract DUID type from '%s', ignoring.", rvalue); + return 0; + } + + type = duid_type_from_string(type_string); + if (type < 0) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to parse DUID type '%s', ignoring.", type_string); + return 0; + } + + if (!isempty(p)) { + usec_t u; + + if (type != DUID_TYPE_LLT) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + r = parse_timestamp(p, &u); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse timestamp, ignoring: %s", p); + return 0; + } + + duid->llt_time = u; + } + + duid->type = type; + + return 0; +} int config_parse_duid_rawdata( const char *unit, diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index a3bdf4f40a..18867d9401 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -669,26 +669,35 @@ int dhcp4_set_client_identifier(Link *link) { switch (link->network->dhcp_client_identifier) { case DHCP_CLIENT_ID_DUID: { - /* If configured, apply user specified DUID and/or IAID */ + /* If configured, apply user specified DUID and IAID */ const DUID *duid = link_get_duid(link); - r = sd_dhcp_client_set_iaid_duid(link->dhcp_client, - link->network->iaid, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); + 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, + duid->llt_time); + else + r = sd_dhcp_client_set_iaid_duid(link->dhcp_client, + link->network->iaid, + duid->type, + duid->raw_data_len > 0 ? duid->raw_data : NULL, + duid->raw_data_len); if (r < 0) - return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m"); + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set IAID+DUID: %m"); break; } case DHCP_CLIENT_ID_DUID_ONLY: { /* If configured, apply user specified DUID */ const DUID *duid = link_get_duid(link); - r = sd_dhcp_client_set_duid(link->dhcp_client, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); + if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0) + r = sd_dhcp_client_set_duid_llt(link->dhcp_client, + duid->llt_time); + else + r = sd_dhcp_client_set_duid(link->dhcp_client, + duid->type, + duid->raw_data_len > 0 ? duid->raw_data : NULL, + duid->raw_data_len); if (r < 0) return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m"); break; diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index aa400bc35b..fa6e18cd2c 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -495,10 +495,13 @@ int dhcp6_configure(Link *link) { return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set IAID: %m"); duid = link_get_duid(link); - r = sd_dhcp6_client_set_duid(client, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); + if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0) + r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time); + else + r = sd_dhcp6_client_set_duid(client, + duid->type, + duid->raw_data_len > 0 ? duid->raw_data : NULL, + duid->raw_data_len); if (r < 0) return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set DUID: %m"); diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf index 54161446bb..cc88fc0add 100644 --- a/src/network/networkd-gperf.gperf +++ b/src/network/networkd-gperf.gperf @@ -18,5 +18,5 @@ struct ConfigPerfItem; %struct-type %includes %% -DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Manager, duid.type) +DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Manager, duid) DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, duid) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 6ad5257f79..357231152e 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -130,7 +130,7 @@ DHCP.RequestBroadcast, config_parse_bool, DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier) DHCP.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class) -DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid.type) +DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid) DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid) DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) DHCP.RouteTable, config_parse_dhcp_route_table, 0, 0 diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 0cd1c75f14..484eca6a95 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -70,6 +70,7 @@ typedef struct DUID { uint8_t raw_data_len; uint8_t raw_data[MAX_DUID_LEN]; + usec_t llt_time; } DUID; typedef enum RADVPrefixDelegation { diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c index fc1646f4bf..d05680d7e1 100644 --- a/src/network/test-networkd-conf.c +++ b/src/network/test-networkd-conf.c @@ -11,23 +11,30 @@ #include "networkd-conf.h" #include "networkd-network.h" -static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected) { - DUIDType actual = 0; +static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected, usec_t expected_time) { + DUID actual = {}; int r; r = config_parse_duid_type("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL); - log_info_errno(r, "\"%s\" → %d (%m)", rvalue, actual); + log_info_errno(r, "\"%s\" → %d (%m)", rvalue, actual.type); assert_se(r == ret); - assert_se(expected == actual); + assert_se(expected == actual.type); + if (expected == DUID_TYPE_LLT) + assert_se(expected_time == actual.llt_time); } static void test_config_parse_duid_type(void) { - test_config_parse_duid_type_one("", 0, 0); - test_config_parse_duid_type_one("link-layer-time", 0, DUID_TYPE_LLT); - test_config_parse_duid_type_one("vendor", 0, DUID_TYPE_EN); - test_config_parse_duid_type_one("link-layer", 0, DUID_TYPE_LL); - test_config_parse_duid_type_one("uuid", 0, DUID_TYPE_UUID); - test_config_parse_duid_type_one("foo", 0, 0); + test_config_parse_duid_type_one("", 0, 0, 0); + test_config_parse_duid_type_one("link-layer-time", 0, DUID_TYPE_LLT, 0); + test_config_parse_duid_type_one("link-layer-time:2000-01-01 00:00:00 UTC", 0, DUID_TYPE_LLT, (usec_t) 946684800000000); + test_config_parse_duid_type_one("vendor", 0, DUID_TYPE_EN, 0); + test_config_parse_duid_type_one("vendor:2000-01-01 00:00:00 UTC", 0, 0, 0); + test_config_parse_duid_type_one("link-layer", 0, DUID_TYPE_LL, 0); + test_config_parse_duid_type_one("link-layer:2000-01-01 00:00:00 UTC", 0, 0, 0); + test_config_parse_duid_type_one("uuid", 0, DUID_TYPE_UUID, 0); + test_config_parse_duid_type_one("uuid:2000-01-01 00:00:00 UTC", 0, 0, 0); + test_config_parse_duid_type_one("foo", 0, 0, 0); + test_config_parse_duid_type_one("foo:2000-01-01 00:00:00 UTC", 0, 0, 0); } static void test_config_parse_duid_rawdata_one(const char *rvalue, int ret, const DUID* expected) { |