cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen/***
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen This file is part of systemd.
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen Copyright (C) 2015 Tom Gundersen <teg@jklmen>
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen systemd is free software; you can redistribute it and/or modify it
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen under the terms of the GNU Lesser General Public License as published by
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen (at your option) any later version.
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen systemd is distributed in the hope that it will be useful, but
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen Lesser General Public License for more details.
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen You should have received a copy of the GNU Lesser General Public License
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen***/
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
b4bbcaa9c44260e88402cb8f9a5fb8ac7f35e123Thomas Hindoe Paaboel Andersen#include "libudev.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "sd-id128.h"
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen#include "dhcp-identifier.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "dhcp6-protocol.h"
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen#include "network-internal.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "siphash24.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "sparse-endian.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "udev-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "virt.h"
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen#define SYSTEMD_PEN 43793
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersenint dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen sd_id128_t machine_id;
dbe81cbd2a93088236a2e4e41eeb33378940f7b9Martin Pitt uint64_t hash;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen int r;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen assert(duid);
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen assert(len);
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen r = sd_id128_get_machine(&machine_id);
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen if (r < 0)
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen return r;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
9ee18af3a036074c4021c82ae2e67f5ccaa9ea9dTom Gundersen unaligned_write_be16(&duid->type, DHCP6_DUID_EN);
9ee18af3a036074c4021c82ae2e67f5ccaa9ea9dTom Gundersen unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
9ee18af3a036074c4021c82ae2e67f5ccaa9ea9dTom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen *len = sizeof(duid->type) + sizeof(duid->en);
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen /* a bit of snake-oil perhaps, but no need to expose the machine-id
dbe81cbd2a93088236a2e4e41eeb33378940f7b9Martin Pitt directly; duid->en.id might not be aligned, so we need to copy */
933f9caeeb2b3c1b951d330e04beb04226e5a890Daniel Mack hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes));
dbe81cbd2a93088236a2e4e41eeb33378940f7b9Martin Pitt memcpy(duid->en.id, &hash, sizeof(duid->en.id));
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen return 0;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen}
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
9ee18af3a036074c4021c82ae2e67f5ccaa9ea9dTom Gundersenint dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen /* name is a pointer to memory in the udev_device struct, so must
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen have the same scope */
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen _cleanup_udev_device_unref_ struct udev_device *device = NULL;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen const char *name = NULL;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen uint64_t id;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
75f86906c52735c98dc0aa7e24b773edb42ee814Lennart Poettering if (detect_container() <= 0) {
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen /* not in a container, udev will be around */
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen _cleanup_udev_unref_ struct udev *udev;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen char ifindex_str[2 + DECIMAL_STR_MAX(int)];
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen udev = udev_new();
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen if (!udev)
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen return -ENOMEM;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen sprintf(ifindex_str, "n%d", ifindex);
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen device = udev_device_new_from_device_id(udev, ifindex_str);
40862866417265ac8c20422cb44f14a8f141ce0dTom Gundersen if (device) {
40862866417265ac8c20422cb44f14a8f141ce0dTom Gundersen if (udev_device_get_is_initialized(device) <= 0)
40862866417265ac8c20422cb44f14a8f141ce0dTom Gundersen /* not yet ready */
40862866417265ac8c20422cb44f14a8f141ce0dTom Gundersen return -EBUSY;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
40862866417265ac8c20422cb44f14a8f141ce0dTom Gundersen name = net_get_name(device);
40862866417265ac8c20422cb44f14a8f141ce0dTom Gundersen }
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen }
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen if (name)
933f9caeeb2b3c1b951d330e04beb04226e5a890Daniel Mack id = siphash24(name, strlen(name), HASH_KEY.bytes);
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen else
e2acdb6b0f68d9b4152708a9f21bf9e11f8b9e7eTorstein Husebø /* fall back to MAC address if no predictable name available */
933f9caeeb2b3c1b951d330e04beb04226e5a890Daniel Mack id = siphash24(mac, mac_len, HASH_KEY.bytes);
933f9caeeb2b3c1b951d330e04beb04226e5a890Daniel Mack
933f9caeeb2b3c1b951d330e04beb04226e5a890Daniel Mack id = htole64(id);
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen /* fold into 32 bits */
9ee18af3a036074c4021c82ae2e67f5ccaa9ea9dTom Gundersen unaligned_write_be32(_id, (id & 0xffffffff) ^ (id >> 32));
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen return 0;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen}