]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp: use MAC address when DUIDType=link-layer-time or link-layer but DUIDRawData...
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 7 Aug 2018 04:35:58 +0000 (13:35 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 8 Aug 2018 01:15:00 +0000 (10:15 +0900)
src/libsystemd-network/dhcp-identifier.c
src/libsystemd-network/dhcp-identifier.h
src/libsystemd-network/sd-dhcp-client.c
src/libsystemd-network/sd-dhcp6-client.c

index 4b7e7ee0ab2861c7cea3263e0ff2a69a44e75adb..a8ed98f29a9609529fa41483dfae1426b80649c6 100644 (file)
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <linux/if_infiniband.h>
+
 #include "libudev.h"
 #include "sd-id128.h"
 
@@ -14,6 +16,7 @@
 #define SYSTEMD_PEN    43793
 #define HASH_KEY       SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
 #define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03)
+#define USEC_2000       ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */
 
 int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
         struct duid d;
@@ -46,6 +49,56 @@ int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
         return 0;
 }
 
+int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) {
+        uint16_t time_from_2000y;
+
+        assert(duid);
+        assert(len);
+        assert(addr);
+
+        if (arp_type == ARPHRD_ETHER)
+                assert_return(addr_len == ETH_ALEN, -EINVAL);
+        else if (arp_type == ARPHRD_INFINIBAND)
+                assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+        else
+                return -EINVAL;
+
+        if (t < USEC_2000)
+                time_from_2000y = 0;
+        else
+                time_from_2000y = (uint16_t) (((t - USEC_2000) / USEC_PER_SEC) & 0xffffffff);
+
+        unaligned_write_be16(&duid->type, DUID_TYPE_LLT);
+        unaligned_write_be16(&duid->llt.htype, arp_type);
+        unaligned_write_be32(&duid->llt.time, time_from_2000y);
+        memcpy(duid->llt.haddr, addr, addr_len);
+
+        *len = sizeof(duid->type) + sizeof(duid->llt.htype) + sizeof(duid->llt.time) + addr_len;
+
+        return 0;
+}
+
+int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) {
+        assert(duid);
+        assert(len);
+        assert(addr);
+
+        if (arp_type == ARPHRD_ETHER)
+                assert_return(addr_len == ETH_ALEN, -EINVAL);
+        else if (arp_type == ARPHRD_INFINIBAND)
+                assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+        else
+                return -EINVAL;
+
+        unaligned_write_be16(&duid->type, DUID_TYPE_LL);
+        unaligned_write_be16(&duid->ll.htype, arp_type);
+        memcpy(duid->ll.haddr, addr, addr_len);
+
+        *len = sizeof(duid->type) + sizeof(duid->ll.htype) + addr_len;
+
+        return 0;
+}
+
 int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
         sd_id128_t machine_id;
         uint64_t hash;
index cebfa8f4a838fd19c3411550a0fd1af636a69a3d..64315d3a3bd6f0348d21cfcf45a9bcf221ef6c72 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "macro.h"
 #include "sparse-endian.h"
+#include "time-util.h"
 #include "unaligned.h"
 
 typedef enum DUIDType {
@@ -52,6 +53,8 @@ struct duid {
 } _packed_;
 
 int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len);
+int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
+int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
 int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
 int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len);
 int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);
index 6f541f657740f686e3bd18f29bb92547edcea1ce..62c57c8c9fe2f3b6ce41a84b79f4ffa80441e6d0 100644 (file)
@@ -383,18 +383,34 @@ static int dhcp_client_set_iaid_duid(
                 len = sizeof(client->client_id.ns.duid.type) + duid_len;
         } else
                 switch (duid_type) {
+                case DUID_TYPE_LLT:
+                        if (!client->mac_addr || client->mac_addr_len == 0)
+                                return -EOPNOTSUPP;
+
+                        r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, 0, client->mac_addr, client->mac_addr_len, client->arp_type, &len);
+                        if (r < 0)
+                                return r;
+                        break;
                 case DUID_TYPE_EN:
                         r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
                         if (r < 0)
                                 return r;
                         break;
+                case DUID_TYPE_LL:
+                        if (!client->mac_addr || client->mac_addr_len == 0)
+                                return -EOPNOTSUPP;
+
+                        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;
+                        break;
                 case DUID_TYPE_UUID:
                         r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len);
                         if (r < 0)
                                 return r;
                         break;
                 default:
-                        return -EOPNOTSUPP;
+                        return -EINVAL;
                 }
 
         client->client_id_len = sizeof(client->client_id.type) + len +
index 31382b5431125e85b9532688d452985eafc89e94..d4831361bf7eb9867a2bae5789311903fa4e631b 100644 (file)
@@ -203,18 +203,34 @@ int sd_dhcp6_client_set_duid(
                 client->duid_len = sizeof(client->duid.type) + duid_len;
         } else
                 switch (duid_type) {
+                case DUID_TYPE_LLT:
+                        if (!client->mac_addr || client->mac_addr_len == 0)
+                                return -EOPNOTSUPP;
+
+                        r = dhcp_identifier_set_duid_llt(&client->duid, 0, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len);
+                        if (r < 0)
+                                return r;
+                        break;
                 case DUID_TYPE_EN:
                         r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
                         if (r < 0)
                                 return r;
                         break;
+                case DUID_TYPE_LL:
+                        if (!client->mac_addr || client->mac_addr_len == 0)
+                                return -EOPNOTSUPP;
+
+                        r = dhcp_identifier_set_duid_ll(&client->duid, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len);
+                        if (r < 0)
+                                return r;
+                        break;
                 case DUID_TYPE_UUID:
                         r = dhcp_identifier_set_duid_uuid(&client->duid, &client->duid_len);
                         if (r < 0)
                                 return r;
                         break;
                 default:
-                        return -EOPNOTSUPP;
+                        return -EINVAL;
                 }
 
         return 0;