udev-builtin-net_id.c revision 971e7fb62548f2c9c4e32684bb13409e6579dc6a
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/***
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering This file is part of systemd.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Copyright 2012 Kay Sievers <kay@vrfy.org>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is free software; you can redistribute it and/or modify it
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering under the terms of the GNU Lesser General Public License as published by
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (at your option) any later version.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is distributed in the hope that it will be useful, but
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Lesser General Public License for more details.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering You should have received a copy of the GNU Lesser General Public License
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering***/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/*
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * Predictable network interface device names based on:
a9cdc94f7ff40f22a3cf9472f612a80730a1b010Dave Reisner * - firmware/bios-provided index numbers for on-board devices
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * - firmware-provided pci-express hotplug slot index number
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * - physical/geographical location of the hardware
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * - the interface's MAC address
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * Two character prefixes based on the type of interface:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * en -- ethernet
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * wl -- wlan
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ww -- wwan
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * Type of names:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * o<index> -- on-board device index number
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * s<slot>[f<function>] -- hotplug slot index number
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * x<MAC> -- MAC address
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * p<bus>s<slot>[f<function>] -- PCI geographical location
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * p<bus>s<slot>[f<function>][u<port>][...][c<config>][i<interface>]
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * -- USB port number chain
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering * All multi-function PCI devices will carry the [f<function>] number in the
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * device name, including the function 0 device.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * For USB devices the full chain of port numbers of hubs is composed. If the
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * name gets longer than the maximum number of 15 characters, the name is not
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * exported.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * The usual USB configuration == 1 and interface == 0 values are suppressed.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * PCI ethernet card with firmware index
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_ONBOARD=eno1
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * PCI ethernet card
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_MAC=enx000000000466
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_PATH=enp5s0
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_SLOT=ens1
1b12a7b5896f94bdf33b3a6661ebabd761ea6adcHarald Hoyer *
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * PCI ethernet card in hotplug slot with firmware index number:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_MAC=enx000000000466
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_PATH=enp5s0
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_SLOT=ens1
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * PCI wlan card:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_MAC=wlx0024d7e31130
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_PATH=wlp3s0
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * USB built-in 3G modem:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_MAC=wwx028037ec0200
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_PATH=wwp0s29u1u4i6
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * USB Android phone:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_MAC=enxd626b3450fb5
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * ID_NET_NAME_PATH=enp0s29u1u2
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <stdio.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <stdlib.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <stdarg.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <unistd.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <string.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <errno.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <net/if.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include <linux/pci_regs.h>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "udev.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringenum netname_type{
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering NET_UNDEF,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering NET_PCI,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering NET_USB,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering};
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstruct netnames {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering enum netname_type type;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering uint8_t mac[6];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering bool mac_valid;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering struct udev_device *pcidev;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char pci_slot[IFNAMSIZ];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char pci_path[IFNAMSIZ];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char pci_onboard[IFNAMSIZ];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *pci_onboard_label;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering struct udev_device *usbdev;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char usb_ports[IFNAMSIZ];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering};
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/* retrieve on-board index number and label from firmware */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *index;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int idx;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* ACPI _DSM -- device specific method for naming a PCI or PCI Express device */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering index = udev_device_get_sysattr_value(names->pcidev, "acpi_index");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* SMBIOS type 41 -- Onboard Devices Extended Information */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!index)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering index = udev_device_get_sysattr_value(names->pcidev, "index");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!index)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOENT;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering idx = strtoul(index, NULL, 0);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (idx <= 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering snprintf(names->pci_onboard, sizeof(names->pci_onboard), "o%d", idx);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->pci_onboard_label = udev_device_get_sysattr_value(names->pcidev, "label");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/* read the 256 bytes PCI configuration space to check the multi-function bit */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic bool is_pci_singlefunction(struct udev_device *dev) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char filename[256];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering FILE *f;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char config[64];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering bool single = false;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering snprintf(filename, sizeof(filename), "%s/config", udev_device_get_syspath(dev));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering f = fopen(filename, "re");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!f)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto out;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (fread(&config, sizeof(config), 1, f) != 1)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto out;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* bit 0-6 header type, bit 7 multi/single function device */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if ((config[PCI_HEADER_TYPE] & 0x80) == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering single = true;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringout:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fclose(f);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return single;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering struct udev *udev = udev_device_get_udev(names->pcidev);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned int bus;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned int slot;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned int func;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering struct udev_device *pci = NULL;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek char slots[256];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering DIR *dir;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering struct dirent *dent;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char str[256];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int hotplug_slot = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int err = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* compose a name based on the raw kernel's PCI bus, slot numbers */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (sscanf(udev_device_get_sysname(names->pcidev), "0000:%x:%x.%d", &bus, &slot, &func) != 3)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOENT;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (func == 0 && is_pci_singlefunction(names->pcidev))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering snprintf(names->pci_path, sizeof(names->pci_path), "p%ds%d", bus, slot);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering snprintf(names->pci_path, sizeof(names->pci_path), "p%ds%df%d", bus, slot, func);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* ACPI _SUN -- slot user number */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering pci = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!pci) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering err = -ENOENT;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto out;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering snprintf(slots, sizeof(slots), "%s/slots", udev_device_get_syspath(pci));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering dir = opendir(slots);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!dir) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering err = -errno;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto out;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int i;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char *rest;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char *address;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (dent->d_name[0] == '.')
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering continue;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering i = strtol(dent->d_name, &rest, 10);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (rest[0] != '\0')
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering continue;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (i < 1)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering continue;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering snprintf(str, sizeof(str), "%s/%s/address", slots, dent->d_name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (read_one_line_file(str, &address) >= 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* match slot address with device by stripping the function */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (strncmp(address, udev_device_get_sysname(names->pcidev), strlen(address)) == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering hotplug_slot = i;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(address);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (hotplug_slot > 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering closedir(dir);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (hotplug_slot > 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (func == 0 && is_pci_singlefunction(names->pcidev))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering snprintf(names->pci_slot, sizeof(names->pci_slot), "s%d", hotplug_slot);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering snprintf(names->pci_slot, sizeof(names->pci_slot), "s%df%d", hotplug_slot, func);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringout:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering udev_device_unref(pci);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return err;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssenstatic int names_pci(struct udev_device *dev, struct netnames *names) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering struct udev_device *parent;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering parent = udev_device_get_parent(dev);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!parent)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOENT;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* check if our direct parent is a PCI device with no other bus in-between */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (streq("pci", udev_device_get_subsystem(parent))) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->type = NET_PCI;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->pcidev = parent;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->pcidev = udev_device_get_parent_with_subsystem_devtype(dev, "pci", NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!names->pcidev)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOENT;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering dev_pci_onboard(dev, names);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering dev_pci_slot(dev, names);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int names_usb(struct udev_device *dev, struct netnames *names) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char name[256];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char *ports;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char *config;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char *interf;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering size_t l;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char *s;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->usbdev = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!names->usbdev)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOENT;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* get USB port number chain, configuration, interface */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering util_strscpy(name, sizeof(name), udev_device_get_sysname(names->usbdev));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = strchr(name, '-');
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering ports = s+1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = strchr(ports, ':');
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s[0] = '\0';
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna config = s+1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = strchr(config, '.');
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s[0] = '\0';
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering interf = s+1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* prefix every port number in the chain with "u"*/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = ports;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering while ((s = strchr(s, '.')))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s[0] = 'u';
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = names->usb_ports;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering l = util_strpcpyl(&s, sizeof(names->usb_ports), "u", ports, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* append USB config number, suppress the common config == 1 */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!streq(config, "1"))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering l = util_strpcpyl(&s, sizeof(names->usb_ports), "c", config, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* append USB interface number, suppress the interface == 0 */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!streq(interf, "0"))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering l = util_strpcpyl(&s, sizeof(names->usb_ports), "i", interf, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (l == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENAMETOOLONG;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->type = NET_USB;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int names_mac(struct udev_device *dev, struct netnames *names) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *s;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned int i;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned int a1, a2, a3, a4, a5, a6;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* check for NET_ADDR_PERM, skip random MAC addresses */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = udev_device_get_sysattr_value(dev, "addr_assign_type");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return EXIT_FAILURE;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering i = strtoul(s, NULL, 0);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (i != 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = udev_device_get_sysattr_value(dev, "address");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOENT;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (sscanf(s, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* skip empty MAC addresses */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (a1 + a2 + a3 + a4 + a5 + a6 == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->mac[0] = a1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->mac[1] = a2;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->mac[2] = a3;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->mac[3] = a4;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->mac[4] = a5;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->mac[5] = a6;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->mac_valid = true;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/* IEEE Organizationally Unique Identifier vendor string */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int ieee_oui(struct udev_device *dev, struct netnames *names, bool test) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char str[32];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!names->mac_valid)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOENT;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* skip commonly misused 00:00:00 (Xerox) prefix */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (memcmp(names->mac, "\0\0\0", 3) == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering snprintf(str, sizeof(str), "OUI:%02X%02X%02X%02X%02X%02X",
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->mac[0], names->mac[1], names->mac[2],
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names->mac[3], names->mac[4], names->mac[5]);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering udev_builtin_hwdb_lookup(dev, str, test);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool test) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *s;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned int i;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *devtype;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *prefix = "en";
2f7a4867babd3fd382e5495f21724358f30fa67dMichal Sekletar struct netnames names;
2f7a4867babd3fd382e5495f21724358f30fa67dMichal Sekletar int err;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* handle only ARPHRD_ETHER devices */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = udev_device_get_sysattr_value(dev, "type");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return EXIT_FAILURE;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering i = strtoul(s, NULL, 0);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (i != 1)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering devtype = udev_device_get_devtype(dev);
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering if (devtype) {
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering if (streq("wlan", devtype))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering prefix = "wl";
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else if (streq("wwan", devtype))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering prefix = "ww";
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering zero(names);
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek err = names_mac(dev, &names);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (err >= 0 && names.mac_valid) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char str[IFNAMSIZ];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering snprintf(str, sizeof(str), "%sx%02x%02x%02x%02x%02x%02x", prefix,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names.mac[0], names.mac[1], names.mac[2],
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering names.mac[3], names.mac[4], names.mac[5]);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna ieee_oui(dev, &names, test);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna }
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna /* get PCI based path names, we compose only PCI based paths */
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna err = names_pci(dev, &names);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (err < 0)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna goto out;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer /* plain PCI device */
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (names.type == NET_PCI) {
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna char str[IFNAMSIZ];
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (names.pci_onboard[0])
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard) < (int)sizeof(str))
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (names.pci_onboard_label)
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard_label) < (int)sizeof(str))
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (names.pci_path[0])
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_path) < (int)sizeof(str))
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (names.pci_slot[0])
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_slot) < (int)sizeof(str))
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna goto out;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna }
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek /* USB device */
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna err = names_usb(dev, &names);
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek if (err >= 0 && names.type == NET_USB) {
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek char str[IFNAMSIZ];
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek
ef42202ac8ed27e7ff1fc90ef8bc2590046dff25Zbigniew Jędrzejewski-Szmek if (names.pci_path[0])
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.usb_ports) < (int)sizeof(str))
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (names.pci_slot[0])
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.usb_ports) < (int)sizeof(str))
8333c77edf8fd1654cd96f3f6ee0f078dd64b58bZbigniew Jędrzejewski-Szmek udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna }
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmekout:
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return EXIT_SUCCESS;
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna}
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagnaconst struct udev_builtin udev_builtin_net_id = {
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna .name = "net_id",
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna .cmd = builtin_net_id,
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek .help = "network device properties",
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna};
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna