/*** This file is part of systemd. Copyright 2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* * eno -- ethernet on-board * ID_NET_NAME_FIRMWARE=eno1 * * enpsf -- physical location/path * ID_NET_NAME_PATH=enp19s0f0 * * enm -- MAC address * ID_NET_NAME_MAC=enxf0def180d479 */ #include #include #include #include #include #include #include "udev.h" static int dev_pci(struct udev_device *dev, const char *prefix, bool test) { struct udev_device *d; unsigned int bus; unsigned int slot; unsigned int func; const char *index; int err; /* skip other buses than direct PCI parents */ d = udev_device_get_parent(dev); if (!d || !streq("pci", udev_device_get_subsystem(d))) return -ENOENT; /* ACPI _SUN -- slot user number */ index = udev_device_get_sysattr_value(d, "acpi_index"); /* SMBIOS type 41 -- Onboard Devices Extended Information */ if (!index) index = udev_device_get_sysattr_value(d, "index"); if (index) { unsigned int idx; idx = strtoul(index, NULL, 0); if (idx > 0) { const char *label; char s[16]; snprintf(s, sizeof(s), "%so%d", prefix, idx); udev_builtin_add_property(dev, test, "ID_NET_NAME_FIRMWARE", s); label = udev_device_get_sysattr_value(d, "label"); if (label) udev_builtin_add_property(dev, test, "ID_NET_LABEL_FIRMWARE", label); } } /* compose a name based on the PCI bus location */ if (sscanf(udev_device_get_sysname(d), "0000:%x:%x.%d", &bus, &slot, &func) == 3) { char str[16]; snprintf(str, sizeof(str), "%sp%ds%df%d", prefix, bus, slot, func); err = udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); if (err < 0) return err; } return 0; } static int dev_mac(struct udev_device *dev, const char *prefix, bool test) { const char *s; unsigned int i; unsigned int a1, a2, a3, a4, a5, a6; char str[16]; int err; /* check for NET_ADDR_PERM, skip random MAC addresses */ s = udev_device_get_sysattr_value(dev, "addr_assign_type"); if (!s) return EXIT_FAILURE; i = strtoul(s, NULL, 0); if (i != 0) return 0; s = udev_device_get_sysattr_value(dev, "address"); if (!s) return -ENOENT; if (sscanf(s, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) return -EINVAL; /* skip empty MAC addresses */ if (a1 + a2 + a3 + a4 + a5 + a6 == 0) return -EINVAL; /* add IEEE Organizationally Unique Identifier */ snprintf(str, sizeof(str), "OUI:%X%X%X", a1, a2, a3); udev_builtin_hwdb_lookup(dev, str, test); snprintf(str, sizeof(str), "%sx%x%x%x%x%x%x", prefix, a1, a2, a3, a4, a5, a6); err = udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str); if (err < 0) return err; return 0; } static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool test) { const char *s; unsigned int i; const char *devtype; const char *prefix = "en"; /* handle only ARPHRD_ETHER devices */ s = udev_device_get_sysattr_value(dev, "type"); if (!s) return EXIT_FAILURE; i = strtoul(s, NULL, 0); if (i != 1) return 0; devtype = udev_device_get_devtype(dev); if (devtype) { if (streq("wlan", devtype)) prefix = "wl"; else if (streq("wwan", devtype)) prefix = "ww"; } dev_pci(dev, prefix, test); dev_mac(dev, prefix, test); return EXIT_SUCCESS; } const struct udev_builtin udev_builtin_net_id = { .name = "net_id", .cmd = builtin_net_id, .help = "network device properties", };