]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/dhcp-identifier.c
network: replace udev_device by sd_device
[thirdparty/systemd.git] / src / libsystemd-network / dhcp-identifier.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
cfb5b380 2
51517f9e 3#include "sd-device.h"
07630cea 4#include "sd-id128.h"
cfb5b380 5
cfb5b380 6#include "dhcp-identifier.h"
07630cea 7#include "dhcp6-protocol.h"
cfb5b380 8#include "network-internal.h"
07630cea
LP
9#include "siphash24.h"
10#include "sparse-endian.h"
07630cea 11#include "virt.h"
cfb5b380
TG
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
3b6a4e97
ZJS
16int 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
cfb5b380
TG
47int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
48 sd_id128_t machine_id;
dbe81cbd 49 uint64_t hash;
cfb5b380
TG
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
413708d1 59 unaligned_write_be16(&duid->type, DUID_TYPE_EN);
9ee18af3
TG
60 unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
61
cfb5b380
TG
62 *len = sizeof(duid->type) + sizeof(duid->en);
63
64 /* a bit of snake-oil perhaps, but no need to expose the machine-id
dbe81cbd 65 directly; duid->en.id might not be aligned, so we need to copy */
933f9cae 66 hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes));
dbe81cbd 67 memcpy(duid->en.id, &hash, sizeof(duid->en.id));
cfb5b380
TG
68
69 return 0;
70}
71
9ee18af3 72int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
51517f9e
YW
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;
cfb5b380
TG
76 const char *name = NULL;
77 uint64_t id;
78
75f86906 79 if (detect_container() <= 0) {
cfb5b380 80 /* not in a container, udev will be around */
cfb5b380 81 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
51517f9e 82 int initialized, r;
cfb5b380
TG
83
84 sprintf(ifindex_str, "n%d", ifindex);
51517f9e
YW
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)
40862866
TG
90 /* not yet ready */
91 return -EBUSY;
cfb5b380 92
40862866
TG
93 name = net_get_name(device);
94 }
cfb5b380
TG
95 }
96
97 if (name)
933f9cae 98 id = siphash24(name, strlen(name), HASH_KEY.bytes);
cfb5b380 99 else
e2acdb6b 100 /* fall back to MAC address if no predictable name available */
933f9cae
DM
101 id = siphash24(mac, mac_len, HASH_KEY.bytes);
102
103 id = htole64(id);
cfb5b380
TG
104
105 /* fold into 32 bits */
9ee18af3 106 unaligned_write_be32(_id, (id & 0xffffffff) ^ (id >> 32));
cfb5b380
TG
107
108 return 0;
109}