]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/dhcp-identifier.c
util-lib: split our string related calls from util.[ch] into its own file string...
[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
cfb5b380 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;
38 int r;
39
40 assert(duid);
41 assert(len);
42
43 r = sd_id128_get_machine(&machine_id);
44 if (r < 0)
45 return r;
46
9ee18af3
TG
47 unaligned_write_be16(&duid->type, DHCP6_DUID_EN);
48 unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
49
cfb5b380
TG
50 *len = sizeof(duid->type) + sizeof(duid->en);
51
52 /* a bit of snake-oil perhaps, but no need to expose the machine-id
53 directly */
54 siphash24(duid->en.id, &machine_id, sizeof(machine_id), HASH_KEY.bytes);
55
56 return 0;
57}
58
9ee18af3 59int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
cfb5b380
TG
60 /* name is a pointer to memory in the udev_device struct, so must
61 have the same scope */
62 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
63 const char *name = NULL;
64 uint64_t id;
65
75f86906 66 if (detect_container() <= 0) {
cfb5b380
TG
67 /* not in a container, udev will be around */
68 _cleanup_udev_unref_ struct udev *udev;
69 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
70
71 udev = udev_new();
72 if (!udev)
73 return -ENOMEM;
74
75 sprintf(ifindex_str, "n%d", ifindex);
76 device = udev_device_new_from_device_id(udev, ifindex_str);
40862866
TG
77 if (device) {
78 if (udev_device_get_is_initialized(device) <= 0)
79 /* not yet ready */
80 return -EBUSY;
cfb5b380 81
40862866
TG
82 name = net_get_name(device);
83 }
cfb5b380
TG
84 }
85
86 if (name)
87 siphash24((uint8_t*)&id, name, strlen(name), HASH_KEY.bytes);
88 else
e2acdb6b 89 /* fall back to MAC address if no predictable name available */
cfb5b380
TG
90 siphash24((uint8_t*)&id, mac, mac_len, HASH_KEY.bytes);
91
92 /* fold into 32 bits */
9ee18af3 93 unaligned_write_be32(_id, (id & 0xffffffff) ^ (id >> 32));
cfb5b380
TG
94
95 return 0;
96}