]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: accept additional time-value after ':' when DUIDType=link-layer-time
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 7 Aug 2018 04:57:48 +0000 (13:57 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 8 Aug 2018 01:15:00 +0000 (10:15 +0900)
src/network/networkd-conf.c
src/network/networkd-dhcp4.c
src/network/networkd-dhcp6.c
src/network/networkd-gperf.gperf
src/network/networkd-network-gperf.gperf
src/network/networkd-network.h
src/network/test-networkd-conf.c

index 05bbc0b3e9230fa2306548566b8f2f80b5cb235a..334ffc3c5710f23c13f3ad3247651093c73c9c6b 100644 (file)
@@ -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,
index a3bdf4f40a0d0f36e124de9c945e7f2fc93cc3c5..18867d9401df2b8a7847c393e3bc171ecea97a93 100644 (file)
@@ -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;
index aa400bc35bf008de047faab6eb844d9b463be240..fa6e18cd2c49553fa29bd2a14d7d6e4783e8aed9 100644 (file)
@@ -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");
 
index 54161446bba942bd58fe25dd4a4b9cf9a9de26e5..cc88fc0addc96a952ef7ab9baa45d8ae34c32f05 100644 (file)
@@ -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)
index 6ad5257f79292f57b305b6a4e08cb75af469c5fc..357231152e0649c4f02fa4fc3144921a781d0fab 100644 (file)
@@ -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
index 0cd1c75f14f7e898d398ad1dfa41a5929a1d9c3f..484eca6a95c3bddd3acafbb9074ec9bb5881941b 100644 (file)
@@ -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 {
index fc1646f4bf5b82268efa61896430bc7ed6d7f6d5..d05680d7e11fad2cacb7a909e1a168481b5203c5 100644 (file)
 #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) {