]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/dhcp-identifier.c
resolved: expose some properties on the bus
[thirdparty/systemd.git] / src / libsystemd-network / dhcp-identifier.c
CommitLineData
cfb5b380
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright (C) 2015 Tom Gundersen <teg@jklmen>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
b4bbcaa9 22#include "libudev.h"
07630cea 23#include "sd-id128.h"
cfb5b380 24
cfb5b380 25#include "dhcp-identifier.h"
07630cea 26#include "dhcp6-protocol.h"
cfb5b380 27#include "network-internal.h"
07630cea
LP
28#include "siphash24.h"
29#include "sparse-endian.h"
30#include "udev-util.h"
31#include "virt.h"
cfb5b380
TG
32
33#define SYSTEMD_PEN 43793
34#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
35
36int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
37 sd_id128_t machine_id;
dbe81cbd 38 uint64_t hash;
cfb5b380
TG
39 int r;
40
41 assert(duid);
42 assert(len);
43
44 r = sd_id128_get_machine(&machine_id);
45 if (r < 0)
46 return r;
47
9ee18af3
TG
48 unaligned_write_be16(&duid->type, DHCP6_DUID_EN);
49 unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
50
cfb5b380
TG
51 *len = sizeof(duid->type) + sizeof(duid->en);
52
53 /* a bit of snake-oil perhaps, but no need to expose the machine-id
dbe81cbd 54 directly; duid->en.id might not be aligned, so we need to copy */
933f9cae 55 hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes));
dbe81cbd 56 memcpy(duid->en.id, &hash, sizeof(duid->en.id));
cfb5b380
TG
57
58 return 0;
59}
60
9ee18af3 61int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
cfb5b380
TG
62 /* name is a pointer to memory in the udev_device struct, so must
63 have the same scope */
64 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
65 const char *name = NULL;
66 uint64_t id;
67
75f86906 68 if (detect_container() <= 0) {
cfb5b380
TG
69 /* not in a container, udev will be around */
70 _cleanup_udev_unref_ struct udev *udev;
71 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
72
73 udev = udev_new();
74 if (!udev)
75 return -ENOMEM;
76
77 sprintf(ifindex_str, "n%d", ifindex);
78 device = udev_device_new_from_device_id(udev, ifindex_str);
40862866
TG
79 if (device) {
80 if (udev_device_get_is_initialized(device) <= 0)
81 /* not yet ready */
82 return -EBUSY;
cfb5b380 83
40862866
TG
84 name = net_get_name(device);
85 }
cfb5b380
TG
86 }
87
88 if (name)
933f9cae 89 id = siphash24(name, strlen(name), HASH_KEY.bytes);
cfb5b380 90 else
e2acdb6b 91 /* fall back to MAC address if no predictable name available */
933f9cae
DM
92 id = siphash24(mac, mac_len, HASH_KEY.bytes);
93
94 id = htole64(id);
cfb5b380
TG
95
96 /* fold into 32 bits */
9ee18af3 97 unaligned_write_be32(_id, (id & 0xffffffff) ^ (id >> 32));
cfb5b380
TG
98
99 return 0;
100}