LCOV - code coverage report
Current view: top level - udev - udev-builtin-net_id.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 482 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 16 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 425 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : /*
       4                 :            :  * Predictable network interface device names based on:
       5                 :            :  *  - firmware/bios-provided index numbers for on-board devices
       6                 :            :  *  - firmware-provided pci-express hotplug slot index number
       7                 :            :  *  - physical/geographical location of the hardware
       8                 :            :  *  - the interface's MAC address
       9                 :            :  *
      10                 :            :  * http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames
      11                 :            :  *
      12                 :            :  * When the code here is changed, man/systemd.net-naming-scheme.xml must be updated too.
      13                 :            :  */
      14                 :            : 
      15                 :            : #include <errno.h>
      16                 :            : #include <fcntl.h>
      17                 :            : #include <net/if.h>
      18                 :            : #include <net/if_arp.h>
      19                 :            : #include <stdarg.h>
      20                 :            : #include <stdio.h>
      21                 :            : #include <stdlib.h>
      22                 :            : #include <string.h>
      23                 :            : #include <unistd.h>
      24                 :            : #include <linux/pci_regs.h>
      25                 :            : 
      26                 :            : #include "alloc-util.h"
      27                 :            : #include "dirent-util.h"
      28                 :            : #include "fd-util.h"
      29                 :            : #include "fileio.h"
      30                 :            : #include "fs-util.h"
      31                 :            : #include "naming-scheme.h"
      32                 :            : #include "parse-util.h"
      33                 :            : #include "proc-cmdline.h"
      34                 :            : #include "stdio-util.h"
      35                 :            : #include "string-util.h"
      36                 :            : #include "strv.h"
      37                 :            : #include "strxcpyx.h"
      38                 :            : #include "udev-builtin.h"
      39                 :            : 
      40                 :            : #define ONBOARD_INDEX_MAX (16*1024-1)
      41                 :            : 
      42                 :            : enum netname_type{
      43                 :            :         NET_UNDEF,
      44                 :            :         NET_PCI,
      45                 :            :         NET_USB,
      46                 :            :         NET_BCMA,
      47                 :            :         NET_VIRTIO,
      48                 :            :         NET_CCW,
      49                 :            :         NET_VIO,
      50                 :            :         NET_PLATFORM,
      51                 :            :         NET_NETDEVSIM,
      52                 :            : };
      53                 :            : 
      54                 :            : struct netnames {
      55                 :            :         enum netname_type type;
      56                 :            : 
      57                 :            :         uint8_t mac[6];
      58                 :            :         bool mac_valid;
      59                 :            : 
      60                 :            :         sd_device *pcidev;
      61                 :            :         char pci_slot[IFNAMSIZ];
      62                 :            :         char pci_path[IFNAMSIZ];
      63                 :            :         char pci_onboard[IFNAMSIZ];
      64                 :            :         const char *pci_onboard_label;
      65                 :            : 
      66                 :            :         char usb_ports[IFNAMSIZ];
      67                 :            :         char bcma_core[IFNAMSIZ];
      68                 :            :         char ccw_busid[IFNAMSIZ];
      69                 :            :         char vio_slot[IFNAMSIZ];
      70                 :            :         char platform_path[IFNAMSIZ];
      71                 :            :         char netdevsim_path[IFNAMSIZ];
      72                 :            : };
      73                 :            : 
      74                 :            : struct virtfn_info {
      75                 :            :         sd_device *physfn_pcidev;
      76                 :            :         char suffix[IFNAMSIZ];
      77                 :            : };
      78                 :            : 
      79                 :            : /* skip intermediate virtio devices */
      80                 :          0 : static sd_device *skip_virtio(sd_device *dev) {
      81                 :            :         sd_device *parent;
      82                 :            : 
      83                 :            :         /* there can only ever be one virtio bus per parent device, so we can
      84                 :            :          * safely ignore any virtio buses. see
      85                 :            :          * http://lists.linuxfoundation.org/pipermail/virtualization/2015-August/030331.html */
      86         [ #  # ]:          0 :         for (parent = dev; parent; ) {
      87                 :            :                 const char *subsystem;
      88                 :            : 
      89         [ #  # ]:          0 :                 if (sd_device_get_subsystem(parent, &subsystem) < 0)
      90                 :          0 :                         break;
      91                 :            : 
      92         [ #  # ]:          0 :                 if (!streq(subsystem, "virtio"))
      93                 :          0 :                         break;
      94                 :            : 
      95         [ #  # ]:          0 :                 if (sd_device_get_parent(parent, &parent) < 0)
      96                 :          0 :                         return NULL;
      97                 :            :         }
      98                 :            : 
      99                 :          0 :         return parent;
     100                 :            : }
     101                 :            : 
     102                 :          0 : static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn_info *ret) {
     103                 :          0 :         _cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL;
     104                 :            :         const char *physfn_link_file, *syspath;
     105                 :          0 :         _cleanup_free_ char *physfn_pci_syspath = NULL;
     106                 :          0 :         _cleanup_free_ char *virtfn_pci_syspath = NULL;
     107                 :            :         struct dirent *dent;
     108                 :          0 :         _cleanup_closedir_ DIR *dir = NULL;
     109                 :            :         char suffix[IFNAMSIZ];
     110                 :            :         int r;
     111                 :            : 
     112         [ #  # ]:          0 :         assert(dev);
     113         [ #  # ]:          0 :         assert(names);
     114         [ #  # ]:          0 :         assert(ret);
     115                 :            : 
     116                 :          0 :         r = sd_device_get_syspath(names->pcidev, &syspath);
     117         [ #  # ]:          0 :         if (r < 0)
     118                 :          0 :                 return r;
     119                 :            : 
     120                 :            :         /* Check if this is a virtual function. */
     121   [ #  #  #  #  :          0 :         physfn_link_file = strjoina(syspath, "/physfn");
          #  #  #  #  #  
                #  #  # ]
     122                 :          0 :         r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath);
     123         [ #  # ]:          0 :         if (r < 0)
     124                 :          0 :                 return r;
     125                 :            : 
     126                 :            :         /* Get physical function's pci device. */
     127                 :          0 :         r = sd_device_new_from_syspath(&physfn_pcidev, physfn_pci_syspath);
     128         [ #  # ]:          0 :         if (r < 0)
     129                 :          0 :                 return r;
     130                 :            : 
     131                 :            :         /* Find the virtual function number by finding the right virtfn link. */
     132                 :          0 :         dir = opendir(physfn_pci_syspath);
     133         [ #  # ]:          0 :         if (!dir)
     134                 :          0 :                 return -errno;
     135                 :            : 
     136   [ #  #  #  # ]:          0 :         FOREACH_DIRENT_ALL(dent, dir, break) {
     137   [ #  #  #  # ]:          0 :                 _cleanup_free_ char *virtfn_link_file = NULL;
     138                 :            : 
     139         [ #  # ]:          0 :                 if (!startswith(dent->d_name, "virtfn"))
     140                 :          0 :                         continue;
     141                 :            : 
     142                 :          0 :                 virtfn_link_file = path_join(physfn_pci_syspath, dent->d_name);
     143         [ #  # ]:          0 :                 if (!virtfn_link_file)
     144                 :          0 :                         return -ENOMEM;
     145                 :            : 
     146         [ #  # ]:          0 :                 if (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath) < 0)
     147                 :          0 :                         continue;
     148                 :            : 
     149         [ #  # ]:          0 :                 if (streq(syspath, virtfn_pci_syspath)) {
     150         [ #  # ]:          0 :                         if (!snprintf_ok(suffix, sizeof(suffix), "v%s", &dent->d_name[6]))
     151                 :          0 :                                 return -ENOENT;
     152                 :            : 
     153                 :          0 :                         break;
     154                 :            :                 }
     155                 :            :         }
     156         [ #  # ]:          0 :         if (isempty(suffix))
     157                 :          0 :                 return -ENOENT;
     158                 :            : 
     159                 :          0 :         ret->physfn_pcidev = TAKE_PTR(physfn_pcidev);
     160                 :          0 :         strncpy(ret->suffix, suffix, sizeof(ret->suffix));
     161                 :            : 
     162                 :          0 :         return 0;
     163                 :            : }
     164                 :            : 
     165                 :            : /* retrieve on-board index number and label from firmware */
     166                 :          0 : static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
     167                 :          0 :         unsigned long idx, dev_port = 0;
     168                 :          0 :         const char *attr, *port_name = NULL;
     169                 :            :         size_t l;
     170                 :            :         char *s;
     171                 :            :         int r;
     172                 :            : 
     173                 :            :         /* ACPI _DSM — device specific method for naming a PCI or PCI Express device */
     174         [ #  # ]:          0 :         if (sd_device_get_sysattr_value(names->pcidev, "acpi_index", &attr) < 0) {
     175                 :            :                 /* SMBIOS type 41 — Onboard Devices Extended Information */
     176                 :          0 :                 r = sd_device_get_sysattr_value(names->pcidev, "index", &attr);
     177         [ #  # ]:          0 :                 if (r < 0)
     178                 :          0 :                         return r;
     179                 :            :         }
     180                 :            : 
     181                 :          0 :         r = safe_atolu(attr, &idx);
     182         [ #  # ]:          0 :         if (r < 0)
     183                 :          0 :                 return r;
     184   [ #  #  #  # ]:          0 :         if (idx == 0 && !naming_scheme_has(NAMING_ZERO_ACPI_INDEX))
     185                 :          0 :                 return -EINVAL;
     186                 :            : 
     187                 :            :         /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
     188                 :            :          * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We
     189                 :            :          * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network
     190                 :            :          * interface a system might have. Ideally the kernel would already filter his crap for us, but it
     191                 :            :          * doesn't currently. */
     192         [ #  # ]:          0 :         if (idx > ONBOARD_INDEX_MAX)
     193                 :          0 :                 return -ENOENT;
     194                 :            : 
     195                 :            :         /* kernel provided port index for multiple ports on a single PCI function */
     196         [ #  # ]:          0 :         if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0)
     197                 :          0 :                 dev_port = strtoul(attr, NULL, 10);
     198                 :            : 
     199                 :            :         /* kernel provided front panel port name for multiple port PCI device */
     200                 :          0 :         (void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
     201                 :            : 
     202                 :          0 :         s = names->pci_onboard;
     203                 :          0 :         l = sizeof(names->pci_onboard);
     204                 :          0 :         l = strpcpyf(&s, l, "o%lu", idx);
     205         [ #  # ]:          0 :         if (port_name)
     206                 :          0 :                 l = strpcpyf(&s, l, "n%s", port_name);
     207         [ #  # ]:          0 :         else if (dev_port > 0)
     208                 :          0 :                 l = strpcpyf(&s, l, "d%lu", dev_port);
     209         [ #  # ]:          0 :         if (l == 0)
     210                 :          0 :                 names->pci_onboard[0] = '\0';
     211                 :            : 
     212         [ #  # ]:          0 :         if (sd_device_get_sysattr_value(names->pcidev, "label", &names->pci_onboard_label) < 0)
     213                 :          0 :                 names->pci_onboard_label = NULL;
     214                 :            : 
     215                 :          0 :         return 0;
     216                 :            : }
     217                 :            : 
     218                 :            : /* read the 256 bytes PCI configuration space to check the multi-function bit */
     219                 :          0 : static bool is_pci_multifunction(sd_device *dev) {
     220                 :          0 :         _cleanup_close_ int fd = -1;
     221                 :            :         const char *filename, *syspath;
     222                 :            :         uint8_t config[64];
     223                 :            : 
     224         [ #  # ]:          0 :         if (sd_device_get_syspath(dev, &syspath) < 0)
     225                 :          0 :                 return false;
     226                 :            : 
     227   [ #  #  #  #  :          0 :         filename = strjoina(syspath, "/config");
          #  #  #  #  #  
                #  #  # ]
     228                 :          0 :         fd = open(filename, O_RDONLY | O_CLOEXEC);
     229         [ #  # ]:          0 :         if (fd < 0)
     230                 :          0 :                 return false;
     231         [ #  # ]:          0 :         if (read(fd, &config, sizeof(config)) != sizeof(config))
     232                 :          0 :                 return false;
     233                 :            : 
     234                 :            :         /* bit 0-6 header type, bit 7 multi/single function device */
     235                 :          0 :         return config[PCI_HEADER_TYPE] & 0x80;
     236                 :            : }
     237                 :            : 
     238                 :          0 : static bool is_pci_ari_enabled(sd_device *dev) {
     239                 :            :         const char *a;
     240                 :            : 
     241         [ #  # ]:          0 :         if (sd_device_get_sysattr_value(dev, "ari_enabled", &a) < 0)
     242                 :          0 :                 return false;
     243                 :            : 
     244                 :          0 :         return streq(a, "1");
     245                 :            : }
     246                 :            : 
     247                 :          0 : static int dev_pci_slot(sd_device *dev, struct netnames *names) {
     248                 :          0 :         unsigned long dev_port = 0;
     249                 :          0 :         unsigned domain, bus, slot, func, hotplug_slot = 0;
     250                 :            :         size_t l;
     251                 :            :         char *s;
     252                 :          0 :         const char *sysname, *attr, *port_name = NULL, *syspath;
     253                 :          0 :         _cleanup_(sd_device_unrefp) sd_device *pci = NULL;
     254                 :            :         sd_device *hotplug_slot_dev;
     255                 :            :         char slots[PATH_MAX];
     256                 :          0 :         _cleanup_closedir_ DIR *dir = NULL;
     257                 :            :         struct dirent *dent;
     258                 :            :         int r;
     259                 :            : 
     260                 :          0 :         r = sd_device_get_sysname(names->pcidev, &sysname);
     261         [ #  # ]:          0 :         if (r < 0)
     262                 :          0 :                 return r;
     263                 :            : 
     264         [ #  # ]:          0 :         if (sscanf(sysname, "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4)
     265                 :          0 :                 return -ENOENT;
     266                 :            : 
     267   [ #  #  #  # ]:          0 :         if (naming_scheme_has(NAMING_NPAR_ARI) &&
     268                 :          0 :             is_pci_ari_enabled(names->pcidev))
     269                 :            :                 /* ARI devices support up to 256 functions on a single device ("slot"), and interpret the
     270                 :            :                  * traditional 5-bit slot and 3-bit function number as a single 8-bit function number,
     271                 :            :                  * where the slot makes up the upper 5 bits. */
     272                 :          0 :                 func += slot * 8;
     273                 :            : 
     274                 :            :         /* kernel provided port index for multiple ports on a single PCI function */
     275         [ #  # ]:          0 :         if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) {
     276                 :          0 :                 dev_port = strtoul(attr, NULL, 10);
     277                 :            :                 /* With older kernels IP-over-InfiniBand network interfaces sometimes erroneously
     278                 :            :                  * provide the port number in the 'dev_id' sysfs attribute instead of 'dev_port',
     279                 :            :                  * which thus stays initialized as 0. */
     280   [ #  #  #  # ]:          0 :                 if (dev_port == 0 &&
     281                 :          0 :                     sd_device_get_sysattr_value(dev, "type", &attr) >= 0) {
     282                 :            :                         unsigned long type;
     283                 :            : 
     284                 :          0 :                         type = strtoul(attr, NULL, 10);
     285   [ #  #  #  # ]:          0 :                         if (type == ARPHRD_INFINIBAND &&
     286                 :          0 :                             sd_device_get_sysattr_value(dev, "dev_id", &attr) >= 0)
     287                 :          0 :                                 dev_port = strtoul(attr, NULL, 16);
     288                 :            :                 }
     289                 :            :         }
     290                 :            : 
     291                 :            :         /* kernel provided front panel port name for multi-port PCI device */
     292                 :          0 :         (void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
     293                 :            : 
     294                 :            :         /* compose a name based on the raw kernel's PCI bus, slot numbers */
     295                 :          0 :         s = names->pci_path;
     296                 :          0 :         l = sizeof(names->pci_path);
     297         [ #  # ]:          0 :         if (domain > 0)
     298                 :          0 :                 l = strpcpyf(&s, l, "P%u", domain);
     299                 :          0 :         l = strpcpyf(&s, l, "p%us%u", bus, slot);
     300   [ #  #  #  # ]:          0 :         if (func > 0 || is_pci_multifunction(names->pcidev))
     301                 :          0 :                 l = strpcpyf(&s, l, "f%u", func);
     302         [ #  # ]:          0 :         if (port_name)
     303                 :          0 :                 l = strpcpyf(&s, l, "n%s", port_name);
     304         [ #  # ]:          0 :         else if (dev_port > 0)
     305                 :          0 :                 l = strpcpyf(&s, l, "d%lu", dev_port);
     306         [ #  # ]:          0 :         if (l == 0)
     307                 :          0 :                 names->pci_path[0] = '\0';
     308                 :            : 
     309                 :            :         /* ACPI _SUN — slot user number */
     310                 :          0 :         r = sd_device_new_from_subsystem_sysname(&pci, "subsystem", "pci");
     311         [ #  # ]:          0 :         if (r < 0)
     312                 :          0 :                 return r;
     313                 :            : 
     314                 :          0 :         r = sd_device_get_syspath(pci, &syspath);
     315         [ #  # ]:          0 :         if (r < 0)
     316                 :          0 :                 return r;
     317         [ #  # ]:          0 :         if (!snprintf_ok(slots, sizeof slots, "%s/slots", syspath))
     318                 :          0 :                 return -ENAMETOOLONG;
     319                 :            : 
     320                 :          0 :         dir = opendir(slots);
     321         [ #  # ]:          0 :         if (!dir)
     322                 :          0 :                 return -errno;
     323                 :            : 
     324                 :          0 :         hotplug_slot_dev = names->pcidev;
     325         [ #  # ]:          0 :         while (hotplug_slot_dev) {
     326         [ #  # ]:          0 :                 if (sd_device_get_sysname(hotplug_slot_dev, &sysname) < 0)
     327                 :          0 :                         continue;
     328                 :            : 
     329   [ #  #  #  # ]:          0 :                 FOREACH_DIRENT_ALL(dent, dir, break) {
     330                 :            :                         unsigned i;
     331                 :            :                         char str[PATH_MAX];
     332      [ #  #  # ]:          0 :                         _cleanup_free_ char *address = NULL;
     333                 :            : 
     334         [ #  # ]:          0 :                         if (dent->d_name[0] == '.')
     335                 :          0 :                                 continue;
     336                 :          0 :                         r = safe_atou_full(dent->d_name, 10, &i);
     337   [ #  #  #  # ]:          0 :                         if (r < 0 || i <= 0)
     338                 :          0 :                                 continue;
     339                 :            : 
     340                 :            :                         /* match slot address with device by stripping the function */
     341   [ #  #  #  # ]:          0 :                         if (snprintf_ok(str, sizeof str, "%s/%s/address", slots, dent->d_name) &&
     342         [ #  # ]:          0 :                             read_one_line_file(str, &address) >= 0 &&
     343                 :          0 :                             startswith(sysname, address)) {
     344                 :          0 :                                 hotplug_slot = i;
     345                 :          0 :                                 break;
     346                 :            :                         }
     347                 :            :                 }
     348         [ #  # ]:          0 :                 if (hotplug_slot > 0)
     349                 :          0 :                         break;
     350         [ #  # ]:          0 :                 if (sd_device_get_parent_with_subsystem_devtype(hotplug_slot_dev, "pci", NULL, &hotplug_slot_dev) < 0)
     351                 :          0 :                         break;
     352                 :          0 :                 rewinddir(dir);
     353                 :            :         }
     354                 :            : 
     355         [ #  # ]:          0 :         if (hotplug_slot > 0) {
     356                 :          0 :                 s = names->pci_slot;
     357                 :          0 :                 l = sizeof(names->pci_slot);
     358         [ #  # ]:          0 :                 if (domain > 0)
     359                 :          0 :                         l = strpcpyf(&s, l, "P%d", domain);
     360                 :          0 :                 l = strpcpyf(&s, l, "s%d", hotplug_slot);
     361   [ #  #  #  # ]:          0 :                 if (func > 0 || is_pci_multifunction(names->pcidev))
     362                 :          0 :                         l = strpcpyf(&s, l, "f%d", func);
     363         [ #  # ]:          0 :                 if (port_name)
     364                 :          0 :                         l = strpcpyf(&s, l, "n%s", port_name);
     365         [ #  # ]:          0 :                 else if (dev_port > 0)
     366                 :          0 :                         l = strpcpyf(&s, l, "d%lu", dev_port);
     367         [ #  # ]:          0 :                 if (l == 0)
     368                 :          0 :                         names->pci_slot[0] = '\0';
     369                 :            :         }
     370                 :            : 
     371                 :          0 :         return 0;
     372                 :            : }
     373                 :            : 
     374                 :          0 : static int names_vio(sd_device *dev, struct netnames *names) {
     375                 :            :         sd_device *parent;
     376                 :            :         unsigned busid, slotid, ethid;
     377                 :            :         const char *syspath, *subsystem;
     378                 :            :         int r;
     379                 :            : 
     380                 :            :         /* check if our direct parent is a VIO device with no other bus in-between */
     381                 :          0 :         r = sd_device_get_parent(dev, &parent);
     382         [ #  # ]:          0 :         if (r < 0)
     383                 :          0 :                 return r;
     384                 :            : 
     385                 :          0 :         r = sd_device_get_subsystem(parent, &subsystem);
     386         [ #  # ]:          0 :         if (r < 0)
     387                 :          0 :                 return r;
     388         [ #  # ]:          0 :         if (!streq("vio", subsystem))
     389                 :          0 :                 return -ENOENT;
     390                 :            : 
     391                 :            :         /* The devices' $DEVPATH number is tied to (virtual) hardware (slot id
     392                 :            :          * selected in the HMC), thus this provides a reliable naming (e.g.
     393                 :            :          * "/devices/vio/30000002/net/eth1"); we ignore the bus number, as
     394                 :            :          * there should only ever be one bus, and then remove leading zeros. */
     395                 :          0 :         r = sd_device_get_syspath(dev, &syspath);
     396         [ #  # ]:          0 :         if (r < 0)
     397                 :          0 :                 return r;
     398                 :            : 
     399         [ #  # ]:          0 :         if (sscanf(syspath, "/sys/devices/vio/%4x%4x/net/eth%u", &busid, &slotid, &ethid) != 3)
     400                 :          0 :                 return -EINVAL;
     401                 :            : 
     402         [ #  # ]:          0 :         xsprintf(names->vio_slot, "v%u", slotid);
     403                 :          0 :         names->type = NET_VIO;
     404                 :          0 :         return 0;
     405                 :            : }
     406                 :            : 
     407                 :            : #define _PLATFORM_TEST "/sys/devices/platform/vvvvPPPP"
     408                 :            : #define _PLATFORM_PATTERN4 "/sys/devices/platform/%4s%4x:%2x/net/eth%u"
     409                 :            : #define _PLATFORM_PATTERN3 "/sys/devices/platform/%3s%4x:%2x/net/eth%u"
     410                 :            : 
     411                 :          0 : static int names_platform(sd_device *dev, struct netnames *names, bool test) {
     412                 :            :         sd_device *parent;
     413                 :            :         char vendor[5];
     414                 :            :         unsigned model, instance, ethid;
     415                 :            :         const char *syspath, *pattern, *validchars, *subsystem;
     416                 :            :         int r;
     417                 :            : 
     418                 :            :         /* check if our direct parent is a platform device with no other bus in-between */
     419                 :          0 :         r = sd_device_get_parent(dev, &parent);
     420         [ #  # ]:          0 :         if (r < 0)
     421                 :          0 :                 return r;
     422                 :            : 
     423                 :          0 :         r = sd_device_get_subsystem(parent, &subsystem);
     424         [ #  # ]:          0 :         if (r < 0)
     425                 :          0 :                 return r;
     426                 :            : 
     427         [ #  # ]:          0 :         if (!streq("platform", subsystem))
     428                 :          0 :                  return -ENOENT;
     429                 :            : 
     430                 :          0 :         r = sd_device_get_syspath(dev, &syspath);
     431         [ #  # ]:          0 :         if (r < 0)
     432                 :          0 :                 return r;
     433                 :            : 
     434                 :            :         /* syspath is too short, to have a valid ACPI instance */
     435         [ #  # ]:          0 :         if (strlen(syspath) < sizeof _PLATFORM_TEST)
     436                 :          0 :                 return -EINVAL;
     437                 :            : 
     438                 :            :         /* Vendor ID can be either PNP ID (3 chars A-Z) or ACPI ID (4 chars A-Z and numerals) */
     439         [ #  # ]:          0 :         if (syspath[sizeof _PLATFORM_TEST - 1] == ':') {
     440                 :          0 :                 pattern = _PLATFORM_PATTERN4;
     441                 :          0 :                 validchars = UPPERCASE_LETTERS DIGITS;
     442                 :            :         } else {
     443                 :          0 :                 pattern = _PLATFORM_PATTERN3;
     444                 :          0 :                 validchars = UPPERCASE_LETTERS;
     445                 :            :         }
     446                 :            : 
     447                 :            :         /* Platform devices are named after ACPI table match, and instance id
     448                 :            :          * eg. "/sys/devices/platform/HISI00C2:00");
     449                 :            :          * The Vendor (3 or 4 char), followed by hexdecimal model number : instance id.
     450                 :            :          */
     451                 :            : 
     452                 :            : #pragma GCC diagnostic push
     453                 :            : #pragma GCC diagnostic ignored "-Wformat-nonliteral"
     454         [ #  # ]:          0 :         if (sscanf(syspath, pattern, vendor, &model, &instance, &ethid) != 4)
     455                 :          0 :                 return -EINVAL;
     456                 :            : #pragma GCC diagnostic pop
     457                 :            : 
     458         [ #  # ]:          0 :         if (!in_charset(vendor, validchars))
     459                 :          0 :                 return -ENOENT;
     460                 :            : 
     461                 :          0 :         ascii_strlower(vendor);
     462                 :            : 
     463         [ #  # ]:          0 :         xsprintf(names->platform_path, "a%s%xi%u", vendor, model, instance);
     464                 :          0 :         names->type = NET_PLATFORM;
     465                 :          0 :         return 0;
     466                 :            : }
     467                 :            : 
     468                 :          0 : static int names_pci(sd_device *dev, struct netnames *names) {
     469                 :            :         sd_device *parent;
     470                 :          0 :         struct netnames vf_names = {};
     471                 :          0 :         struct virtfn_info vf_info = {};
     472                 :            :         const char *subsystem;
     473                 :            :         int r;
     474                 :            : 
     475         [ #  # ]:          0 :         assert(dev);
     476         [ #  # ]:          0 :         assert(names);
     477                 :            : 
     478                 :          0 :         r = sd_device_get_parent(dev, &parent);
     479         [ #  # ]:          0 :         if (r < 0)
     480                 :          0 :                 return r;
     481                 :            :         /* skip virtio subsystem if present */
     482                 :          0 :         parent = skip_virtio(parent);
     483                 :            : 
     484         [ #  # ]:          0 :         if (!parent)
     485                 :          0 :                 return -ENOENT;
     486                 :            : 
     487                 :            :         /* check if our direct parent is a PCI device with no other bus in-between */
     488         [ #  # ]:          0 :         if (sd_device_get_subsystem(parent, &subsystem) >= 0 &&
     489         [ #  # ]:          0 :             streq("pci", subsystem)) {
     490                 :          0 :                 names->type = NET_PCI;
     491                 :          0 :                 names->pcidev = parent;
     492                 :            :         } else {
     493                 :          0 :                 r = sd_device_get_parent_with_subsystem_devtype(dev, "pci", NULL, &names->pcidev);
     494         [ #  # ]:          0 :                 if (r < 0)
     495                 :          0 :                         return r;
     496                 :            :         }
     497                 :            : 
     498   [ #  #  #  # ]:          0 :         if (naming_scheme_has(NAMING_SR_IOV_V) &&
     499                 :          0 :             get_virtfn_info(dev, names, &vf_info) >= 0) {
     500                 :            :                 /* If this is an SR-IOV virtual device, get base name using physical device and add virtfn suffix. */
     501                 :          0 :                 vf_names.pcidev = vf_info.physfn_pcidev;
     502                 :          0 :                 dev_pci_onboard(dev, &vf_names);
     503                 :          0 :                 dev_pci_slot(dev, &vf_names);
     504         [ #  # ]:          0 :                 if (vf_names.pci_onboard[0])
     505         [ #  # ]:          0 :                         if (strlen(vf_names.pci_onboard) + strlen(vf_info.suffix) < sizeof(names->pci_onboard))
     506                 :          0 :                                 strscpyl(names->pci_onboard, sizeof(names->pci_onboard),
     507                 :            :                                          vf_names.pci_onboard, vf_info.suffix, NULL);
     508         [ #  # ]:          0 :                 if (vf_names.pci_slot[0])
     509         [ #  # ]:          0 :                         if (strlen(vf_names.pci_slot) + strlen(vf_info.suffix) < sizeof(names->pci_slot))
     510                 :          0 :                                 strscpyl(names->pci_slot, sizeof(names->pci_slot),
     511                 :            :                                          vf_names.pci_slot, vf_info.suffix, NULL);
     512         [ #  # ]:          0 :                 if (vf_names.pci_path[0])
     513         [ #  # ]:          0 :                         if (strlen(vf_names.pci_path) + strlen(vf_info.suffix) < sizeof(names->pci_path))
     514                 :          0 :                                 strscpyl(names->pci_path, sizeof(names->pci_path),
     515                 :            :                                          vf_names.pci_path, vf_info.suffix, NULL);
     516                 :          0 :                 sd_device_unref(vf_info.physfn_pcidev);
     517                 :            :         } else {
     518                 :          0 :                 dev_pci_onboard(dev, names);
     519                 :          0 :                 dev_pci_slot(dev, names);
     520                 :            :         }
     521                 :            : 
     522                 :          0 :         return 0;
     523                 :            : }
     524                 :            : 
     525                 :          0 : static int names_usb(sd_device *dev, struct netnames *names) {
     526                 :            :         sd_device *usbdev;
     527                 :            :         char name[256], *ports, *config, *interf, *s;
     528                 :            :         const char *sysname;
     529                 :            :         size_t l;
     530                 :            :         int r;
     531                 :            : 
     532         [ #  # ]:          0 :         assert(dev);
     533         [ #  # ]:          0 :         assert(names);
     534                 :            : 
     535                 :          0 :         r = sd_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface", &usbdev);
     536         [ #  # ]:          0 :         if (r < 0)
     537                 :          0 :                 return r;
     538                 :            : 
     539                 :          0 :         r = sd_device_get_sysname(usbdev, &sysname);
     540         [ #  # ]:          0 :         if (r < 0)
     541                 :          0 :                 return r;
     542                 :            : 
     543                 :            :         /* get USB port number chain, configuration, interface */
     544                 :          0 :         strscpy(name, sizeof(name), sysname);
     545                 :          0 :         s = strchr(name, '-');
     546         [ #  # ]:          0 :         if (!s)
     547                 :          0 :                 return -EINVAL;
     548                 :          0 :         ports = s+1;
     549                 :            : 
     550                 :          0 :         s = strchr(ports, ':');
     551         [ #  # ]:          0 :         if (!s)
     552                 :          0 :                 return -EINVAL;
     553                 :          0 :         s[0] = '\0';
     554                 :          0 :         config = s+1;
     555                 :            : 
     556                 :          0 :         s = strchr(config, '.');
     557         [ #  # ]:          0 :         if (!s)
     558                 :          0 :                 return -EINVAL;
     559                 :          0 :         s[0] = '\0';
     560                 :          0 :         interf = s+1;
     561                 :            : 
     562                 :            :         /* prefix every port number in the chain with "u" */
     563                 :          0 :         s = ports;
     564         [ #  # ]:          0 :         while ((s = strchr(s, '.')))
     565                 :          0 :                 s[0] = 'u';
     566                 :          0 :         s = names->usb_ports;
     567                 :          0 :         l = strpcpyl(&s, sizeof(names->usb_ports), "u", ports, NULL);
     568                 :            : 
     569                 :            :         /* append USB config number, suppress the common config == 1 */
     570         [ #  # ]:          0 :         if (!streq(config, "1"))
     571                 :          0 :                 l = strpcpyl(&s, sizeof(names->usb_ports), "c", config, NULL);
     572                 :            : 
     573                 :            :         /* append USB interface number, suppress the interface == 0 */
     574         [ #  # ]:          0 :         if (!streq(interf, "0"))
     575                 :          0 :                 l = strpcpyl(&s, sizeof(names->usb_ports), "i", interf, NULL);
     576         [ #  # ]:          0 :         if (l == 0)
     577                 :          0 :                 return -ENAMETOOLONG;
     578                 :            : 
     579                 :          0 :         names->type = NET_USB;
     580                 :          0 :         return 0;
     581                 :            : }
     582                 :            : 
     583                 :          0 : static int names_bcma(sd_device *dev, struct netnames *names) {
     584                 :            :         sd_device *bcmadev;
     585                 :            :         unsigned core;
     586                 :            :         const char *sysname;
     587                 :            :         int r;
     588                 :            : 
     589         [ #  # ]:          0 :         assert(dev);
     590         [ #  # ]:          0 :         assert(names);
     591                 :            : 
     592                 :          0 :         r = sd_device_get_parent_with_subsystem_devtype(dev, "bcma", NULL, &bcmadev);
     593         [ #  # ]:          0 :         if (r < 0)
     594                 :          0 :                 return r;
     595                 :            : 
     596                 :          0 :         r = sd_device_get_sysname(bcmadev, &sysname);
     597         [ #  # ]:          0 :         if (r < 0)
     598                 :          0 :                 return r;
     599                 :            : 
     600                 :            :         /* bus num:core num */
     601         [ #  # ]:          0 :         if (sscanf(sysname, "bcma%*u:%u", &core) != 1)
     602                 :          0 :                 return -EINVAL;
     603                 :            :         /* suppress the common core == 0 */
     604         [ #  # ]:          0 :         if (core > 0)
     605         [ #  # ]:          0 :                 xsprintf(names->bcma_core, "b%u", core);
     606                 :            : 
     607                 :          0 :         names->type = NET_BCMA;
     608                 :          0 :         return 0;
     609                 :            : }
     610                 :            : 
     611                 :          0 : static int names_ccw(sd_device *dev, struct netnames *names) {
     612                 :            :         sd_device *cdev;
     613                 :            :         const char *bus_id, *subsys;
     614                 :            :         size_t bus_id_len;
     615                 :            :         size_t bus_id_start;
     616                 :            :         int r;
     617                 :            : 
     618         [ #  # ]:          0 :         assert(dev);
     619         [ #  # ]:          0 :         assert(names);
     620                 :            : 
     621                 :            :         /* Retrieve the associated CCW device */
     622                 :          0 :         r = sd_device_get_parent(dev, &cdev);
     623         [ #  # ]:          0 :         if (r < 0)
     624                 :          0 :                 return r;
     625                 :            : 
     626                 :            :         /* skip virtio subsystem if present */
     627                 :          0 :         cdev = skip_virtio(cdev);
     628         [ #  # ]:          0 :         if (!cdev)
     629                 :          0 :                 return -ENOENT;
     630                 :            : 
     631                 :          0 :         r = sd_device_get_subsystem(cdev, &subsys);
     632         [ #  # ]:          0 :         if (r < 0)
     633                 :          0 :                 return r;
     634                 :            : 
     635                 :            :         /* Network devices are either single or grouped CCW devices */
     636         [ #  # ]:          0 :         if (!STR_IN_SET(subsys, "ccwgroup", "ccw"))
     637                 :          0 :                 return -ENOENT;
     638                 :            : 
     639                 :            :         /* Retrieve bus-ID of the CCW device.  The bus-ID uniquely
     640                 :            :          * identifies the network device on the Linux on System z channel
     641                 :            :          * subsystem.  Note that the bus-ID contains lowercase characters.
     642                 :            :          */
     643                 :          0 :         r = sd_device_get_sysname(cdev, &bus_id);
     644         [ #  # ]:          0 :         if (r < 0)
     645                 :          0 :                 return r;
     646                 :            : 
     647                 :            :         /* Check the length of the bus-ID. Rely on the fact that the kernel provides a correct bus-ID;
     648                 :            :          * alternatively, improve this check and parse and verify each bus-ID part...
     649                 :            :          */
     650                 :          0 :         bus_id_len = strlen(bus_id);
     651   [ #  #  #  # ]:          0 :         if (!IN_SET(bus_id_len, 8, 9))
     652                 :          0 :                 return -EINVAL;
     653                 :            : 
     654                 :            :         /* Strip leading zeros from the bus id for aesthetic purposes. This
     655                 :            :          * keeps the ccw names stable, yet much shorter in general case of
     656                 :            :          * bus_id 0.0.0600 -> 600. This is similar to e.g. how PCI domain is
     657                 :            :          * not prepended when it is zero. Preserve the last 0 for 0.0.0000.
     658                 :            :          */
     659                 :          0 :         bus_id_start = strspn(bus_id, ".0");
     660         [ #  # ]:          0 :         bus_id += bus_id_start < bus_id_len ? bus_id_start : bus_id_len - 1;
     661                 :            : 
     662                 :            :         /* Store the CCW bus-ID for use as network device name */
     663         [ #  # ]:          0 :         if (snprintf_ok(names->ccw_busid, sizeof(names->ccw_busid), "c%s", bus_id))
     664                 :          0 :                 names->type = NET_CCW;
     665                 :            : 
     666                 :          0 :         return 0;
     667                 :            : }
     668                 :            : 
     669                 :          0 : static int names_mac(sd_device *dev, struct netnames *names) {
     670                 :            :         const char *s;
     671                 :            :         unsigned long i;
     672                 :            :         unsigned a1, a2, a3, a4, a5, a6;
     673                 :            :         int r;
     674                 :            : 
     675                 :            :         /* Some kinds of devices tend to have hardware addresses
     676                 :            :          * that are impossible to use in an iface name.
     677                 :            :          */
     678                 :          0 :         r = sd_device_get_sysattr_value(dev, "type", &s);
     679         [ #  # ]:          0 :         if (r < 0)
     680                 :          0 :                 return r;
     681                 :            : 
     682                 :          0 :         i = strtoul(s, NULL, 0);
     683         [ #  # ]:          0 :         switch (i) {
     684                 :            :         /* The persistent part of a hardware address of an InfiniBand NIC
     685                 :            :          * is 8 bytes long. We cannot fit this much in an iface name.
     686                 :            :          */
     687                 :          0 :         case ARPHRD_INFINIBAND:
     688                 :          0 :                 return -EINVAL;
     689                 :          0 :         default:
     690                 :          0 :                 break;
     691                 :            :         }
     692                 :            : 
     693                 :            :         /* check for NET_ADDR_PERM, skip random MAC addresses */
     694                 :          0 :         r = sd_device_get_sysattr_value(dev, "addr_assign_type", &s);
     695         [ #  # ]:          0 :         if (r < 0)
     696                 :          0 :                 return r;
     697                 :          0 :         i = strtoul(s, NULL, 0);
     698         [ #  # ]:          0 :         if (i != 0)
     699                 :          0 :                 return 0;
     700                 :            : 
     701                 :          0 :         r = sd_device_get_sysattr_value(dev, "address", &s);
     702         [ #  # ]:          0 :         if (r < 0)
     703                 :          0 :                 return r;
     704         [ #  # ]:          0 :         if (sscanf(s, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6)
     705                 :          0 :                 return -EINVAL;
     706                 :            : 
     707                 :            :         /* skip empty MAC addresses */
     708         [ #  # ]:          0 :         if (a1 + a2 + a3 + a4 + a5 + a6 == 0)
     709                 :          0 :                 return -EINVAL;
     710                 :            : 
     711                 :          0 :         names->mac[0] = a1;
     712                 :          0 :         names->mac[1] = a2;
     713                 :          0 :         names->mac[2] = a3;
     714                 :          0 :         names->mac[3] = a4;
     715                 :          0 :         names->mac[4] = a5;
     716                 :          0 :         names->mac[5] = a6;
     717                 :          0 :         names->mac_valid = true;
     718                 :          0 :         return 0;
     719                 :            : }
     720                 :            : 
     721                 :          0 : static int names_netdevsim(sd_device *dev, struct netnames *names) {
     722                 :            :         sd_device *netdevsimdev;
     723                 :            :         const char *sysname;
     724                 :            :         unsigned addr;
     725                 :          0 :         const char *port_name = NULL;
     726                 :            :         int r;
     727                 :            :         bool ok;
     728                 :            : 
     729         [ #  # ]:          0 :         if (!naming_scheme_has(NAMING_NETDEVSIM))
     730                 :          0 :                 return 0;
     731                 :            : 
     732         [ #  # ]:          0 :         assert(dev);
     733         [ #  # ]:          0 :         assert(names);
     734                 :            : 
     735                 :          0 :         r = sd_device_get_parent_with_subsystem_devtype(dev, "netdevsim", NULL, &netdevsimdev);
     736         [ #  # ]:          0 :         if (r < 0)
     737                 :          0 :                 return r;
     738                 :          0 :         r = sd_device_get_sysname(netdevsimdev, &sysname);
     739         [ #  # ]:          0 :         if (r < 0)
     740                 :          0 :                 return r;
     741                 :            : 
     742         [ #  # ]:          0 :         if (sscanf(sysname, "netdevsim%u", &addr) != 1)
     743                 :          0 :                 return -EINVAL;
     744                 :            : 
     745                 :          0 :         r = sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
     746         [ #  # ]:          0 :         if (r < 0)
     747                 :          0 :                 return r;
     748                 :            : 
     749                 :          0 :         ok = snprintf_ok(names->netdevsim_path, sizeof(names->netdevsim_path), "i%un%s", addr, port_name);
     750         [ #  # ]:          0 :         if (!ok)
     751                 :          0 :                 return -ENOBUFS;
     752                 :            : 
     753                 :          0 :         names->type = NET_NETDEVSIM;
     754                 :            : 
     755                 :          0 :         return 0;
     756                 :            : }
     757                 :            : 
     758                 :            : /* IEEE Organizationally Unique Identifier vendor string */
     759                 :          0 : static int ieee_oui(sd_device *dev, struct netnames *names, bool test) {
     760                 :            :         char str[32];
     761                 :            : 
     762         [ #  # ]:          0 :         if (!names->mac_valid)
     763                 :          0 :                 return -ENOENT;
     764                 :            :         /* skip commonly misused 00:00:00 (Xerox) prefix */
     765         [ #  # ]:          0 :         if (memcmp(names->mac, "\0\0\0", 3) == 0)
     766                 :          0 :                 return -EINVAL;
     767         [ #  # ]:          0 :         xsprintf(str, "OUI:%02X%02X%02X%02X%02X%02X", names->mac[0],
     768                 :            :                  names->mac[1], names->mac[2], names->mac[3], names->mac[4],
     769                 :            :                  names->mac[5]);
     770                 :          0 :         udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test);
     771                 :          0 :         return 0;
     772                 :            : }
     773                 :            : 
     774                 :          0 : static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
     775                 :          0 :         const char *s, *p, *devtype, *prefix = "en";
     776                 :          0 :         struct netnames names = {};
     777                 :            :         unsigned long i;
     778                 :            :         int r;
     779                 :            : 
     780                 :            :         /* handle only ARPHRD_ETHER, ARPHRD_SLIP and ARPHRD_INFINIBAND devices */
     781                 :          0 :         r = sd_device_get_sysattr_value(dev, "type", &s);
     782         [ #  # ]:          0 :         if (r < 0)
     783                 :          0 :                 return r;
     784                 :            : 
     785                 :          0 :         i = strtoul(s, NULL, 0);
     786   [ #  #  #  # ]:          0 :         switch (i) {
     787                 :          0 :         case ARPHRD_ETHER:
     788                 :          0 :                 prefix = "en";
     789                 :          0 :                 break;
     790                 :          0 :         case ARPHRD_INFINIBAND:
     791         [ #  # ]:          0 :                 if (naming_scheme_has(NAMING_INFINIBAND))
     792                 :          0 :                         prefix = "ib";
     793                 :            :                 else
     794                 :          0 :                         return 0;
     795                 :          0 :                 break;
     796                 :          0 :         case ARPHRD_SLIP:
     797                 :          0 :                 prefix = "sl";
     798                 :          0 :                 break;
     799                 :          0 :         default:
     800                 :          0 :                 return 0;
     801                 :            :         }
     802                 :            : 
     803                 :            :         /* skip stacked devices, like VLANs, ... */
     804                 :          0 :         r = sd_device_get_sysattr_value(dev, "ifindex", &s);
     805         [ #  # ]:          0 :         if (r < 0)
     806                 :          0 :                 return r;
     807                 :          0 :         r = sd_device_get_sysattr_value(dev, "iflink", &p);
     808         [ #  # ]:          0 :         if (r < 0)
     809                 :          0 :                 return r;
     810         [ #  # ]:          0 :         if (!streq(s, p))
     811                 :          0 :                 return 0;
     812                 :            : 
     813         [ #  # ]:          0 :         if (sd_device_get_devtype(dev, &devtype) >= 0) {
     814         [ #  # ]:          0 :                 if (streq("wlan", devtype))
     815                 :          0 :                         prefix = "wl";
     816         [ #  # ]:          0 :                 else if (streq("wwan", devtype))
     817                 :          0 :                         prefix = "ww";
     818                 :            :         }
     819                 :            : 
     820                 :          0 :         udev_builtin_add_property(dev, test, "ID_NET_NAMING_SCHEME", naming_scheme()->name);
     821                 :            : 
     822                 :          0 :         r = names_mac(dev, &names);
     823   [ #  #  #  # ]:          0 :         if (r >= 0 && names.mac_valid) {
     824                 :            :                 char str[IFNAMSIZ];
     825                 :            : 
     826         [ #  # ]:          0 :                 xsprintf(str, "%sx%02x%02x%02x%02x%02x%02x", prefix,
     827                 :            :                          names.mac[0], names.mac[1], names.mac[2],
     828                 :            :                          names.mac[3], names.mac[4], names.mac[5]);
     829                 :          0 :                 udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str);
     830                 :            : 
     831                 :          0 :                 ieee_oui(dev, &names, test);
     832                 :            :         }
     833                 :            : 
     834                 :            :         /* get path names for Linux on System z network devices */
     835   [ #  #  #  # ]:          0 :         if (names_ccw(dev, &names) >= 0 && names.type == NET_CCW) {
     836                 :            :                 char str[IFNAMSIZ];
     837                 :            : 
     838         [ #  # ]:          0 :                 if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.ccw_busid))
     839                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
     840                 :          0 :                 return 0;
     841                 :            :         }
     842                 :            : 
     843                 :            :         /* get ibmveth/ibmvnic slot-based names. */
     844   [ #  #  #  # ]:          0 :         if (names_vio(dev, &names) >= 0 && names.type == NET_VIO) {
     845                 :            :                 char str[IFNAMSIZ];
     846                 :            : 
     847         [ #  # ]:          0 :                 if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.vio_slot))
     848                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
     849                 :          0 :                 return 0;
     850                 :            :         }
     851                 :            : 
     852                 :            :         /* get ACPI path names for ARM64 platform devices */
     853   [ #  #  #  # ]:          0 :         if (names_platform(dev, &names, test) >= 0 && names.type == NET_PLATFORM) {
     854                 :            :                 char str[IFNAMSIZ];
     855                 :            : 
     856         [ #  # ]:          0 :                 if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.platform_path))
     857                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
     858                 :          0 :                 return 0;
     859                 :            :         }
     860                 :            : 
     861                 :            :         /* get netdevsim path names */
     862   [ #  #  #  # ]:          0 :         if (names_netdevsim(dev, &names) >= 0 && names.type == NET_NETDEVSIM) {
     863                 :            :                 char str[IFNAMSIZ];
     864                 :            : 
     865         [ #  # ]:          0 :                 if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.netdevsim_path))
     866                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
     867                 :            : 
     868                 :          0 :                 return 0;
     869                 :            :         }
     870                 :            : 
     871                 :            :         /* get PCI based path names, we compose only PCI based paths */
     872         [ #  # ]:          0 :         if (names_pci(dev, &names) < 0)
     873                 :          0 :                 return 0;
     874                 :            : 
     875                 :            :         /* plain PCI device */
     876         [ #  # ]:          0 :         if (names.type == NET_PCI) {
     877                 :            :                 char str[IFNAMSIZ];
     878                 :            : 
     879         [ #  # ]:          0 :                 if (names.pci_onboard[0] &&
     880         [ #  # ]:          0 :                     snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_onboard))
     881                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);
     882                 :            : 
     883         [ #  # ]:          0 :                 if (names.pci_onboard_label &&
     884   [ #  #  #  # ]:          0 :                     snprintf_ok(str, sizeof str, "%s%s",
     885                 :            :                                 naming_scheme_has(NAMING_LABEL_NOPREFIX) ? "" : prefix,
     886                 :            :                                 names.pci_onboard_label))
     887                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str);
     888                 :            : 
     889         [ #  # ]:          0 :                 if (names.pci_path[0] &&
     890         [ #  # ]:          0 :                     snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_path))
     891                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
     892                 :            : 
     893         [ #  # ]:          0 :                 if (names.pci_slot[0] &&
     894         [ #  # ]:          0 :                     snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_slot))
     895                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
     896                 :          0 :                 return 0;
     897                 :            :         }
     898                 :            : 
     899                 :            :         /* USB device */
     900   [ #  #  #  # ]:          0 :         if (names_usb(dev, &names) >= 0 && names.type == NET_USB) {
     901                 :            :                 char str[IFNAMSIZ];
     902                 :            : 
     903         [ #  # ]:          0 :                 if (names.pci_path[0] &&
     904         [ #  # ]:          0 :                     snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_path, names.usb_ports))
     905                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
     906                 :            : 
     907         [ #  # ]:          0 :                 if (names.pci_slot[0] &&
     908         [ #  # ]:          0 :                     snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_slot, names.usb_ports))
     909                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
     910                 :          0 :                 return 0;
     911                 :            :         }
     912                 :            : 
     913                 :            :         /* Broadcom bus */
     914   [ #  #  #  # ]:          0 :         if (names_bcma(dev, &names) >= 0 && names.type == NET_BCMA) {
     915                 :            :                 char str[IFNAMSIZ];
     916                 :            : 
     917         [ #  # ]:          0 :                 if (names.pci_path[0] &&
     918         [ #  # ]:          0 :                     snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_path, names.bcma_core))
     919                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
     920                 :            : 
     921         [ #  # ]:          0 :                 if (names.pci_slot[0] &&
     922         [ #  # ]:          0 :                     snprintf(str, sizeof str, "%s%s%s", prefix, names.pci_slot, names.bcma_core))
     923                 :          0 :                         udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
     924                 :          0 :                 return 0;
     925                 :            :         }
     926                 :            : 
     927                 :          0 :         return 0;
     928                 :            : }
     929                 :            : 
     930                 :            : const UdevBuiltin udev_builtin_net_id = {
     931                 :            :         .name = "net_id",
     932                 :            :         .cmd = builtin_net_id,
     933                 :            :         .help = "Network device properties",
     934                 :            : };

Generated by: LCOV version 1.14