udev-builtin-net_id.c revision 0037a669ac9a2bbedccdb2f483111351e8ff4659
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit This file is part of systemd.
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit Copyright 2012 Kay Sievers <kay@vrfy.org>
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit systemd is free software; you can redistribute it and/or modify it
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit under the terms of the GNU Lesser General Public License as published by
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit the Free Software Foundation; either version 2.1 of the License, or
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit (at your option) any later version.
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit systemd is distributed in the hope that it will be useful, but
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit WITHOUT ANY WARRANTY; without even the implied warranty of
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit Lesser General Public License for more details.
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit You should have received a copy of the GNU Lesser General Public License
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit along with systemd; If not, see <http://www.gnu.org/licenses/>.
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * Predictable network interface device names based on:
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * - firmware/bios-provided index numbers for on-board devices
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * - firmware-provided pci-express hotplug slot index number
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * - physical/geographical location of the hardware
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * - the interface's MAC address
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * Two character prefixes based on the type of interface:
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * en -- Ethernet
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * sl -- serial line IP (slip)
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * wl -- wlan
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * ww -- wwan
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * Type of names:
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * b<number> -- BCMA bus core number
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * c<bus_id> -- CCW bus group name, without leading zeros [s390]
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * o<index>[d<dev_port>] -- on-board device index number
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * s<slot>[f<function>][d<dev_port>] -- hotplug slot index number
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * x<MAC> -- MAC address
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * [P<domain>]p<bus>s<slot>[f<function>][d<dev_port>]
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * -- PCI geographical location
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * -- USB port number chain
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * All multi-function PCI devices will carry the [f<function>] number in the
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * device name, including the function 0 device.
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * When using PCI geography, The PCI domain is only prepended when it is not 0.
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * For USB devices the full chain of port numbers of hubs is composed. If the
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * name gets longer than the maximum number of 15 characters, the name is not
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * The usual USB configuration == 1 and interface == 0 values are suppressed.
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * PCI Ethernet card with firmware index "1":
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * ID_NET_NAME_ONBOARD=eno1
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit * ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "fd-util.h"
#include "fileio.h"
#include "stdio-util.h"
#include "string-util.h"
#include "udev.h"
enum netname_type{
struct netnames {
bool mac_valid;
const char *pci_onboard_label;
unsigned dev_port = 0;
size_t l;
const char *attr;
int idx;
if (!attr)
if (!attr)
return -ENOENT;
if (idx <= 0)
return -EINVAL;
/* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to report for
* example). Let's define a cut-off where we don't consider the index reliable anymore. We pick some arbitrary
* cut-off, which is somewhere beyond the realistic number of physical network interface a system might
return -ENOENT;
if (attr)
if (dev_port > 0)
const char *filename;
if (fd < 0)
size_t l;
const char *attr;
if (sscanf(udev_device_get_sysname(names->pcidev), "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4)
return -ENOENT;
if (attr)
if (domain > 0)
if (dev_port > 0)
if (!pci) {
goto out;
if (!dir) {
goto out;
char *rest;
char *address;
hotplug_slot = i;
if (hotplug_slot > 0)
if (hotplug_slot > 0) {
if (domain > 0)
if (dev_port > 0)
out:
return err;
if (!parent)
return -ENOENT;
return -ENOENT;
char *ports;
char *config;
char *interf;
size_t l;
if (!usbdev)
return -ENOENT;
return -EINVAL;
return -EINVAL;
return -EINVAL;
s = ports;
return -ENAMETOOLONG;
unsigned int core;
if (!bcmadev)
return -ENOENT;
return -EINVAL;
if (core > 0)
const char *bus_id;
int rc;
if (!cdev)
return -ENOENT;
return -ENOENT;
if (!bus_id)
return -ENOENT;
return -EINVAL;
return EXIT_FAILURE;
return -ENOENT;
return -EINVAL;
return -EINVAL;
return -ENOENT;
return -EINVAL;
const char *devtype;
int err;
return EXIT_FAILURE;
case ARPHRD_ETHER:
case ARPHRD_SLIP:
return EXIT_FAILURE;
return EXIT_FAILURE;
if (!streq(s, p))
if (devtype) {
goto out;
if (err < 0)
goto out;
goto out;
if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.usb_ports) < (int)sizeof(str))
if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.usb_ports) < (int)sizeof(str))
goto out;
if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.bcma_core) < (int)sizeof(str))
if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.bcma_core) < (int)sizeof(str))
goto out;
out:
return EXIT_SUCCESS;