udev-builtin-net_id.c revision 137661d87525a3c339afd2804e577532d58d3fbc
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering This file is part of systemd.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Copyright 2012 Kay Sievers <kay@vrfy.org>
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering (at your option) any later version.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering systemd is distributed in the hope that it will be useful, but
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Lesser General Public License for more details.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * predictable network interface device names based on:
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * - firmware/bios-provided index numbers for on-board devices
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell * - firmware-provided pci-express hotplug slot index number
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * - physical/geographical location of the hardware
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering * - the interface's MAC address
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * two character prefixes based on the type of interface:
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering * en -- ethernet
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * type of names:
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * o<index> -- on-board device index number
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * s<slot>[f<function>] -- hotplug slot index number
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen * x<MAC> -- MAC address
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering * p<bus>s<slot>[f<function>] -- PCI geographical location
d18d46ecea80a7f07415edb9264af6a254fd70bbZbigniew Jędrzejewski-Szmek * All multi-function devices will carry the [f<function>] number in the
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * device name, including the function 0 device.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * ID_NET_NAME_ONBOARD=eno1
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * ID_NET_NAME_SLOT=ens1
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * ID_NET_NAME_SLOT=ens2f0
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * ID_NET_NAME_SLOT=ens2f1
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * ID_NET_NAME_MAC=enxf0def180d479
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * ID_NET_NAME_PATH=enp0s25
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * ID_NET_NAME_PATH=enp19s3f0
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * ID_NET_NAME_PATH=enp19s3f1
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering/* retrieve on-board index number and label from firmware */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int dev_pci_onboard(struct udev_device *dev, struct udev_device *parent, const char *prefix, bool test) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* ACPI _DSM -- device specific method for naming a PCI or PCI Express device */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering index = udev_device_get_sysattr_value(parent, "acpi_index");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* SMBIOS type 41 -- Onboard Devices Extended Information */
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek index = udev_device_get_sysattr_value(parent, "index");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering snprintf(s, sizeof(s), "%so%d", prefix, idx);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering err = udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", s);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek label = udev_device_get_sysattr_value(parent, "label");
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek err = udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", label);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering/* read the 256 bytes PCI configuration space to check the multi-function bit */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic bool is_pci_singlefunction(struct udev_device *dev) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering snprintf(filename, sizeof(filename), "%s/config", udev_device_get_syspath(dev));
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (fread(&config, sizeof(config), 1, f) != 1)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* bit 0-6 header type, bit 7 multi/single function device */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if ((config[PCI_HEADER_TYPE] & 0x80) == 0)
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmekstatic int dev_pci_slot(struct udev_device *dev, struct udev_device *parent, const char *prefix, bool test) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek struct udev *udev = udev_device_get_udev(dev);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* compose a name based on the raw kernel's PCI bus, slot numbers */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (sscanf(udev_device_get_sysname(parent), "0000:%x:%x.%d", &bus, &slot, &func) != 3)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (func == 0 && is_pci_singlefunction(parent))
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering snprintf(str, sizeof(str), "%sp%ds%d", prefix, bus, slot);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering snprintf(str, sizeof(str), "%sp%ds%df%d", prefix, bus, slot, func);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering err = udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek /* ACPI _SUN -- slot user number */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering pci = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering snprintf(slots, sizeof(slots), "%s/slots", udev_device_get_syspath(pci));
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering snprintf(str, sizeof(str), "%s/%s/address", slots, dent->d_name);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (read_one_line_file(str, &address) >= 0) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* match slot address with device by stripping the function */
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden if (strncmp(address, udev_device_get_sysname(parent), strlen(address)) == 0)
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden if (func == 0 && is_pci_singlefunction(parent))
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering snprintf(str, sizeof(str), "%ss%d", prefix, hotplug_slot);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering snprintf(str, sizeof(str), "%ss%df%d", prefix, hotplug_slot, func);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering err = udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int dev_pci(struct udev_device *dev, const char *prefix, bool test) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* skip other buses than direct PCI parents */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (!parent || !streq("pci", udev_device_get_subsystem(parent)))
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek dev_pci_slot(dev, parent, prefix, test);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmekstatic int dev_mac(struct udev_device *dev, const char *prefix, bool test) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* check for NET_ADDR_PERM, skip random MAC addresses */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering s = udev_device_get_sysattr_value(dev, "addr_assign_type");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering s = udev_device_get_sysattr_value(dev, "address");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (sscanf(s, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* skip empty MAC addresses */
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering * IEEE Organizationally Unique Identifier vendor string
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering * skip commonly misused 00:00:00 (Xerox) prefix
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering snprintf(str, sizeof(str), "OUI:%02X%02X%02X", a1, a2, a3);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering udev_builtin_hwdb_lookup(dev, str, test);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering snprintf(str, sizeof(str), "%sx%02x%02x%02x%02x%02x%02x", prefix, a1, a2, a3, a4, a5, a6);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool test) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *s;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering unsigned int i;
d18d46ecea80a7f07415edb9264af6a254fd70bbZbigniew Jędrzejewski-Szmek /* handle only ARPHRD_ETHER devices */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering s = udev_device_get_sysattr_value(dev, "type");
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmekconst struct udev_builtin udev_builtin_net_id = {
874bc134ac6504c45e94174e37af13ff21a6bfe2Zbigniew Jędrzejewski-Szmek .help = "network device properties",