]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/dhcp-identifier.c
network: replace udev_device by sd_device
[thirdparty/systemd.git] / src / libsystemd-network / dhcp-identifier.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include "sd-device.h"
4 #include "sd-id128.h"
5
6 #include "dhcp-identifier.h"
7 #include "dhcp6-protocol.h"
8 #include "network-internal.h"
9 #include "siphash24.h"
10 #include "sparse-endian.h"
11 #include "virt.h"
12
13 #define SYSTEMD_PEN 43793
14 #define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
15
16 int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
17 struct duid d;
18
19 assert_cc(sizeof(d.raw) >= MAX_DUID_LEN);
20 if (duid_len > MAX_DUID_LEN)
21 return -EINVAL;
22
23 switch (duid_type) {
24 case DUID_TYPE_LLT:
25 if (duid_len <= sizeof(d.llt))
26 return -EINVAL;
27 break;
28 case DUID_TYPE_EN:
29 if (duid_len != sizeof(d.en))
30 return -EINVAL;
31 break;
32 case DUID_TYPE_LL:
33 if (duid_len <= sizeof(d.ll))
34 return -EINVAL;
35 break;
36 case DUID_TYPE_UUID:
37 if (duid_len != sizeof(d.uuid))
38 return -EINVAL;
39 break;
40 default:
41 /* accept unknown type in order to be forward compatible */
42 break;
43 }
44 return 0;
45 }
46
47 int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
48 sd_id128_t machine_id;
49 uint64_t hash;
50 int r;
51
52 assert(duid);
53 assert(len);
54
55 r = sd_id128_get_machine(&machine_id);
56 if (r < 0)
57 return r;
58
59 unaligned_write_be16(&duid->type, DUID_TYPE_EN);
60 unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
61
62 *len = sizeof(duid->type) + sizeof(duid->en);
63
64 /* a bit of snake-oil perhaps, but no need to expose the machine-id
65 directly; duid->en.id might not be aligned, so we need to copy */
66 hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes));
67 memcpy(duid->en.id, &hash, sizeof(duid->en.id));
68
69 return 0;
70 }
71
72 int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
73 /* name is a pointer to memory in the sd_device struct, so must
74 * have the same scope */
75 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
76 const char *name = NULL;
77 uint64_t id;
78
79 if (detect_container() <= 0) {
80 /* not in a container, udev will be around */
81 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
82 int initialized, r;
83
84 sprintf(ifindex_str, "n%d", ifindex);
85 if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) {
86 r = sd_device_get_is_initialized(device, &initialized);
87 if (r < 0)
88 return r;
89 if (!initialized)
90 /* not yet ready */
91 return -EBUSY;
92
93 name = net_get_name(device);
94 }
95 }
96
97 if (name)
98 id = siphash24(name, strlen(name), HASH_KEY.bytes);
99 else
100 /* fall back to MAC address if no predictable name available */
101 id = siphash24(mac, mac_len, HASH_KEY.bytes);
102
103 id = htole64(id);
104
105 /* fold into 32 bits */
106 unaligned_write_be32(_id, (id & 0xffffffff) ^ (id >> 32));
107
108 return 0;
109 }