udev-builtin-net_id.c revision 3b64e4d4f40baac56148c7d333d6a0053358ec7a
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering/***
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering This file is part of systemd.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering Copyright 2012 Kay Sievers <kay@vrfy.org>
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering systemd is free software; you can redistribute it and/or modify it
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering under the terms of the GNU Lesser General Public License as published by
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering (at your option) any later version.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering systemd is distributed in the hope that it will be useful, but
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering Lesser General Public License for more details.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering You should have received a copy of the GNU Lesser General Public License
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering***/
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering/*
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * Predictable network interface device names based on:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * - firmware/bios-provided index numbers for on-board devices
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * - firmware-provided pci-express hotplug slot index number
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * - physical/geographical location of the hardware
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * - the interface's MAC address
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * Two character prefixes based on the type of interface:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * en -- ethernet
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * sl -- serial line IP (slip)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * wl -- wlan
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ww -- wwan
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * Type of names:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * b<number> -- BCMA bus core number
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ccw<name> -- CCW bus group name
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * o<index>[d<dev_port>] -- on-board device index number
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * s<slot>[f<function>][d<dev_port>] -- hotplug slot index number
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * x<MAC> -- MAC address
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * [P<domain>]p<bus>s<slot>[f<function>][d<dev_port>]
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * -- PCI geographical location
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * -- USB port number chain
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * All multi-function PCI devices will carry the [f<function>] number in the
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * device name, including the function 0 device.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * When using PCI geography, The PCI domain is only prepended when it is not 0.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * For USB devices the full chain of port numbers of hubs is composed. If the
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * name gets longer than the maximum number of 15 characters, the name is not
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * exported.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * The usual USB configuration == 1 and interface == 0 values are suppressed.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * PCI ethernet card with firmware index "1":
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_ONBOARD=eno1
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * PCI ethernet card in hotplug slot with firmware index number:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_MAC=enx000000000466
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_PATH=enp5s0
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_SLOT=ens1
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * PCI ethernet multi-function card with 2 ports:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/enp2s0f0
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_MAC=enx78e7d1ea46da
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_PATH=enp2s0f0
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.1/net/enp2s0f1
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_MAC=enx78e7d1ea46dc
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_PATH=enp2s0f1
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * PCI wlan card:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_MAC=wlx0024d7e31130
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_PATH=wlp3s0
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * USB built-in 3G modem:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_MAC=wwx028037ec0200
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_PATH=wwp0s29u1u4i6
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * USB Android phone:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_MAC=enxd626b3450fb5
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * ID_NET_NAME_PATH=enp0s29u1u2
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include <stdio.h>
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include <stdlib.h>
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include <stdarg.h>
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include <unistd.h>
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include <fcntl.h>
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include <string.h>
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include <errno.h>
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include <net/if.h>
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include <net/if_arp.h>
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include <linux/pci_regs.h>
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include "udev.h"
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include "fileio.h"
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringenum netname_type{
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering NET_UNDEF,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering NET_PCI,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering NET_USB,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering NET_BCMA,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering NET_VIRTIO,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering NET_CCWGROUP,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering};
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstruct netnames {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering enum netname_type type;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering uint8_t mac[6];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering bool mac_valid;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering struct udev_device *pcidev;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char pci_slot[IFNAMSIZ];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char pci_path[IFNAMSIZ];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char pci_onboard[IFNAMSIZ];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *pci_onboard_label;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char usb_ports[IFNAMSIZ];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char bcma_core[IFNAMSIZ];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char ccw_group[IFNAMSIZ];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering};
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering/* retrieve on-board index number and label from firmware */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering unsigned dev_port = 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering size_t l;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *s;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *attr;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering int idx;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* ACPI _DSM -- device specific method for naming a PCI or PCI Express device */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering attr = udev_device_get_sysattr_value(names->pcidev, "acpi_index");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* SMBIOS type 41 -- Onboard Devices Extended Information */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!attr)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering attr = udev_device_get_sysattr_value(names->pcidev, "index");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!attr)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering idx = strtoul(attr, NULL, 0);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (idx <= 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* kernel provided port index for multiple ports on a single PCI function */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering attr = udev_device_get_sysattr_value(dev, "dev_port");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (attr)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering dev_port = strtol(attr, NULL, 10);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = names->pci_onboard;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = sizeof(names->pci_onboard);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyf(&s, l, "o%d", idx);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (dev_port > 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyf(&s, l, "d%d", dev_port);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (l == 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->pci_onboard[0] = '\0';
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->pci_onboard_label = udev_device_get_sysattr_value(names->pcidev, "label");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering/* read the 256 bytes PCI configuration space to check the multi-function bit */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic bool is_pci_multifunction(struct udev_device *dev) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering _cleanup_close_ int fd = -1;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *filename;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering uint8_t config[64];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering filename = strjoina(udev_device_get_syspath(dev), "/config");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering fd = open(filename, O_RDONLY | O_CLOEXEC);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (fd < 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return false;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (read(fd, &config, sizeof(config)) != sizeof(config))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return false;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* bit 0-6 header type, bit 7 multi/single function device */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if ((config[PCI_HEADER_TYPE] & 0x80) != 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return true;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return false;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering struct udev *udev = udev_device_get_udev(names->pcidev);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering unsigned domain, bus, slot, func, dev_port = 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering size_t l;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *s;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *attr;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering struct udev_device *pci = NULL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char slots[256], str[256];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering _cleanup_closedir_ DIR *dir = NULL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering struct dirent *dent;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering int hotplug_slot = 0, err = 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (sscanf(udev_device_get_sysname(names->pcidev), "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* kernel provided port index for multiple ports on a single PCI function */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering attr = udev_device_get_sysattr_value(dev, "dev_port");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (attr)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering dev_port = strtol(attr, NULL, 10);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* compose a name based on the raw kernel's PCI bus, slot numbers */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = names->pci_path;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = sizeof(names->pci_path);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (domain > 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyf(&s, l, "P%u", domain);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyf(&s, l, "p%us%u", bus, slot);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (func > 0 || is_pci_multifunction(names->pcidev))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyf(&s, l, "f%u", func);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (dev_port > 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyf(&s, l, "d%u", dev_port);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (l == 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->pci_path[0] = '\0';
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* ACPI _SUN -- slot user number */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering pci = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!pci) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering err = -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering goto out;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering snprintf(slots, sizeof(slots), "%s/slots", udev_device_get_syspath(pci));
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering dir = opendir(slots);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!dir) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering err = -errno;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering goto out;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering int i;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *rest;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *address;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (dent->d_name[0] == '.')
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering continue;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering i = strtol(dent->d_name, &rest, 10);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (rest[0] != '\0')
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering continue;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (i < 1)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering continue;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering snprintf(str, sizeof(str), "%s/%s/address", slots, dent->d_name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (read_one_line_file(str, &address) >= 0) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* match slot address with device by stripping the function */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (strneq(address, udev_device_get_sysname(names->pcidev), strlen(address)))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering hotplug_slot = i;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering free(address);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (hotplug_slot > 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (hotplug_slot > 0) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = names->pci_slot;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = sizeof(names->pci_slot);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (domain > 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyf(&s, l, "P%d", domain);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyf(&s, l, "s%d", hotplug_slot);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (func > 0 || is_pci_multifunction(names->pcidev))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyf(&s, l, "f%d", func);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (dev_port > 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyf(&s, l, "d%d", dev_port);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (l == 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->pci_slot[0] = '\0';
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringout:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_device_unref(pci);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return err;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic int names_pci(struct udev_device *dev, struct netnames *names) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering struct udev_device *parent;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(dev);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(names);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering parent = udev_device_get_parent(dev);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!parent)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* check if our direct parent is a PCI device with no other bus in-between */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr("pci", udev_device_get_subsystem(parent))) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->type = NET_PCI;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->pcidev = parent;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->pcidev = udev_device_get_parent_with_subsystem_devtype(dev, "pci", NULL);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!names->pcidev)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering dev_pci_onboard(dev, names);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering dev_pci_slot(dev, names);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic int names_usb(struct udev_device *dev, struct netnames *names) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering struct udev_device *usbdev;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char name[256];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *ports;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *config;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *interf;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering size_t l;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *s;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(dev);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(names);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering usbdev = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!usbdev)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* get USB port number chain, configuration, interface */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering strscpy(name, sizeof(name), udev_device_get_sysname(usbdev));
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = strchr(name, '-');
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!s)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering ports = s+1;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = strchr(ports, ':');
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!s)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s[0] = '\0';
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering config = s+1;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = strchr(config, '.');
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!s)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s[0] = '\0';
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering interf = s+1;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* prefix every port number in the chain with "u" */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = ports;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering while ((s = strchr(s, '.')))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s[0] = 'u';
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = names->usb_ports;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyl(&s, sizeof(names->usb_ports), "u", ports, NULL);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* append USB config number, suppress the common config == 1 */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!streq(config, "1"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyl(&s, sizeof(names->usb_ports), "c", config, NULL);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* append USB interface number, suppress the interface == 0 */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!streq(interf, "0"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering l = strpcpyl(&s, sizeof(names->usb_ports), "i", interf, NULL);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (l == 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENAMETOOLONG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->type = NET_USB;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic int names_bcma(struct udev_device *dev, struct netnames *names) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering struct udev_device *bcmadev;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering unsigned int core;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(dev);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(names);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering bcmadev = udev_device_get_parent_with_subsystem_devtype(dev, "bcma", NULL);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!bcmadev)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* bus num:core num */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (sscanf(udev_device_get_sysname(bcmadev), "bcma%*u:%u", &core) != 1)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* suppress the common core == 0 */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (core > 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering snprintf(names->bcma_core, sizeof(names->bcma_core), "b%u", core);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->type = NET_BCMA;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic int names_ccw(struct udev_device *dev, struct netnames *names) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering struct udev_device *cdev;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *bus_id;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering size_t bus_id_len;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering int rc;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(dev);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(names);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* Retrieve the associated CCW device */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering cdev = udev_device_get_parent(dev);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!cdev)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* Network devices are always grouped CCW devices */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!streq_ptr("ccwgroup", udev_device_get_subsystem(cdev)))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* Retrieve bus-ID of the grouped CCW device. The bus-ID uniquely
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * identifies the network device on the Linux on System z channel
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * subsystem. Note that the bus-ID contains lowercase characters.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering bus_id = udev_device_get_sysname(cdev);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!bus_id)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* Check the length of the bus-ID. Rely on that the kernel provides
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * a correct bus-ID; alternatively, improve this check and parse and
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering * verify each bus-ID part...
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering bus_id_len = strlen(bus_id);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!bus_id_len || bus_id_len < 8 || bus_id_len > 9)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* Store the CCW bus-ID for use as network device name */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering rc = snprintf(names->ccw_group, sizeof(names->ccw_group), "ccw%s", bus_id);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (rc >= 0 && rc < (int)sizeof(names->ccw_group))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->type = NET_CCWGROUP;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic int names_mac(struct udev_device *dev, struct netnames *names) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *s;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering unsigned int i;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering unsigned int a1, a2, a3, a4, a5, a6;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* check for NET_ADDR_PERM, skip random MAC addresses */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = udev_device_get_sysattr_value(dev, "addr_assign_type");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!s)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return EXIT_FAILURE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering i = strtoul(s, NULL, 0);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (i != 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = udev_device_get_sysattr_value(dev, "address");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!s)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (sscanf(s, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* skip empty MAC addresses */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (a1 + a2 + a3 + a4 + a5 + a6 == 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->mac[0] = a1;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->mac[1] = a2;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->mac[2] = a3;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->mac[3] = a4;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->mac[4] = a5;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->mac[5] = a6;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->mac_valid = true;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering/* IEEE Organizationally Unique Identifier vendor string */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic int ieee_oui(struct udev_device *dev, struct netnames *names, bool test) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char str[32];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!names->mac_valid)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -ENOENT;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* skip commonly misused 00:00:00 (Xerox) prefix */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (memcmp(names->mac, "\0\0\0", 3) == 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering snprintf(str, sizeof(str), "OUI:%02X%02X%02X%02X%02X%02X",
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->mac[0], names->mac[1], names->mac[2],
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names->mac[3], names->mac[4], names->mac[5]);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool test) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *s;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *p;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering unsigned int i;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *devtype;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *prefix = "en";
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering struct netnames names = {};
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering int err;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* handle only ARPHRD_ETHER and ARPHRD_SLIP devices */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = udev_device_get_sysattr_value(dev, "type");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!s)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return EXIT_FAILURE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering i = strtoul(s, NULL, 0);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering switch (i) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case ARPHRD_ETHER:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering prefix = "en";
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case ARPHRD_SLIP:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering prefix = "sl";
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering default:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* skip stacked devices, like VLANs, ... */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering s = udev_device_get_sysattr_value(dev, "ifindex");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!s)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return EXIT_FAILURE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering p = udev_device_get_sysattr_value(dev, "iflink");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!p)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return EXIT_FAILURE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!streq(s, p))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering devtype = udev_device_get_devtype(dev);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (devtype) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq("wlan", devtype))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering prefix = "wl";
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq("wwan", devtype))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering prefix = "ww";
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering err = names_mac(dev, &names);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (err >= 0 && names.mac_valid) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char str[IFNAMSIZ];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering snprintf(str, sizeof(str), "%sx%02x%02x%02x%02x%02x%02x", prefix,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names.mac[0], names.mac[1], names.mac[2],
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering names.mac[3], names.mac[4], names.mac[5]);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering ieee_oui(dev, &names, test);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* get path names for Linux on System z network devices */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering err = names_ccw(dev, &names);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (err >= 0 && names.type == NET_CCWGROUP) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char str[IFNAMSIZ];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (snprintf(str, sizeof(str), "%s%s", prefix, names.ccw_group) < (int)sizeof(str))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering goto out;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* get PCI based path names, we compose only PCI based paths */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering err = names_pci(dev, &names);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (err < 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering goto out;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* plain PCI device */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (names.type == NET_PCI) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char str[IFNAMSIZ];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (names.pci_onboard[0])
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard) < (int)sizeof(str))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (names.pci_onboard_label)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard_label) < (int)sizeof(str))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (names.pci_path[0])
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_path) < (int)sizeof(str))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (names.pci_slot[0])
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_slot) < (int)sizeof(str))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering goto out;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* USB device */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering err = names_usb(dev, &names);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (err >= 0 && names.type == NET_USB) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char str[IFNAMSIZ];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (names.pci_path[0])
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.usb_ports) < (int)sizeof(str))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (names.pci_slot[0])
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.usb_ports) < (int)sizeof(str))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering goto out;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering /* Broadcom bus */
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering err = names_bcma(dev, &names);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (err >= 0 && names.type == NET_BCMA) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char str[IFNAMSIZ];
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (names.pci_path[0])
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.bcma_core) < (int)sizeof(str))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (names.pci_slot[0])
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.bcma_core) < (int)sizeof(str))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering goto out;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringout:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return EXIT_SUCCESS;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringconst struct udev_builtin udev_builtin_net_id = {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering .name = "net_id",
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering .cmd = builtin_net_id,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering .help = "Network device properties",
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering};
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering